Arduino+XBee Dual-stage Temp Controller

Homebrew Talk - Beer, Wine, Mead, & Cider Brewing Discussion Forum

Help Support Homebrew Talk - Beer, Wine, Mead, & Cider Brewing Discussion Forum:

This site may earn a commission from merchant affiliate links, including eBay, Amazon, and others.
I just got my Arduino yesterday and am working on a similar project. Cant wait to start using the web to ferment... I will be using PHP and a MYSQL database work the numbers. I will post my code to help others out because I would never have learned code without the help of the open-source coders.
 
Chuginator said:
Thanks, man! Sorry, I tend to get way too technical. Simply put, it's a home-brew temp controller for my fermentation fridge, with the added benefit that my computer can control and log data remotely from it.

I'm pretty impressed with the range on the XBee's. Even within that enclosure, I'm getting updates once a minute reliably, from about 100' and going through three walls. I wish they were a little cheaper (they're about $20 each), but I ask myself if it's worth $20 to keep an eye on things remotely, and it is to me. Particularly in the test phase to see how well the temp control code is performing in reality, and how my free fridge is keeping up (or not).

LOL. Yeah I got that part. You're right it was very technical.

I've read about other examples of this on here. Although I don't think any are quite this extensive. I have a root cellar (unfinished by my dad from before I could remember) at the edge of my yard that I have aspirations of turning into a fermentation/lagering/aging/long term storage facility. The concrete pad that is the roof is perfect for a brew shop also. The capacity to monitor the different ferm/lagering chambers and beers remotely gets me all hot and bothered.
 
LOL. Yeah I got that part. You're right it was very technical.

I've read about other examples of this on here. Although I don't think any are quite this extensive. I have a root cellar (unfinished by my dad from before I could remember) at the edge of my yard that I have aspirations of turning into a fermentation/lagering/aging/long term storage facility. The concrete pad that is the roof is perfect for a brew shop also. The capacity to monitor the different ferm/lagering chambers and beers remotely gets me all hot and bothered.

I hear ya. That sounds like a cool place (literally!) to ferment beer in!

If you're going to monitor more than three temperatures, get yourself an Arduino Mega. Fortunately I had just enough inputs with the Arduino Uno to fulfill my requirements.

I really wish XBee's were a little easier to interface with the Arduino. I had to do the same thing with this project that I did my sprinkler controller - got the XBee from DigiKey, the breakout board and 2mm headers from SparkFun, the Arduino, proto shield, headers, LCD and most everything else electronic-wise from AdaFruit. It'd be mondo if someone came out with an Arduino that's already XBee capable. It'll probably happen some day (or maybe it already has?), but until then, get your soldering iron out. ;)

Again, if anyone wants to attempt this and you have hangups on code, speak up and I can post routines for you or answer questions. It's certainly not rocket science and most of the code to do this is smeared all over the Internet already. The PC-side software can also be done much simpler than my arrangement.
 
just FYI... if you are using 1-wire temp sensors like the popular DS18S20, you only need one digital input on the arduino even for 100+ sensors. the data pin on each sensor can be daisy chained, and each sensor has a unique hardware identifier key to differentiate them in code.
 
just FYI... if you are using 1-wire temp sensors like the popular DS18S20, you only need one digital input on the arduino even for 100+ sensors. the data pin on each sensor can be daisy chained, and each sensor has a unique hardware identifier key to differentiate them in code.

Yep - good point! :mug:
 
just FYI... if you are using 1-wire temp sensors like the popular DS18S20, you only need one digital input on the arduino even for 100+ sensors. the data pin on each sensor can be daisy chained, and each sensor has a unique hardware identifier key to differentiate them in code.

And using the Serial Backpack from Sparkfun will free up a bunch of additional pins if you are that tight. That's what I did. DS18B20's and the backpack and I only used 5 pins (plus Tx, 5v, and GND). I don't know if the backpack will work with your fancy multi-colored LCD, however.
 
For the cost of the backpack you could just buy a serial LCD screen on ebay. Good points though using serial and 1 wire. I am also in the process of building a similar project. I had 2 LCD screens that were bad, but my third was a charm. Haven't had the joy of working on the xbee. I'm considering going wifi instead. Do you have any plans to setup your project to send tweets?
 
