SALES INQUIRIES: 1 (888) 767-9864

Homebrewing with Arduino :: Student Project

Ever done any homebrewing?  If you have, it’s hard not to have Arduino pass through your mind as a tool to help in the process.

The following Arduino homebrew project is the result of a ton of hard work and dedication from one of our customers, Klas Bergman.

Klas has used an Arduino Mega, temperature sensors, SD card reader, LEDs, an ethernet connection, (and more) to make one heck of a fermentation control and monitoring system – and did I mention he sends the data to ThingSpeak?

(Below is Klas’ description of the project verbatim,  I did add some headers to break it up.) 

An Obsession with Fermentation…

Ever since I started brewing beer at home I’ve been obsessing over the fermentation stage of the process, since it is crucial to the taste and quality of the finished product.

I used to stand by the airlock with a stopwatch counting bubbles and taking notes. And I found it very frustrating to be in the dark about the temperature of the fermenting beer as it is so important to flavor control.

Warmer temperatures favor ester production for example. And if I succeed in brewing an awesome batch, I want to be able to brew it again and again.

Electronic workbench with soldering iron poised for work

That proves to be pretty difficult if you’re not in command of such an important parameter as temperature is. A couple of years ago I bought an old fridge and a thermostat just for gaining more control so that was a big step in the right direction.

But still, I found it frustrating to not know the exact temperature at all times. I know, it’s pretty wierd. 🙂

Arduino to Control, Log, and Monitor a Homebrew….

When I got into Arduino I started looking for a way to gain that control and to log the values automatically and preferably save it on my computer or at least to an SD card.

To write temperature to an SD card and even publish the data on the internet proved to be pretty easily accomplished using an ethernet shield.

And I was not the first (as is most often the case) to be interested in a bubble counting device.  A couple of other people had been successful in building just that. Here and here are two examples.

They use a photo gate to detect bubbles passing the airlock. I could not think of a better way myself so I got one too. The interrupt in my code, regarding the bubble counting part, is taken from here so the credit goes to them.

glass tubbing and a temp sensor being help against it with modeling clay

I found a good box to enclose my airlock and all of the electronic components and used some of my daughters modelling clay to mount the airlock to the frame of the box in just the right place.

More Cowbell LEDs

I made a hole for the LCD and dove right into the (for me) challenging soldering job, connecting all pins on the LCD and all the LEDs to the arduino.

Yeah, right, I didn’t mention those. I included a bunch of LEDs. More than I needed.

For sure, I could communicate all relevant messages through the screen, so why include LEDs at all?

Well, just because I’m having some fun with this so why not include a bunch of LEDs? I also added a button to be able to change what is displayed on the LCD.

Arduino Home brewing enclosure with LCD and 7 LEDs

Right now, when pressed, it toggles between displaying the current temperatures and displaying how many bubbles that has passed the airlock so far and the present bubble count / minute. Oh, and I also added a piezo buzzer to audibly warn me if the temperature runs too high.

Arduino Mega to Handle all the Brew

I use an Arduino Mega in this project because I have no less than seven libraries in the code. When I tried using an UNO I ran out of memory.

I use two DS18B20 with the onewire library and I’ve calibrated them to a third, expensive and very accurate thermometer.

Actually, one of the DS18B20 was spot on but the other one was off by half a degree so I account for that in the code. One of the sensors measures the temperature of the air inside the fridge and one measures the temperature inside the tank.

I am very meticulous about keeping other organisms out, other than my yeast strain, which is an occupational hazard from working as a microbiologist for many years I guess, so I won’t let anything touch my beer at any time before the beer is to be had.

This means that I can’t have the DS18B20 hanging down into the wort. So I drilled a hole in the side of the tank and installed a well where the sensor fits.

LEDs to Indicate the Yeast Temperature Preference

There is one multi colored, one red, one blue LED and then there are four green ones. The multi colored one changes color based on the yeast strains preferred temperature range. So that is something I have to change in the code in between brews.

I’m thinking about rewriting it so that I can choose the temperature range with the button. Perhaps I’ll have a database that holds a lot of strains that I can choose from.

