Wednesday, February 13, 2013

Arduino Real Time Fermentation Temperature Monitoring For Cheap!

So this will be my first real big blog post, and it will be discussing the creation of an automated Arduino based fermentation monitoring system that can be built for around $60-70 USD.

It makes use of the Arduino, an Ethernet shield, and the free COSM service that  we will push our temperature data too for easily web accessible graphing and monitoring.

At the end of this project you will have a project that should output the data to COSM and be capable of creating graphs like this real time COSM graph of my Fermentation and Ambient temperatures. COSM is a very powerful tool for free, you can use it to get real time data of your temperatures anywhere you have internet access, and can even set up triggers to tweet/email you when certain things happen.  For example i have it setup to email me if my fermentation temperatures ever gets outside the optimum range for the yeast I am using, which allows me to fix the problem ASAP.
Also side note, it should tweet/email me should my house catch fire and the ambient gets greater than 110!

Note: This is REAL time, the image is built by COSM when you request it.  The image you are seeing is  what my setup is reading as of when you loaded this web page and the image loaded.  If you reload the page it will give you a new graph with the updated data.  The graphs are currently showing the last 24 hour period.  There may or may not be some dips or other weird values showing as its not hooked up if i am not brewing.

You get most of the  data from going to the actual feed below, but can also  have it export some pretty nifty graphs to see long term graphs at a glance.

This is the feed
https://cosm.com/feeds/83208


Equipment Needed

  • Arduino Uno
  • Wiznet 5100 Ethernet Shield
  • 2 x DS18B20 Temperature Sensors
  • Wire
  • Solder
  • Soldering Iron
  • 2 x 4.7K Resistors
  • 5V Power Supply OR Smart Phone USB Wall Charger(come with most smart phones now)


It should be noted that you can set this up with a single DS18B20 for fermentation if you are not interested in ambient or  another sensor, so adjust your  quantities of the sensors and resistors above accordingly.

A good place to get the UNO and Wiznet  Ethernet shield is DealExtreme, for those not familiar with it, they produce cheap Chinese knockoffs of stuff.  But because Arduino is an open source project revolving around a  single chip, there should be no fear in buying from them.  The only downside is it can take upwards of 3-4+ weeks from ordering to get your products in the US.  Take that into consideration, you can get the Uno and Wiznet Ethernet shield from other outlets, but at a much higher cost.  Some people may be against the idea of supporting Chinese manufacturing, or just don't want to wait over a month to get everything...just make sure you get the Wiznet 5100 and not another Ethernet shield or the code here probably wont work.

Arduino UNO - $15.20


Wiznet 5100 Ethernet Shield - $13.99



2 x Maxim DS18B20+ Temperature Sensors - ~$2.50 each. 


You can find these at sites like Digikey or other electronics stores online, hunt around and you can find them at decent rates.  I bought a bundle of 10 off Ebay for $20 dollars.  Can also be bought if you go through DealExtreme.

Wire

I bought some cheap 4 wire flexible thermostat wire from Lowe's for 33c/foot.  Its nice and thin and will fit down a thermowell but yet remain flexible...you can use any wiring you want as long as it will fit in your thermowell.  Home phone wiring may be good since its flexible and fairly narrow, some Ethernet cables may work as well if thin  enough, but again it needs to be able to fit down your thermowell.  You only need 3 wires, so i just cut one(the white one) off.

Thermowell - $14

You can use any you want, just make sure its not too long to fit into your bucket or carboy but to get a fair ways into your wort when its at the 5G marker.  This one ended up actually being too tall for my 8 gallon bucket, so mine is just JBWeld'd in the bucket lid with a few inches out the top of the bucket.  I'd prefer to have to have it flush but whatever works!


Food Safe  Heat Shrink Tubing - $3

Another option besides using a thermowell is to use some food safe heat shrink tubing, and to wrap your sensor in it.  I personally havent tried this, but someone commented on it on Reddit and i dont see why it wouldnt work.  Would likely work best if you could source one of the stainless steel caps that Adafruit uses on their premade DS18B20 probes.


4.7k Resistor - Cheap?

The DS18B20's require that you have a 4.7k resistor between the Data  and Power pins in order to function.