I'm using PHP and JPGraph. The MySQL query I'm using is:

$query = "SELECT unix_timestamp(datetime) as datetime, onoff, mode, setpoint, ambair, ambfridgeair, carboy FROM log WHERE datetime >= date_sub(curdate(), interval 6 hour) ORDER BY datetime ASC";

This pulls out the data (which is being logged once per minute) for the last six hours, then it's pumped through JPGraph.

Thanks for the recommendation. I just assumed everyone uses processing, for all these arduino projects, but I have trouble finding the time to learn a new language.

I am currently using the google charts API, but will have a closer look at JPGraph as well. It was becoming apparent that if I sample 1 time per minute, over a 31 calendar day month, thats about 45,000 readings per sensor.

What I'd like to find, is a chart API that works like google's stock market history (ex: http://www.google.com/finance?q=INDEXDJX:.DJI). I think it would be really slick!
 
Thanks for the recommendation. I just assumed everyone uses processing, for all these arduino projects, but I have trouble finding the time to learn a new language.

I am currently using the google charts API, but will have a closer look at JPGraph as well. It was becoming apparent that if I sample 1 time per minute, over a 31 calendar day month, thats about 45,000 readings per sensor.

What I'd like to find, is a chart API that works like google's stock market history (ex: http://www.google.com/finance?q=INDEXDJX:.DJI). I think it would be really slick!

Never used Processing, but have heard of it. Not worth my time personally. Would rather have real data in a real database.

45K readings per sensor is nothing. These days, disk is cheap. CPU is cheap.
 
Thanks for the recommendation. I just assumed everyone uses processing, for all these arduino projects, but I have trouble finding the time to learn a new language.

I am currently using the google charts API, but will have a closer look at JPGraph as well. It was becoming apparent that if I sample 1 time per minute, over a 31 calendar day month, thats about 45,000 readings per sensor.

What I'd like to find, is a chart API that works like google's stock market history (ex: http://www.google.com/finance?q=INDEXDJX:.DJI). I think it would be really slick!

Have you tried Google's Annotated Time Line?

I've used it for a lot of projects. It works for any time frame, not just days, and it's the closest they have to the stock chart. You can play with it in Google Spreadsheets.
 
Hey Chug, mind posting a link to the version of Xbees you're using?
I've got a basic system running. A few one-wire temp sensors running into an Arduino with a 20x4 LCD showing the current temps. I'd love to get some wireless going.
Kinda tempted to see if I can convince the wife to let me take the Xbee class at Sparkfun this December...
 
Hey Chug, mind posting a link to the version of Xbees you're using?
I've got a basic system running. A few one-wire temp sensors running into an Arduino with a 20x4 LCD showing the current temps. I'd love to get some wireless going.
Kinda tempted to see if I can convince the wife to let me take the Xbee class at Sparkfun this December...

Certainly! I'm using the XB24-Z7WIT-004.

Digi-Key link: Digi-Key - 602-1098-ND (Manufacturer - XB24-Z7WIT-004)

I bought the XBee book put out by O'Reilly, if you're interested.

Amazon.com: Building Wireless Sensor Networks: with ZigBee, XBee, Arduino, and Processing (9780596807733): Robert Faludi: Books
 
Last edited by a moderator:
For anyone that's also using the TMP36-style sensor(s) instead of the DS18S20, make note that the schematic should (but does not) show a connection between the 3.3V pin and AREF. You could leave it out and use the internal 5V ref, but you should have more accurate results by using a 3.3V ref.
 
Chuginator,
I first want to say thanks for posting your build, you've inspired me into the world of arduinos and I love it. I just bought one and have had some fun messing with various tutorials online. I have a question on your temp sensors, I have tied two TMP 36 to different analog pins on my board, but I cannot seem to get accurate temperature readings. Each sensor will fluctuate its reading by +/- 4 C and from what I can tell it seems to be a problem with the arduino. Mind you I am powering via USB only as I don't have a 9V power supply.

How were you able to overcome the fluctuation?
 
Certainly! Glad to be an inspiration! I just hope I'm not steering you down the wrong path with the analog sensors, vs. something like the Dallas 1-wire. You may have better luck with those, I'm not sure. I used one a long time ago interfaced to a serial port on a PC, but never have looked into using them with the Arduino. If you do end up tinkering with them, post back on your results!

One thing that will help your accuracy is to use the 3.3V reference. If you fiddle with this, heed the warning at Arduino - AnalogReference.

If you notice the graph I posted, the values are jumping all over the place - probably similar to what you're experiencing. That's before I slapped myself for not averaging the values more rapidly than I was. More on that below.

One "trick" I'd read about concerns the fact that a single analog-digital converter (ADC) is multiplexed over all of the analog pins, and when you tell the Arduino to change which pin it is to read from, it takes the sensor a little time to change the voltage seen by the ADC. So, in theory, it helps to change the pin (by doing an analogRead() call with the desired pin), wait 10ms, then do another analogRead() call to get the stabilized reading. Something you wouldn't have to do with the Dallas sensors.

In my code I'm doing the pin switch + stabilization, then reading the sensor 20 times (AVGSENSOR = 20) to get an average. After the average value is computed, it does the math to convert the 3.3V referenced value to degrees Fahrenheit, applies a static offset to compensate for inaccuracy, does a sanity check to make sure the value is within 20-100F, and if so, crams it into an array for a running average. I'm doing this once a second and the running average array spans one minute (AVGCOUNT = 60). So the final values I'm using for reference elsewhere in the code are the sum of all values in the running average array, divided by the number of entries. Seems to work pretty well.

I have three sensors, so I stuck them all in close proximity to each other into the center of a glass of ice water along with a thermo-pen and made adjustments to their values until they read 32F. The thermo-pen was to verify that the temperature right where the sensors were was indeed 32F.

Code:
    // Ambient air temperature
    analogRead(PIN_TMP36_AMBAIR);  // Switch pin on ADC
    delay(10);                     // Stabilize
    fAvg = 0;
    for(int i=0; i<AVGSENSOR; i++)
      fAvg += (float)analogRead(PIN_TMP36_AMBAIR);
    fAvg /= AVGSENSOR;
    
    fTmp36Volts = fAvg * 3.3;   // Converting that reading to voltage, using 3.3v reference
    fTmp36Volts /= 1024.0; 
    fTempC = (fTmp36Volts - 0.5) * 100 ;  // Converting from 10mV/degree with 500 mV offset to degrees ((voltage - 500mV) * 100)
    fTempF = (fTempC * 9.0 / 5.0) + 32.0;
    fTempF += 0.6;  // Manual adjustment to match thermo-pen thermometer
    if(fTempF >= 20.0 && fTempF <= 100.0)
      fAmbAirTemps[nArrayIndex] = fTempF;
    fTempTotal = 0;
    nTempCount = 0;
    for(int i=0; i<AVGCOUNT; i++)
    {
      if(fAmbAirTemps[i] != 0)
      {
        fTempTotal += fAmbAirTemps[i];
        nTempCount++;
      }
    }
    gfAvgAmbAirTemp = fTempTotal / (float)nTempCount;
 
The multiple readings is key, and I actually just dump the values of the first couple until the reference voltage stabilizes.

The other thing to consider is whether your line is properly insulated against noise. I had an analog sensor on my temp controller for a while, but it was giving me erratic readings. I couldn't figure out why, until I realized that it was going wonky every time my neighbor turned on his microwave. The problem went away as soon as I shielded things properly

But, +1 on the digital 1-Wire sensors. They're a touch more complicated to code for, but much easier to power properly.
 
MalFet, very good point on shielding - I'm also seeing a little weirdness when the heat tape circuit is engaged; all of the sensors fluctuate down a bit, and when it's disengaged, they fluctuate back up. Not enough to affect the unit's performance, but I just don't like it. This only happens when 110VAC is actually plugged in, so I know it's not from just activating the relay. I'm thinking I might have to try some decoupling caps on the analog input lines, or maybe even move to the Dallas 1-wire sensors. I'm not worried about code complexity, and if those are immune from these strange issues (because they're read digitally), they might be the ticket.

Guess it's time to order a few and get to experimenting with them.
 
Guess it's time to order a few and get to experimenting with them.

I'm sure if I were better with the electricals I could make the analog sensors work just as well as the digital, but since I'm handier with code than with wiring it was a no-brainer for me. People argue that the 1-wire cost more, but it's like $3 vs. $2, so unless you're planning on manufacturing a few thousand of these it's kind of a moot point.

Here's a relevant snippit of code for anyone who needs it:
Code:
#include <OneWire.h>

const int sensorPin = 8;
OneWire tempSensor(sensorPin);
byte addr[8];
float tempC;
int lastTempReadTime = 0;
int sensorPresent;
float calibration = 0.0;

void setup () {
  Serial.begin(9600);
  // setup the temp sensor
  if (!tempSensor.search(addr)) {
    Serial.print("No sensors found.\n");
    tempSensor.reset_search();
    return;
  }

  //send the first reading command
  sensorPresent = tempSensor.reset();
  tempSensor.select(addr);
  tempSensor.write(0x44,1);
}

void loop () {
  int now = millis();
  
  // reset the lastTempReadTime variable in case of millis() overflow (after about 50 days)
  if (now < lastTempReadTime) {
    lastTempReadTime = 0;
  }
  
  //if a second has passed since last reading, take another
  if ((now - lastTempReadTime) > 1000) {
    lastTempReadTime = now;
    
    //*********TEMPERATURE READING*************    
    sensorPresent = tempSensor.reset();
    if (sensorPresent) {
      //poll the sensor
      tempSensor.select(addr);
      tempSensor.write(0xBE);
      
      int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;
      byte i;
      byte data[12];
      
      for (i=0; i<9; i++) {
        data[i] = tempSensor.read();
      }
      
      LowByte = data[0];
      HighByte = data[1];
      TReading = (HighByte << 8) + LowByte;
      SignBit = TReading & 0x8000;
      if (SignBit)
      {
        TReading = (TReading ^ 0xffff) + 1;
      }
      Tc_100 = (6 * TReading) + TReading / 4;
      Whole = Tc_100 / 100;
      Fract = Tc_100 % 100;
      
      //convert readings to a useful format
      tempC = (float)Whole + (float)Fract / 100;
      if (SignBit) { 
        tempC = tempC * -1;
      }
      
      //request the next reading
      tempSensor.reset();
      tempSensor.select(addr);
      tempSensor.write(0x44,1);
    }
    Serial.println(tempC + calibration);
  }

  delay(50);
}


It reads ºC, but it should be trivial enough to convert that over to ºF. Credit for the code goes to some tutorial on the Arduino website that I can't find anymore, but I've futzed with it enough that any bugs are likely mine.
 
I was still having the same problem using the 3.3V option as well.

I suspect my problem is the frequency of readings per cycle, I was merely taking one per second or one per minute and it seems that the averaging of multiple per second would give better averages. I'll give it a shot, hopefully tonight.

As for shielding, I've read that you can install a 0.1uF ceramic capacitor across the TMP36 to reduce radio interference (look up the TMP35/36/37 datasheet).
 
New question, if you're logging the temperature, are you logging based on a date and time? Since the arduino does not have a "clock," are you time stamping the readings on the computer side instead of the arduino?

Lastly, do the xbee's act as a wireless usb cable?
 
Hi Matt,

Yes, the date/time is computer-side. When the packet comes in from the XBee, the PHP script just takes the current time and sticks it in the database along with the data.

XBees plug into your PC via a USB cable (FTDI cable), and appear to your OS as a serial port. So, think more like a modem.

I'd highly recommend "Wireless Sensor Networks" by O'Reilly/Robert Faludi. He really takes you by the hand and guides you through the nitty gritty of XBees.
 
I'm fermenting an EdWort IPA and realized that I could use SQL to compute how much I'm spending on energy for the heat tape. 53 cents so far! By the time it's finished, I might have a dollar in it. ;)

fermtemp_ipa.png
 
Back
Top