So when the temperature inside the tank is on the cold side of the strains preferred temperature range, the light is bluish and when it is on the hot side, it is reddish. In between it is of course green.

The red LED is lit only as long as the yeast is in it’s lag face. That is in the beginning of the fermentation cycle when no carbon dioxide is being produced. When the first bubble passes the airlock the red light is turned off.

The green LEDs does not have any function right now. I believe that there is a possibility that I can predict where I am in the fermentation process based on the bubble count. If that is the case, then the green lights could be lit one by one as the fermentation progresses until completion when all green lights could be lit.

The blue LED is turned on when the temperature in the tank falls below 2 degrees Celsius. When does that happen?

Well, when the fermentation is completed I turn on the fridge full time to lower the temperature as much as possible. It is for clarification purposes and it is called “cold crashing” the beer. So when the blue light is turned on I’ll know that it is time to transfer the finished beer to a keg.

Brew IoT with the ThingsSpeak app

I was very happy to find thingspeak.com. It is super easy to upload sensor output to a channel. They let you update as frequently as every 15 seconds and they do all the graphing for you. At any time I can whip out my phone and see what’s happening right now in the thingspeak app. I love that kind of thing!

numbered graph showing a noisy curve

For the Future

I’m pleased with this fermentation monitoring device but I do want to give it control over the temperature in the fridge.

So that is what lies ahead for this project. If I do that I could for example have it induce a cold crash on it’s own when the bubble count is low enough.

Since I don’t want to meddle with high voltages I’ve bought a remote controlled outlet from Nexa and I mean to hack it and give the Arduino control over it.

I’ve included some photos of my efforts 🙂 and my code. It is far from perfect. And I even have some hard-coded values in there I’m ashamed to admit. I did listen in class, I promise!

I’ll clean up the code when I’m done with it – I mean when it controls the fridge and I have a one button menu in place.

A link to my thingspeak channel:
https://thingspeak.com/channels/333710

You can also check out a video of the setup here.

Arduino Code:

/* This sketch is written for a fermentation monitoring system for home brewing. The system will do the following:
    Monitor two temperature sensors. One inside the fermenter and one inside the fermentation cabinett.
    Monitor fermentaion activity through registration of bubbles passing through an airlock.
    The temperature data is written to an LCD display, an SD card and a thingspeak channel via ethernet shield.
    The fermenation activity data is presented on LCD and thinspeak mainly as a fermentation progress with a display of specific gravity in the fermenting beer.
    There are seven LEDs which are there to communicate information through blinking, changing colour or just being lit.
    All info could be communicated through the LCD screen but I'm having some fun with this so why not include a bunch of LEDs?
    Here follows a description of what they do.
    Blue LED will
    Green 1 will be lit and pulsating when 25% or more of the fermentation process is completed. When 100% is hit, it will stop pulsating.
    Green 2 will be lit and pulsating when 50% or more of the fermentation process is complete. When 100% is hit, it will stop pulsating.
    Green 3 will be lit and pulsating when 75% or more of the fermentation process is complete. When 100% is hit, it will stop pulsating.
    Green 4 will be lit when 100% of the fermentation process is complete.
    Red LED will be lit before fermentation is evident and will turn off when the first bubble passes the airlock
    Color changing LED will change color based on the temperatrue inside the fermentation tank. A temperature range must be specified beforehand, the yeasts working range. When the temperature is in the low
    range, the color of the LED turns blueish and when it is on the high end, the LED turns redish. Within the range the color should shift gradually accordingly.
    There is one button that will enable the user to choose different information outputs on the LCD screen
*/

#include <ThingSpeak.h>
#include <OneWire.h>
#include <DallasTemperature.h >
#include <Ethernet.h>
#include <SPI.h>
#include <SD.h>//
#include <LiquidCrystal.h>

byte mac[] = {0x9c, 0xf5, 0xa3, 0x74, 0xf2, 0xd2};

EthernetClient client;


unsigned long previousMillis = 0;
unsigned long previousNumPulses = 0;
const long thingSpeakWriteInterval = 60000;
unsigned long myChannelNumber = 333710;
const char * myWriteAPIKey = "MCS3F5VTNQNJQA23";

