Project tutorial
Temperature Controled Charcoal Smoker

Temperature Controled Charcoal Smoker © GPL3+

Use an Arduino MKR1000 to maintain a constant temperature in a charcoal smoker and allow monitoring over Wifi,

  • 15,937 views
  • 7 comments
  • 21 respects

Components and supplies

Apps and online services

About this project

The Backstory

Most serious BBQ smokers know that the best flavor comes from using charcoal to heat their smokers. Propane and electric smokers have better temperature control, but lose that charcoal flavor. As a heat source, charcoal can be a pain. You need to constantly monitor the temperature, adjust the vents to try to get the right temperature, and have to play with it a few times to get it just right. Then, you've got to keep doing that every half hour as the charcoal level changes in the smoker. Wouldn't it be great to just sit back on your couch, enjoying your favorite cold beverage and sporting event on the TV while letting the smoker do its thing?

The Project

Create a controller that monitors the temperature in the smoker and adjusts the airflow to the charcoal to maintain the correct temperature. Also, provide a way to monitor the temperatures of both the smoker and meat probes remotely. This is based on the soon to be released Arduino MKR1000 with built in Wi-Fi and support for charging a LiPo battery.

The Hardware

The temperature in the smoke is monitored using a 100K NTC Thermistor in a voltage divider connected to one of the analog inputs of the MKR. This thermistor was chosen as it is used for Prusa RepRab hot ends in 3D printers, so they are widely available and inexpensive. The can be bought already soldered to high temperature silicon insulated wire to make the ideal temperature probe. The thermistor is inserted in a length thin (1/4 inch or smaller) stainless steel tube for physical protection with one end crimped off to close it and the wires secured at the other end using heat shrink.

The voltage divider uses a 10K resister as the other half of the voltage divider. This value was chosen as it is close to the resistance of the 100K NTC thermistor at typical smoker temperatures (225 F). This gives a good range for temperature measurement, providing readings from about 50 F to over 300 F with reasonable granularity.

A0 is used to monitor the temperature.  It uses a shorter probe that is placed on the grate inside the smoker. The other analog pins can be used to create more thermistor probes and voltage dividers to be inserted into the meat being smoked to monitor the internal temperature of the meat to know when it is cooked.

On the other side, a small blower is attached to the vent on the smoker. A small stainless steel dog food dish is attached over the vent on the smoker and the blower is attached to hole in the bottom of the dish. This serves two functions, first to completely cover the air vent, and secondly to provide some thermal isolation between the body of the smoker and the blower.  The blower is controlled using a N channel MOSFET. This could be directly wired, but for ease of construction, a MOSFET model was used. The gate on the MOSFET is connected to the Arduino's digital pin

The Build

For the first implementation, everything is done on a breadboard to keep things simple. The thermistor bridge(s) are easy to wire, the 10K resistor from Vcc (3.3V for the MKR) to one side of the thermistor and the other side goes to ground. Connect a jumper between the center of the bridge and an analog pin on the MKR. Cut a length of tubing to use for the probe, Crimp one end in a vice to seal it. Pliers are then used to fold the corners of the crimped tubing to make a sharper point. slide the thermistor in the tubing till it reaches the end. Slip a piece of shrink wrap over the other end and wires. Apply heat to shrink it down and secure the wires.

The blower side is almost as simple. Secure the leads to the blower to the output terminal block on the MOSFET module observing polarity. Attach your LiPo battery pack and the wires from a JST plug to the power terminal block on the MOSFET module, again observing polarity. Plug the JST plug into JST jack for the battery charger on the MKR. Run three jumpers for Vcc, ground, and the control wire from the pins on the MOSFET board to the MKR.  A 10,000 mAh battery was used to provide plenty of battery life with the blower.

On the breadboard, a couple of items were added that are not in the schematic. There's a 10K variable resistor which can be used to generate voltages to test the sketch by switching one of the jumpers from a thermistor to the slider on the variable resistor (the ends of the resister are connected to Vcc and ground). There's also an LED with a 330 Ohm current limiting resister connected to output pin 0 to indicate when the sketch switches the fan on and off.

The Software

There are two pieces of software involved. One is the sketch to control the Arduino and the other is a Universal Windows App, so the smoker can be monitored remotely on any Windows 10 device.

The sketch is largely based on a Wi-Fi server sketch in Simon Monks' book "Programming Arduino Next Steps: Going Further with Sketches" (http://www.amazon.com/Programming-Arduino-Next-Steps-Sketches/dp/0071830251/ref=sr_1_6?ie=UTF8&qid=1459448622&sr=8-6).