5V Power supply $1-2

$1-2 dollars at any Goodwill/Salvation army, free if you have extra wall warts laying around that are 5V. 
Phone charger USB connectors work as well, such as the standard one that comes with the iPhone or the Androids



The USB connectors allow you to plug right into the USB port of the Arduino to get power.  Otherwise for the 5v connector you need to plug in the jack, or cut the supply and solder it directly into the 5V and Ground connections on the Arduino, this allows you to pass their voltage regulator which IMO gets too hot for my liking.

Build

Start by wiring up the DS18B0's to your length of Thermostat or other wiring.  Below is a crude circuit diagram of how it should all be hooked up.



You need to wire your 4.7k resistor across the Data and Voltage pins of the Arduino.  In this case if you are using two sensors, the easiest way is to just solder the 4.7k resistor across the pins directly on the Arduino on the bottom side of the board.  You can also directly solder your wires  to the bottom if you want a more permanent attachment than plugging it in to the headers, which i had problems with falling out with just a slight bump from a cat or vacuum.

Because the DS18B20's use OneWire, you need to ensure that both of your 'sensor cables' are soldered together in some fashion.  The Gnd to Gnd, Power to Power, and Data to data.  I found just twisting the  two ends together  with a third piece of wire(thats going to plug into the Arduino) and soldering them together worked quite well.  You could probably even get away with cable twist connectors if your wire gauge is thick enough.  Once you have the cables with sensors on them, its a good idea to somehow protect the DS18B20 leads so they dont touch.  I found using a bit of hot glue works great, not to mention if you coat the sensor itself in a small layer of hot glue you can essentially make it water proof.  Just dont put so much on you cant get it into your thermowell, ask me how i know!

Update 3/3/13
I  recently have redone my setup a bit to make it a bit more 'professional' at the end.   I have wired my two sensors up to a  single cat5e cable(pins 1-6), and then wired my arduino with a single 4.7k resistor across Digital 3 and 5V with wires then being direct soldered to the arduino and hooked up to a Cat5E Wall jack.
The goal is to mount a Cat5E wall plate in a Radioshack project box, and have a nicer looking final product with double(for future growth!) cat5e jacks i can plug and unplug the sensor cables into.

Ignore the 2 resistors shown, this was a trial  that failed...so i went to just using 1 resistor using the above schematic, other than that the basic setup is the same.

End Update

The next step is to install the Arduino development software off of their site, and connect your arduino via the supplied USB cable to your computer and make sure it all gets detected and installed properly.

Hook your probe(s) up as follows to the Arduino
DS18B20 - Arduino
Data(Pin 2) - Digital Pin 3
Power(Pin 3) - 5V
Ground(Pin 1) - GND

Now close the Arduino software and download the One Wire Library here
http://www.hacktronics.com/code/OneWire.zip
And the DallasTemperature Library
http://www.hacktronics.com/code/DallasTemperature.zip
And the COSM Client
https://github.com/cosm/cosm-arduino/archive/master.zip

Extract these into folders in the Arduino/Libraries folder..so you should have a Arduino/Libraries/OneWire, etc.

Next open the Arduino software, in the settings make sure you set the Serial port the Uno USB drivers installed onto(Check device manager) and the device type to the Arduino UNO.  These can be found under the tools->board drop down and tools->Serial port drop down.

Copy and paste this code in bold into the window
// This sketch looks for 1-wire devices and
// prints their addresses (serial number) to
// the UART, in a format that is useful in Arduino sketches
// Tutorial:
// http://www.hacktronics.com/Tutorials/arduino-1-wire-address-finder.html

#include <OneWire.h>

OneWire  ds(3);  // Connect your 1-wire device to pin 3

void setup(void) {
  Serial.begin(9600);
  discoverOneWireDevices();
}

void discoverOneWireDevices(void) {
  byte i;
  byte present = 0;
  byte data[12];
  byte addr[8];
 
  Serial.print("Looking for 1-Wire devices...\n\r");
  while(ds.search(addr)) {
    Serial.print("\n\rFound \'1-Wire\' device with address:\n\r");
    for( i = 0; i < 8; i++) {
      Serial.print("0x");
      if (addr[i] < 16) {
        Serial.print('0');
      }
      Serial.print(addr[i], HEX);
      if (i < 7) {
        Serial.print(", ");
      }
    }
    if ( OneWire::crc8( addr, 7) != addr[7]) {
        Serial.print("CRC is not valid!\n");
        return;
    }
  }
  Serial.print("\n\r\n\rThat's it.\r\n");
  ds.reset_search();
  return;
}