//Declaring pins for all LEDs. All but two uses pins with PWM capability. The exceptions are 36 and 37.
byte blueLedPin = 9;
byte greenLed1Pin = 8;
byte greenLed2Pin = 7;
byte greenLed3Pin = 6;
byte greenLed4Pin = 36;
byte redLedPin = 37;
byte blueMultiLedPin = 44;
byte greenMultiLedPin = 45;
byte redMultiLedPin = 46;
byte buttonPin = 26;
float blueTemp = 0;
float greenTemp = 0;
float redTemp = 0;

int blinkLedDelay = 200;
int ledSprintDelay = 70;

int ledLine [6] = { redLedPin, greenLed4Pin, greenLed3Pin, greenLed2Pin, greenLed1Pin, blueLedPin };


boolean buttonState = 0;         // variable for reading the pushbutton status
/***********************************************************************************'
  THE FOLLOWING IS REGARDING THE INTERRUPT FUNCTION FOR THE THE PULSE COUNTER
************************************************************************************/
// Connect the opto signal pin to the first INT pin (digital pin 2 on an Arduino Uno)
#define resolution 60000  //only capture pulse that are greater than this to avoid noise
#define sample 4// sample size of pulses for average starts at 0

volatile unsigned long pulseThen;
volatile unsigned long pulseNow;
volatile unsigned long numPulses;
volatile unsigned long keeppulse;
volatile int count = 0;
volatile int pulsesPerMinute = 0;



void isr()
{
  unsigned long now = micros();
  float pulselength;
  pulseNow = now;
  float averagepulse;
  float totalsample = 0;

  if ((pulseNow - pulseThen) > resolution)
  {
    Serial.print("numPulses ");
    Serial.println(numPulses + 1);
    Serial.print(" ");
    pulselength = (float)(pulseNow - pulseThen) / 1000000;
    Serial.print("Tid mellan pulser: ");
    Serial.print(pulselength);
    Serial.print(" sekunder ");
    // Serial.print(" ");
    //Serial.print("keeppulse ");
    //Serial.print(count);

    //  Serial.print("\n");
    if ( count < sample )
    {
      keeppulse = pulselength;
      count++;
    }
    else
    {
      count = 0;
      Serial.print("Average in a sample of ");
      Serial.print(sample + 1);
      // Serial.print(count);
      Serial.print(" is ");
      for ( int x = 0; (x < sample); x++ ) {
        totalsample += (int)keeppulse[x];
      }
      averagepulse = totalsample / sample;
      int averagepulsetime =
        Serial.print(averagepulse);
      Serial.print(" ");
      //    Serial.print("\n\n");
    }

    pulseThen = pulseNow;
    ++numPulses;
  }
  if (numPulses == 1) {
    digitalWrite(redLedPin, LOW);
    File dataFile = SD.open("datalog.txt", FILE_WRITE);

    /* if the file is available, write to it:
        Writing down in SD the time of first activity (millis)
    */

    if (dataFile) {
      dataFile.print("First evidence of fermentation at ");
      dataFile.print(millis() / 1000);
      dataFile.print(" seconds after pitch");

      dataFile.close();

    }
    // if the file isn't open, pop up an error:
    else {
      Serial.println("error opening datalog.txt");
    }

  }

}


/********************************************************************************/
//END OF PULS COUNTER SEGMENT
/*********************************************************************************/


// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(30, 31, 32, 33, 34, 35);

const int piezo = A5;


//The onboard (Ehternet Shield) micro-SD card reader is accessible through the SD Library. When working with this library, SS is on Pin 4.
const int chipSelect = 4;

// Data wire for temp sensors is plugged into port 28 on the Arduino
#define ONE_WIRE_BUS 28

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);