It basically creates a simple Web server that serves up one page showing the measured temperatures and allows the target temperature for the smoker to be set. Initialization consists of setting up the Wi-Fi adapter and assigning a fixed IP address in order to know what to connect to when not connected to a computer to see a DHCP assigned address. Pin 0 is set to output. In the loop, it checks if there is a client trying to connect, and if so then serves up the web page.  If there is a request, it also checks if it includes the parameter in the url to set the target temperature. It then checks the temperature of the smoker and turns the blower on if it is below target temperature and off if it is above.

Measuring temperature using a thermistor in the voltage divider is relatively simple. First from the analog input reading, we can determine the voltage drop over the fixed resistor (The reading if the fixed resistor is connected to ground, Vcc - the reading if it is connected to Vcc) We then use Ohms Law (V=IR) to compute the current (I) through the resistor (I =V/R) Since the same current flows through the thermistor, we use ohms law again to compute the resistance of the thermistor. R = V/I where V is the voltage drop of the thermistor (the analog input reading or Vcc - the reading depending on which side of the divider it's on) and I is the current we just computed. Using R we can plug it into the Thermistor Beta equation:

1/T = 1/T0 + 1/Beta * ln(R/R0)

Where R0 is the Resistance of the thermistor at T0

(Note, all temperatures are in Kelvin so make sure to take that into account)

Serving up the simple HTML web page basically involves Sending out the html header blocks and html formatting codes around the measured temperatures. It also includes an input for the target temperature and a button to include it in a request back to the server.

The Windows Universal App

This is the piece that allows you to sit back and relax knowing your smoker is churning out some of the best smoked beef brisket west of the Pecos (or whatever river of your choice). It periodically loads the web page from the smoker, parses out the temperatures and displays them. It also allows you to set the target temperature for the smoker.

Code for both the sketch and Universal app are available in the GitHub repository listed below.

Code

Smoker Controller SketchArduino
// sketch_12_04_server_wifi

#include <SPI.h>
#include <WiFi101.h>

char ssid[] = "BeeBar2";  // your network SSID (name)
char pass[] = "9254582716";     // your network password

WiFiServer server(80);
WiFiClient client;

const int numPins = 10;
int pins[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int pinState[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
char line1[100];
char buffer[100];

IPAddress server_IP(192,168,123,90) ;

float targetTemperature = 225;
float smokerTemperature = 225;
float v0;

void setup()
{
  Serial.begin(9600);
  while (!Serial) {}; // Leonardo needs this
  for (int i = 0; i < numPins; i++)
  {
    pinMode(pins[i], OUTPUT);
  }
  // change the ADC resolution to 12 bits
  analogReadResolution(12);

  if (WiFi.begin(ssid, pass))
  {
    WiFi.config(server_IP);
    printWifiStatus();
    //Serial.print("Point your Browser at: http://");
    //Serial.println(WiFi.localIP());
  }
  else
  {
    Serial.println("Could not connect to network");
  }
  server.begin();
}

void loop()
{
  client = server.available();
  if (client)
  {
    if (client.connected())
    {
      Serial.print("Request Received: ");
      Serial.println(line1);

      readHeader();
      if (! pageNameIs("/"))
      {
        Serial.print("Invalid Page Requested: ");
        Serial.println(line1);
        client.stop();
        return;
      }
      readTargetTempParam();
      client.println("HTTP/1.1 200 OK\nContent-Type: text/html\n");
      sendBody();
      delay(1);
      client.stop();
    }
    else
    {
      Serial.println("No Client connected ");
    }
  }
  int reading = analogRead(0);
  v0 = (float) reading / 1241.0;
  smokerTemperature = ThermisterTemp(v0, 100000, 10000, 3950, 25);
  digitalWrite(0, smokerTemperature<targetTemperature);
}

void sendBody()
{
  client.println("<html><body>");
  sendAnalogReadings();
  client.println("<form method='GET'>");
  client.print("\n<h1>Target Temperature:</h1> <input type='number' value='");
  client.print(targetTemperature);
  client.println("' name='t'><br>");
  client.println("<input type='submit' value='Update'/>\n</form>\n</body></html>");
}

void sendAnalogReadings()
{
  client.println("<h1>Temperatures</h1>\n<table border='1'>");
  
  Serial.print("Pin(");Serial.print(0);Serial.print("): V=");Serial.print(v0);Serial.print(" Temperature="); Serial.println(smokerTemperature);
 
  client.print("<tr><td>Smoker ");
  client.print("</td><td>"); client.print(smokerTemperature);
  client.println(" F</td></tr>");
    
  for (int i = 1; i < 7; i++)
  {
    int reading = analogRead(i);
    if (reading > 0)
    {
      float v = (float) reading / 1241.0;
      float T = ThermisterTemp(v, 100000, 10000, 3950, 25);
      Serial.print("Pin(");Serial.print(i);Serial.print("): ");Serial.print(reading);Serial.print("V=");Serial.print(v);Serial.print(" Temperature="); Serial.println(T);
      client.print("<tr><td>Probe "); client.print(i);
      client.print("</td><td>"); client.print(T);
      client.println(" F</td></tr>");
    }
  }
  client.println("</table>");
}

void readHeader()
{
  readRequestLine(line1);
  while (readRequestLine(buffer) > 1 && buffer[0] != '\n') {}
}

int readRequestLine(char *line)
{
  char ch;
  int i = 0;
  while (ch != '\n' && i < 100 && client.available())
  {
    if (client.available())
    {
      ch = client.read();
      line[i] = ch;
      i ++;
    }
  }
  line[i] = '\0';
  return i;
}

boolean pageNameIs(char* name)
{
  // page name starts at char pos 4
  // ends with space
  int i = 4;
  char ch = line1[i];
  while (ch != ' ' && ch != '\n' && ch != '?')
  {
    if (name[i - 4] != line1[i])
    {
      return false;
    }
    i++;
    ch = line1[i];
  }
  return true;
}

float readTargetTempParam()
{
  //Serial.print("parsing targetTemperature");Serial.println(line1);
  
  int len = strlen(line1);
  for (int i = 0; i < len; i++)
  {
    if (line1[i] == 't' && line1[i + 1] == '=')
    {
      float val = 0;
      for (int j=i+2; j< len; j++)
      {
        if (isDigit(line1[j]))
        {
          //Serial.print(line1[j]);
          val *= 10;
          val += (int)line1[j]-'0';
        }
        else
        {
          break;
        }
      }
      //Serial.print(" ");
      targetTemperature = val;
      //Serial.print("targetTemperature = ");Serial.println(val);
      return val;
    }
  }
  return -1;
}

void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

float ThermisterTemp(float Vtherm, int R0therm, int Rfixed, int Beta, int T0)
{
  // Current throught the 2 rsiteres is the same, so compute the current 
  // throught the fixed resiter using Ohms law I = V / R
  // The voltage drop over the fixed resister is Vcc (3.3V) - Vtherm
  double I = (3.3 - Vtherm) / Rfixed;
  //Serial.print("I=");Serial.print(I,12);Serial.print(" ");
  
  // Use ohms law to cacultate the resitance of the thermister R = V / I
  double Rtherm = Vtherm / I;
  //Serial.print("Rtherm=");Serial.print(Rtherm);Serial.print(" ");

  // Use the Beta eaquation to calulate the tempuratue in C
  // 1/T = (1/Beta)*ln(Rtherm/R0therm) + (1/T0)
  // (Steinhart-Hart equatin is more accutrate, but I only have the Beta constant 
  // for my thermister.

  // All temperatres are in Kelvin
  T0 += 273.15;
  
  double T = 1.0/( (1.0/((double)Beta))*log((Rtherm)/((double)R0therm)) + (1.0/((double)T0)) );
  //Serial.print("T=");Serial.print(T);Serial.print(" ");

  //Serial.println("");
  // convert to farenheit for us ignorant Americans
  return (float) ((9*(T-273.15))/5)+32;
}
Smoker Controller Sketch & Universal App

Schematics

Schematic
The Mrkr1000 is represented by a Arduino Nano
Smoker.fzz
Schematic Diagram
The Mrkr1000 is represented by a Arduino Nano
The Fritzing tool did not have the part.
Smokerschematic

Comments

Similar projects you might like

Azure Stream Analytics saving lives!

Project tutorial by Asad Zia

  • 6,415 views
  • 3 comments
  • 26 respects

DHT11 /DHT22 Temperature Sensor

Project tutorial by Daniel Porrey

  • 82,654 views
  • 106 comments
  • 133 respects

Arduino Control AC Water Heater temperature

Project tutorial by Mohannad Rawashdeh

  • 9,040 views
  • 0 comments
  • 6 respects

Project KOOL: Temperature and Humidity Remote Monitoring

Project tutorial by vincent wong

  • 4,876 views
  • 1 comment
  • 12 respects

Temperature and Humidity Data Logger

Project tutorial by Wimpie van den Berg

  • 23,407 views
  • 2 comments
  • 22 respects

Beautifully Finished Humidity and Temperature Sensor

Project tutorial by Wicked Makers

  • 16,864 views
  • 21 comments
  • 135 respects
Add projectSign up / Login