void loop(void) {
  // nothing to see here
}


Save it, and with your Arduino all plugged in(don't need Ethernet at this point) and with sensors and lit up, hit upload and make sure that it gets uploaded properly with no compile errors.

When it is complete, from the Tools menu in the Arduino software select the Serial Monitor option.  A new window will pop up and within a second or two it should print some text containing the Address's for any Sensors that are plugged in.  If it pops up and shows no addresses, your sensors are not plugged in properly.  Ensure all connections on both sides are right, use a Multimeter to help debug if you have one.  Because the DS18B20's leads are so small it can be a pain to get them soldered without bridging between leads.  You should see a seperate address for EACH sensor plugged in, so if you have two, and only see one you need to check your  connections until this displays  one address for each sensor.



Write down the addresses it gives you, these are the addresses you need to use in the later program for it to address your sensors on the OneWire bus.

Next create a new program in Arduino, and paste in this
#include <Cosm.h>
#include <CosmClient.h>
#include <CosmDatastream.h>
#include <CosmFeed.h>
#include <CountingStream.h>

#include <b64.h>
#include <HttpClient.h>

#include <OneWire.h>
#include <DallasTemperature.h>
#include <SPI.h>
#include <Ethernet.h>

//Defines for DS18B20
#define ONE_WIRE_BUS 3
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress Sensor1 = {
0x28, 0xA9, 0x31, 0x98, 0x03, 0x00, 0x00, 0x84};
DeviceAddress Sensor2 = {
0x28, 0xA5, 0x0C, 0x74, 0x03, 0x00, 0x00, 0xCA};
//End Defines for DS18B20

//Defines for COSM Ethernet
char cosmKey[] = "IBSjU3xY6SybgOjdyns3F3kdofiSAKxLRzZNOVRoWU1SZz0g";
byte mac[] = {
  0x00, 0x1D, 0x0D, 0x2C, 0x55, 0x3D};

EthernetClient client;
CosmClient cosmclient(client);

//End Defines for COSM Ethernet
double s1 = 0;
double s2 = 0;


#define MYDELAY 5000
char sensor1Id[] = "FermSensor1";
char sensor2Id[] = "Ambient";

CosmDatastream datastreams[] = {
  CosmDatastream(sensor1Id, strlen(sensor1Id), DATASTREAM_FLOAT),
  CosmDatastream(sensor2Id, strlen(sensor2Id), DATASTREAM_FLOAT)};

CosmFeed feed(83208, datastreams, 2);

void setup(void)
{
  // start serial port
  Serial.begin(9600);
  SetupSensors();

  while (Ethernet.begin(mac) != 1)
  {
    Serial.println("Error getting IP address via DHCP, trying again...");
    delay(15000);
  }
}

void SetupSensors()
{
  sensors.begin();
  // set the resolution to 10 bit (good enough?)
  sensors.setResolution(Sensor1, 12);
  sensors.setResolution(Sensor2, 12);
}



float getTemperature(DeviceAddress deviceAddress)
{
  //Get temperature, convert to Fahrenheit, and return
  return DallasTemperature::toFahrenheit(sensors.getTempC(deviceAddress));
}

void loop(void)
{
  SensorLoopAndSend();
}


void SensorLoopAndSend()
{
  sensors.requestTemperatures();
  s1 = getTemperature(Sensor1);
  s2 = getTemperature(Sensor2);
  Serial.print("S1: ");
  Serial.println(s1);
  Serial.print("S2: ");
  Serial.println(s2);
  if((s1 != 185) && (s2 != 185) && (s1 != 32) &&  (s2 != 32))
  {
    datastreams[0].setFloat(s1);
    datastreams[1].setFloat(s2);
    int ret = cosmclient.put(feed, cosmKey);
  }
  delay(MYDELAY);
}

I think the code is pretty easy to read and straight forward
First replace your Device Addresses with the ones i have in my code, you can add more sensors if you wish as well.

Next make an account on COSM.com and when logged on COSM create a Feed by pushing the blue +Device/Feed button in the top right.  Next in your Keys section(top right) you should be given an API Key, find the COSMKey variable in the code above, and replace its value between the quotes with the API key they give you.

Next i don't think its necessary but not a bad idea, when the Ethernet plugged into the Arduino and linked, log into your router and find the mac address of your Wiznet module.  It should be fine to use my MAC address, but using your own wouldn't hurt if you know how to find it since its not printed on the module like it should be.

Next name your Sensors within the code, mine are just Ambient and FermSensor1, these names will be pushed to COSM automatically with your data so you don't need to make them within the COSM webpage.  Don't use spaces, and some special characters might not work so stick to basic characters.

Finally on this line
CosmFeed feed(INSERT FEED HERE, datastreams, 2);
Replace your Feed Number,  and the last number is how many feeds you are pushing.  So if you are using more than 2 sensors increase this number.  It should just be a integer, so no quotes need to be around the feed value.

That should be everything!  Save it and upload it and make sure it compiles, fix any errors you have or ask here if you have no clue what your doing. 

You can check the Serial Monitor to see if its reading your probes properly, if it is you should be seeing data on your COSM feed!

If you are not seeing data, use the Debug area(Top right menu) on COSM.  It will show you how many requests they are getting from you.  By default this code should have about 20 updates per minute which is well under their maximum of 100.  5 Seconds is already way fast for updates, but since they let you do it i don't see why not!  If you are on an ISP provider that has capped download/upload rates, you may want to adjust the MYDELAY to be higher so you don't use a lot of bandwidth.  The value is in milliseconds so the default is 5000 for 5 seconds.

There are an infinite number of ways that you can build this, i am just  documenting my own way i threw it together, at some point i would like to clean it up, but for now its functioning and needed for brewing so i don't want to break it!  I have thought about using phone/Ethernet jack plugs on the ends of my cables, so that i can put my Arduino in a box with a phone/Ethernet wall jack plate and easily plug and unplug sensors in.

Post any ingenious methods of building/connecting that you may have!
That's it! Feel free to post questions here if you have any ill do my best to help!

6 comments:

  1. This is pretty cool. Is there some standard(ized) software that could be loaded to devices based on arduino and which would respond to raise/lower temperature. At some point I'd like to add feature to brewers-assistant to control devices like this. I'd really like my freezer to automatically switch temperatures for lagering when the site tells it.

    ReplyDelete
    Replies
    1. Not really standardized no, most things are DIY on the Arduino....some customization is usually required...that said i do have plans to turn this into a Fermentation temperature controller as well as monitor in the coming months.

      Delete
  2. Great write-up. I need to find a way to have this connected to my two-way temperature controller that turns the freezer on or heater on so I don't need two probes in the wort.

    ReplyDelete
  3. What is the setup if you use the DS18B20 probes? You still need the resistors, right? Would you still need a thermowell if using the probes and the heat shrink wrap stuff? I wonder if it's heavy enough to sink down into the wort, or if a thermowell is necessary to get it in there deep enough.

    I would love to be smart enough to get this to work with my STC-1000 temp controller.

    ReplyDelete
    Replies
    1. Yea you still need to use resistors. You dont need any wrapping if you are using a thermowell. If your going to go without a thermowell, you can wrap the probe and your wire you connect to it(which wont be food safe) in the Food safe heat shrink tubing listed. Depending on what wire you use, it should stay under easily...the wire I got from Lowes was very stiff and holds it shape, so it would stay under easily if i wasnt using a thermowell...

      It would be easier to actually turn this into your own temp controller instead of trying to use it with a STC1000. I have plans sometime in the coming months to get a Solid State relay and start playing with the code to use the Arduino to switch on and off power like the STC-1000 would do, with setpoints, etc.

      Delete
  4. I just got it working and thanks for the post. I have two questions:
    1. Know any way to make it wireless? Can I use this? http://goo.gl/x1k3Q
    2. I'm trying to add another sensor. Can you update this with what I need to change to add one or two more sensors?

    ReplyDelete