void setup(void)
{
  pinMode(blueLedPin, OUTPUT);
  pinMode(greenLed1Pin, OUTPUT);
  pinMode(greenLed2Pin, OUTPUT);
  pinMode(greenLed3Pin, OUTPUT);
  pinMode(greenLed4Pin, OUTPUT);
  pinMode(redLedPin, OUTPUT);
  pinMode(blueMultiLedPin, OUTPUT);
  pinMode(redMultiLedPin, OUTPUT);
  pinMode(greenMultiLedPin, OUTPUT);
  pinMode(buttonPin, INPUT);

  Ethernet.begin(mac);

  ThingSpeak.begin(client);


  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);

  // start serial port
  Serial.begin(9600);

  // Start up the library
  sensors.begin();

  //User friendly informatory startup sequence starts here
  lcd.setCursor(0, 0);
  lcd.print("Veretro Betula");
  lcd.setCursor(0, 1);
  lcd.print("Home brewery");

  //Start LED sprint that will roll during opening message

  ledSprint();
  ledSprint();
  ledSprintEnding();
  delay(1000);

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Initializing");
  lcd.setCursor(0, 1);
  lcd.print("Ethernet...");
  for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 20) {
    // sets the value (range from 0 to 255):
    analogWrite(blueMultiLedPin, fadeValue);

    // wait for 30 milliseconds to see the dimming effect
    delay(30);
  }

  // fade out from max to min in increments of 5 points:
  for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 20) {
    // sets the value (range from 0 to 255):
    analogWrite(blueMultiLedPin, fadeValue);

    // wait for 30 milliseconds to see the dimming effect
    delay(30);
  }
  for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 20) {
    // sets the value (range from 0 to 255):
    analogWrite(blueMultiLedPin, fadeValue);

    // wait for 30 milliseconds to see the dimming effect
    delay(30);
  }

  // fade out from max to min in increments of 5 points:
  for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 20) {
    // sets the value (range from 0 to 255):
    analogWrite(blueMultiLedPin, fadeValue);

    // wait for 30 milliseconds to see the dimming effect
    delay(30);
  } for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 20) {
    // sets the value (range from 0 to 255):
    analogWrite(blueMultiLedPin, fadeValue);

    // wait for 30 milliseconds to see the dimming effect
    delay(30);
  }

  // fade out from max to min in increments of 5 points:
  for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 20) {
    // sets the value (range from 0 to 255):
    analogWrite(blueMultiLedPin, fadeValue);

    // wait for 30 milliseconds to see the dimming effect
    delay(30);
  }

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Ehternet");
  lcd.setCursor(0, 1);
  lcd.print("initialized");
  tone(A5, 880);
  digitalWrite(greenLed1Pin, HIGH);
  digitalWrite(greenLed2Pin, HIGH);
  digitalWrite(greenLed3Pin, HIGH);
  digitalWrite(greenLed4Pin, HIGH);
  digitalWrite(blueLedPin, HIGH);
  digitalWrite(blueMultiLedPin, HIGH);
  delay(blinkLedDelay);
  digitalWrite(greenLed1Pin, LOW);
  digitalWrite(greenLed2Pin, LOW);
  digitalWrite(greenLed3Pin, LOW);
  digitalWrite(greenLed4Pin, LOW);
  digitalWrite(blueLedPin, LOW);
  digitalWrite(blueMultiLedPin, LOW);
  noTone(A5);
  delay(blinkLedDelay);
  tone(A5, 880);
  digitalWrite(greenLed1Pin, HIGH);
  digitalWrite(greenLed2Pin, HIGH);
  digitalWrite(greenLed3Pin, HIGH);
  digitalWrite(greenLed4Pin, HIGH);
  digitalWrite(blueLedPin, HIGH);
  digitalWrite(blueMultiLedPin, HIGH);
  delay(blinkLedDelay);
  digitalWrite(greenLed1Pin, LOW);
  digitalWrite(greenLed2Pin, LOW);
  digitalWrite(greenLed3Pin, LOW);
  digitalWrite(greenLed4Pin, LOW);
  digitalWrite(blueLedPin, LOW);
  digitalWrite(blueMultiLedPin, LOW);

  noTone(A5);
  delay(700);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Initializing");
  lcd.setCursor(0, 1);
  lcd.print("SD card...");
  for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 20) {
    // sets the value (range from 0 to 255):
    analogWrite(blueMultiLedPin, fadeValue);

    // wait for 30 milliseconds to see the dimming effect
    delay(30);
  }

  // fade out from max to min in increments of 5 points:
  for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 20) {
    // sets the value (range from 0 to 255):
    analogWrite(blueMultiLedPin, fadeValue);

    // wait for 30 milliseconds to see the dimming effect
    delay(30);
  }
  for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 20) {
    // sets the value (range from 0 to 255):
    analogWrite(blueMultiLedPin, fadeValue);

    // wait for 30 milliseconds to see the dimming effect
    delay(30);
  }

  // fade out from max to min in increments of 5 points:
  for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 20) {
    // sets the value (range from 0 to 255):
    analogWrite(blueMultiLedPin, fadeValue);

    // wait for 30 milliseconds to see the dimming effect
    delay(30);
  } for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 20) {
    // sets the value (range from 0 to 255):
    analogWrite(blueMultiLedPin, fadeValue);

    // wait for 30 milliseconds to see the dimming effect
    delay(30);
  }

  // fade out from max to min in increments of 5 points:
  for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 20) {
    // sets the value (range from 0 to 255):
    analogWrite(blueMultiLedPin, fadeValue);

    // wait for 30 milliseconds to see the dimming effect
    delay(30);
  }

  lcd.clear();

  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    //The red and greenLed1 blins rapidly four times
    lcd.setCursor(0, 0);
    lcd.print("SD card failed,");
    lcd.setCursor(0, 1);
    lcd.print("or not present");

    //Blink redLedPin and redMultiLedPin fast twice to indicate that something went wrong
    tone(A5, 880);
    digitalWrite(redMultiLedPin, HIGH);
    digitalWrite(redLedPin, HIGH);

    delay(blinkLedDelay);
    digitalWrite(redMultiLedPin, LOW);
    digitalWrite(redLedPin, LOW);
    delay(blinkLedDelay);
    noTone(A5);
    delay(blinkLedDelay);
    tone(A5, 240);
    digitalWrite(redMultiLedPin, HIGH);
    digitalWrite(redLedPin, HIGH);
    delay(blinkLedDelay);
    digitalWrite(redMultiLedPin, LOW);
    digitalWrite(redLedPin, LOW);
    delay(blinkLedDelay);
    noTone(A5);

    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");
  lcd.setCursor(0, 0);
  lcd.print("SD card present");


  // All green LEDs + blue LED + blueMultiPin blink rapidly two times

  tone(A5, 880);
  digitalWrite(greenLed1Pin, HIGH);
  digitalWrite(greenLed2Pin, HIGH);
  digitalWrite(greenLed3Pin, HIGH);
  digitalWrite(greenLed4Pin, HIGH);
  digitalWrite(blueLedPin, HIGH);
  digitalWrite(blueMultiLedPin, HIGH);
  delay(blinkLedDelay);
  digitalWrite(greenLed1Pin, LOW);
  digitalWrite(greenLed2Pin, LOW);
  digitalWrite(greenLed3Pin, LOW);
  digitalWrite(greenLed4Pin, LOW);
  digitalWrite(blueLedPin, LOW);
  digitalWrite(blueMultiLedPin, LOW);
  noTone(A5);
  delay(blinkLedDelay);
  tone(A5, 880);
  digitalWrite(greenLed1Pin, HIGH);
  digitalWrite(greenLed2Pin, HIGH);
  digitalWrite(greenLed3Pin, HIGH);
  digitalWrite(greenLed4Pin, HIGH);
  digitalWrite(blueLedPin, HIGH);
  digitalWrite(blueMultiLedPin, HIGH);
  delay(blinkLedDelay);
  digitalWrite(greenLed1Pin, LOW);
  digitalWrite(greenLed2Pin, LOW);
  digitalWrite(greenLed3Pin, LOW);
  digitalWrite(greenLed4Pin, LOW);
  digitalWrite(blueLedPin, LOW);
  digitalWrite(blueMultiLedPin, LOW);

  noTone(A5);
  lcd.clear();
  delay(700);
  lcd.setCursor(0, 0);
  lcd.print("All set...");
  delay(2000);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Happy");
  lcd.setCursor(0, 1);
  lcd.print("fermenting!");
  successMelody();
  
  delay(1000);
  
  lcd.clear();


  //Turn on the redLed which will be lit until first sign of fermentation
  digitalWrite(redLedPin, HIGH);

  boolean receiving = false;


  pinMode(3, OUTPUT); //probe output on pin 3
  attachInterrupt(0, isr, RISING);
  numPulses = 0;                      // prime the system to start a new reading

}



void loop(void)
{

  // call sensors.requestTemperatures() to issue a global temperature
  // request to all devices on the bus
  sensors.requestTemperatures(); // Send the command to get temperatures
  float tempValueInside = sensors.getTempCByIndex(0) + 0.5;
  float tempValueOutside = sensors.getTempCByIndex(1);

  unsigned long currentMillis = millis();
  unsigned long currentNumPulses = numPulses;

  ThingSpeak.setField(1, tempValueInside);
  ThingSpeak.setField(2, tempValueOutside);
  ThingSpeak.setField(3, pulsesPerMinute);

  if (currentMillis - previousMillis >= thingSpeakWriteInterval) {

    ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
  }

  if (currentMillis - previousMillis >= thingSpeakWriteInterval) {

    pulsesPerMinute = currentNumPulses - previousNumPulses;
    previousMillis = currentMillis;
    previousNumPulses = currentNumPulses;


  }



  /* The following three segments regulates the color of the RGB-LED based on temperature. The variables lowTempLimit and highTempLimit will be changed inbetween fermentations depending
      on the yeast strains  optimal work range.
  */

  float lowTempLimit = 17.8;
  float highTempLimit = 22.2;
  float mediumTemp = lowTempLimit + (highTempLimit - lowTempLimit) / 2;
  float quarterTemp = lowTempLimit + (mediumTemp - lowTempLimit) / 2;
  float threeQuarterTemp = mediumTemp + (mediumTemp - lowTempLimit) / 2;

  if (tempValueInside < lowTempLimit) {
    analogWrite(blueMultiLedPin, 255);
  }
  else if (tempValueInside > 0 && tempValueInside <= mediumTemp) {
    blueTemp = map(tempValueInside, lowTempLimit, mediumTemp, 255, 0);
    analogWrite(blueMultiLedPin, blueTemp);
  }
  else if (tempValueInside > mediumTemp) {
    analogWrite(blueMultiLedPin, 0);
  }

  if (tempValueInside < quarterTemp) {
    analogWrite(greenMultiLedPin, 0);
  }
  else if (tempValueInside > quarterTemp && tempValueInside <= threeQuarterTemp) {
    greenTemp = map(tempValueInside, quarterTemp, mediumTemp, 1, 254);
    analogWrite(greenMultiLedPin, greenTemp);
  }
  else if (tempValueInside > mediumTemp && tempValueInside <= threeQuarterTemp) {
    greenTemp = map(tempValueInside, mediumTemp, threeQuarterTemp, 255, 0);
    analogWrite(greenMultiLedPin, greenTemp);
  }
  else if (tempValueInside > threeQuarterTemp) {
    analogWrite(greenMultiLedPin, 0);
  }

  if (tempValueInside < threeQuarterTemp) {
    analogWrite(redMultiLedPin, 0);
  }
  else if (tempValueInside >= mediumTemp) {
    redTemp = map(tempValueInside, mediumTemp, highTempLimit, 1, 255);
    analogWrite(redMultiLedPin, redTemp);
  }
  else if (tempValueInside > highTempLimit) {
    analogWrite(redMultiLedPin, 255);
  }

  lcd.setCursor(0, 0);
  if (sensors.getTempCByIndex(0) + 0.5 <= highTempLimit) {
    lcd.print("Tank: ");
    lcd.print(tempValueInside);
    lcd.print((char)223);
    lcd.print("C");
    lcd.setCursor(0, 1);
    lcd.print("Chamber: ");
    lcd.print(tempValueOutside);
    lcd.print((char)223);
    lcd.print("C");


  }
  if (sensors.getTempCByIndex(0) + 0.5 >= 25) {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print(sensors.getTempCByIndex(0) + 0.5);
    lcd.print(" grader");
    lcd.setCursor(0, 1);
    lcd.print("Temp too high!");
    //highTempWarning();

  }

  Serial.println(sensors.getTempCByIndex(0) + 0.5);
  Serial.println(pulsesPerMinute);


  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.



  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  // if the file is available, write to it:
  //skriver temp och korrigerar med +0,5 enligt kalibrering gjord 5/9-17
  if (dataFile) {
    dataFile.println(sensors.getTempCByIndex(0) + 0.5);

    dataFile.close();

  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  }

  buttonState = digitalRead(buttonPin);

  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
  if (buttonState == HIGH) {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Pulser: ");
    lcd.print(numPulses);
    lcd.setCursor(0, 1);
    lcd.print(pulsesPerMinute);
    lcd.print(" pulses/minute");
    delay(1000);
    lcd.clear();

     } else {
    //
      }
}



// This function plays the warning melody for a too high temperature.

void highTempWarning() {


  tone (A5, 250);
  delay(75);

  tone (A5, 440);
  delay(75);

  tone (A5, 660);
  delay(75);

  tone (A5, 880);
  delay(75);

  tone (A5, 660);
  delay(75);

  tone (A5, 440);
  delay(75);

  noTone (A5);

}


void  successMelody() {

  int delaySuccessMelody = 150;

  tone (A5, 250);
  delay(delaySuccessMelody);

  tone (A5, 440);
  delay(delaySuccessMelody);

  tone (A5, 660);
  delay(delaySuccessMelody);

  tone (A5, 880);
  delay(100);
 
noTone(A5);
delay(250);

  tone (A5, 660);
  delay(delaySuccessMelody);

  tone (A5, 880);
  delay(400);

  noTone (A5);

}

void ledSprint (){

  for (int i = 0; i < 6; i++) {
    digitalWrite(ledLine[i], HIGH);

    if (i == 0) digitalWrite(ledLine[i + 1], LOW);
    if (i > 0) digitalWrite(ledLine[i - 1], LOW);
    delay(ledSprintDelay);
  }

  // SCAN DOWN
  for (int i = 4; i > 0; i--) {
    digitalWrite(ledLine[i], HIGH);

    if (i == 5) digitalWrite(ledLine[i - 1], LOW);
    if (i < 5) digitalWrite(ledLine[i + 1], LOW);
    delay(ledSprintDelay);
  }
}
void ledSprintEnding () {

  for (int i = 0; i < 6; i++) {
    digitalWrite(ledLine[i], HIGH);

    if (i == 0) digitalWrite(ledLine[i + 1], LOW);
    delay(50);
  }
}

 

4 Comments

  1. Avatar JohnnyFRX on October 30, 2017 at 10:14 am

    That’s about the coolest thing EVER man! Nice work. I’ve messed with beermaking via MRBEER on occasion and that was fun as it was. You’re on a WHOLE ‘nuther level of awesome goodness here. I use the DS18B20’s to track/regulate the temp’s in our Reptiles vivariums with relays and heating devices. Nice sensors to work with, especially with the adjustments available for resolution.

    • Avatar Klas B on November 1, 2017 at 7:26 am

      Thanks! It was a lot of fun putting it together. After this, I’m constantly thinking about and trying to work out if I could automate some of the other stages of the brewing process. There are so many fun sensors to play around with. Solenoid valves, water flow sensors etc. I just wish extra spare time was as available for purchasing 🙂

  2. Avatar MICHAEL JAMES on October 30, 2017 at 11:14 am

    Beer is pretty close to my heart, so this project hits home for me. I didn’t realize that ThingSpeak had an App too – I have always just used the website. I look forward to checking that out. Nice work Klas!

  3. […] where one of our students uses the millis function in their own project? Check out the “Homebrewing with Arduino” post which is […]

Leave a Comment