Brewery bulid

The Homebrew Forum

Help Support The Homebrew Forum:

This site may earn a commission from merchant affiliate links, including eBay, Amazon, and others.

lee26

New Member
Joined
Nov 7, 2013
Messages
11
Reaction score
0
Well first off hello. I have viewed post on here for some time but this is my first post. I have been brewing on and off for the last 4 years but not done much for the last 6 months due to moving house etc. Recently I went on a trip to Skye where I spent most of the day drinking good ale and enjoying the view. heres a pic from said trip to make you all jealous :tongue:
WP_20131015_015_zps8f2d66fe.jpg

(sorry about that lol)

Anyway all that good beer made me wanted to get back it to brewing. So I have set about planing a new brewery build. Another project of mine over the last month or so has been getting my head around arduinos and programming. Can you see where this is going? yes thats right I'm building an arduino based brewery!!

My first set was to find a control pannel for all the electronics. The most suitable thing I could find was a meter box but these things are upwards of £70 and I'm on a students budget! So as this is going to be a bit of a prototype I decided to go with a cheap storage box.
WP_20131018_001_zps614c4ea2.jpg

£8 from B&Q

I will be using one arduino for each tank (HLT,mash,boil) so I started with the HLT just to make sour it was all going to work. Heres a quick shot of me testing the LCD screen
WP_20131018_003_zps4332e96f.jpg

temp reading high as no probe is connected.

here is the inside so far
WP_20131105_002_zpsa3014814.jpg

I have tidied it up a bit since taking this pic :D

here is the control panel powered up. the temp is reading 0 as I am still awaiting the probes from hong kong.
WP_20131106_001_zps13f95a03.jpg

the mess of terminal blocks in the bottom right is no more! lol

I have gone for plastic brewing buckets warped in insulation of all my tanks. This is many due to price and the fact I already had them. here is my HLT and mash tun. more work is required like covering the elements etc.
WP_20131105_001_zps4dc3d6f6.jpg

the hole in the mash tun is for the HERMS return.

I am using a cheap ASDA kettel as a heat exchange. the plan is when more funds become available is to get a plate chiller and use my immersion chiller as an exchanger inside my HLT.
WP_20131106_003_zpsbcc3ca5e.jpg


And thats all so far. I have a long way to go before I can brew my first beer on this system but its good fun building too! I also plan on building a sort of diy ro water system soon as the ones you can buy are far to expensive. If anyone has any advise on this please let me know.

Anyway I will update this post as I go along hopefully with lots of pics

thanks

Lee :thumb:
 
Hi.

Your links won't work until you've been here a few days and made a few posts. It's an anti-spam thing.
 
oldbloke said:
Hi.

Your links won't work until you've been here a few days and made a few posts. It's an anti-spam thing.


That's not the only problem. I tried reporting but all the links are mangled with IMG and URL and stuff in the wrong place.
 
Hopefully thats the images working now? I copied the links direct from photo bucket but they didn't seem to work correctly. anyway sorted now. :thumb:
 
Antony said:
Looks good, what exactly are you doing with the kettle?

the kettle is the heat exchange for my HERMS system. Instead of having a copper coil inside the HLT it in the kettle. the main reason for this is because it was cheap :thumb:

Arduino is a electronics prototyping platform which allows you to program micro controllers relatively easily
 
h_doody said:
Any chance you could post the design of the arduino controller?

yes but what do you mean by design? the code or the schematic of the circuit?
 
Both, really. I'm looking at doing something similar with my own brewery and it's either an Arduino set up or a few PID controllers.
 
Well PID would be easier for sure. the arduino approach has coursed me some head aches! The code for the HLT is as follows. I can give you the schematic right now as I don't have one but watch this space

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int floatswitch=10;
int value=0;
int saferelay=8;
int reading = 1;
int sensorPin = A1;
int relay =9;

void setup()
{
lcd.begin(16, 2);
lcd.setCursor(0, 1);
lcd.print("Welcome" );
lcd.setCursor(0,0);
delay(3000);
pinMode(floatswitch, INPUT);
digitalWrite(floatswitch, HIGH);
pinMode(saferelay, OUTPUT);
delay(5000);
pinMode(relay,OUTPUT);
lcd.begin(16, 2);
}
void loop()
{
value = digitalRead(floatswitch);
if (value == HIGH) {
digitalWrite(saferelay, LOW);
}
else {
digitalWrite(saferelay, HIGH);
}
reading = analogRead(sensorPin);
int celsius = reading/2;
lcd.setCursor(0, 0);
lcd.print("Temperature: ");
lcd.setCursor(0,1);
lcd.print(celsius, DEC);
lcd.print((char)223);
lcd.print("C");
if (celsius >70) {
digitalWrite(9,LOW);
} else {
digitalWrite(9,HIGH);
}
{
delay(500);
lcd.clear();}
}

Its a wee bit messy but it is my first code ever lol
 
if its just the ds18b20 sensors you want and can make your own probes from them you can get some free samples from the maxim website sent by fed ex so are both cheaper n quicker than ebay hongkong..
 
Fil said:
if its just the ds18b20 sensors you want and can make your own probes from them you can get some free samples from the maxim website sent by fed ex so are both cheaper n quicker than ebay hongkong..

I was going to use the LM35DZ. Do you have link to there site? Thanks :D
 
Many thanks Fil I will have a look at that when i'm not full of beer :cheers: :D
 
Ok so I have done a bit more building today. First off I have decided to go with an off the shelve PID to control the mash temp. The main reason for this is I want it to be acruate to within a degree and I have been struggling with code to active this. It is something I will continue to work on but in order to get brewing asap I have gone for the PID.

I have started to make the boiler I haven't insulated it yet as I still need to put the second element in. There is also a bit more plumbing to do but its almost there.
WP_20131112_001_zpsd247f8b6.jpg


I have also been working on the wiring. The top screen is for the HLT the PID is for the Mash and the bottom screen is for the boiler. It has taken about 15 hours just in wiring so far but I'm. Almost done! :-)
WP_20131112_006_zps2eb1891e.jpg


Here is a shot of the inside. Its a working progress and dose need some tiding up.
WP_20131112_008_zpsa6ef8e20.jpg


So her hopefully not long to go as I got some beer ingredients in the post today. I plan on the first beer being a hobgoblen clone.

I'm also picking up a fridge tomorow that I found on Gumtree for £25 that I plane on making in to a keg fridge.

P.s. sorry for the spelling it's late!
 
If it helps here is the code implimenting the arduino pid lib i lifted from Jabba (jamie) over on Jims beerkit from his brewery programming thread


Code:
/*-------------------------------------------------------------

Release 1 03/4/2012

Semi-automated HERMS (Heat Exchange Recirculating Mash System)
brewery and sous vide cooker. 

Developed with Arduino IDE release 0023 and associated libraries

All code published as open source- do with it what you may!

by Jamie Abbott (j.abbott(at)dsl.pipex.com) 2011-12

--------------------------------------------------------------*/

#include <LiquidCrystal.h>
#include <PID_v1.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Bounce.h>
#include <avr/pgmspace.h>

#define ONE_WIRE_BUS 8               //One-Wire bus for 3 DS18b20 tempreature sensors on pin 8
OneWire oneWire(ONE_WIRE_BUS);       //setup a oneWire instance to communicate with any OneWire devices
DallasTemperature sensors(&oneWire); //pass oneWire reference to Dallas Temperature.

float HLTtemp, Mash_CookTemp, BoilTemp,value;  //define names of temp. sensors

LiquidCrystal lcd (2,3,4,5,6,7); //setup LCD display pins

const boolean PotPin=A0;  //pump speed potentiometer 
                                                                                                                                                                                                     
const boolean button_pin1=A5;    //
const boolean button_pin2=A4;    //buttons on analogue pins
const boolean button_pin3=A3;    //

Bounce button1 = Bounce(button_pin1,5); //
Bounce button2 = Bounce(button_pin2,5); //setup de-bouncing on buttons  
Bounce button3 = Bounce(button_pin3,5); //

const boolean HLTrelay=11;       //
const boolean Mash_CookRelay=12; //solid State Relays controlling heating elements on analouge pins
const boolean BoilerRelay=13;    //

const byte buzzer=9;            //buzzer alarm to alert when a brew process has finished
const byte HERMSpumpFET=10;     //MOSFET to control solar pump that re-circs wort around HERMS kettle control

unsigned short HLTtarget=78;    //default mash liqour target temp. (hot enough to pre-heat mash tun) 
unsigned short MashTarget=66;   //default target mash temp.
unsigned short BoilTarget=100;  //default boil target temp.
unsigned short SpargeTarget=75; //default sparge liqour target temp.
unsigned short MashTime=90;     //default mash duration
unsigned short BoilTime=90;     //default boil duration
unsigned short ChillTarget=25;  //default target cool temp.

unsigned short PotValue;        //to hold value from pump potentiometer
unsigned short PumpDisplay;     //value as % of pump speed

unsigned short CookTarget=57;   //default target cook temp.
unsigned long CookTime;         //to store cooking duration
unsigned long CookHrs=2;        //default cook time hours
unsigned long CookMins=30;      //default cook time minutes

long time;

unsigned long MashStartTime, BrewEndTime, BoilStartTime, BrewStartTime, BrewDuration, CookStartTime;  //brewday finish time
unsigned long lastPIDCalculation = 0;

boolean HLTon = true;
boolean BoilOff = true;
boolean ChillOn = true;
boolean set = true;
boolean CookTargetSet = true;
boolean CookHrsSet = true;
boolean CookMinsSet = true;
boolean state = true;
boolean BoilPause = false;

#define COOK 1   //menu mode for cooking sous vide
#define BREW 2   //menu mode for brewing
byte mode=0;     //initalise menu mode 
byte CookMenu=1; //initalise brew menu 
byte BrewMenu=1; //initalise brew menu

double Setpoint, Input, Output;                      //
PID myPID(&Input, &Output, &Setpoint,5,2,1, DIRECT); //Specifies the PID links and initial tuning parameters
int WindowSize=2500;                                 //
unsigned long windowStartTime;                       //

byte CustomChar[8]={ //
B00010,              //
B01110,              //
B10001,              //Creates letter 'é' 
B11111,              //
B10000,              //
B01110};             //
int eAcute;          //                                           //

//Text strings below stored in flash memory to save sapce in SRAM

const prog_uchar s01[] PROGMEM ="      Welcome!";
const prog_uchar s02[] PROGMEM ="  what do you want";
const prog_uchar s03[] PROGMEM ="       to do?";
const prog_uchar s04[] PROGMEM ="COOK S-V        BREW";

const prog_uchar s05[] PROGMEM =" Welcome to Fil's";
const prog_uchar s06[] PROGMEM ="      Brewery"     ;
const prog_uchar s07[] PROGMEM ="  Press any button";
const prog_uchar s08[] PROGMEM ="    to go forward  ";

const prog_uchar s09[] PROGMEM =" Welcome to Fil's ";
const prog_uchar s10[] PROGMEM ="  Sous Vide Cooker! ";
const prog_uchar s11[] PROGMEM ="  Press any button  ";
const prog_uchar s12[] PROGMEM ="    to go forward   ";

const prog_uchar s13[] PROGMEM ="      HLT: ";
const prog_uchar s14[] PROGMEM ="       MT: ";
const prog_uchar s15[] PROGMEM ="   Boiler: ";
const prog_uchar s16[] PROGMEM ="  PRESS ANY BUTTON";

const prog_uchar s17[] PROGMEM ="Ready to start mash!";
const prog_uchar s18[] PROGMEM ="Prime pump&fill HLT ";
const prog_uchar s19[] PROGMEM =" for sparge liquor  ";
const prog_uchar s20[] PROGMEM ="                    ";

const prog_uchar s21[] PROGMEM ="     HLT Setup ";
const prog_uchar s22[] PROGMEM ="Current Temp:";
const prog_uchar s23[] PROGMEM =" UP     SET     DOWN";

const prog_uchar s24[] PROGMEM ="     Mash Setup ";

const prog_uchar s25[] PROGMEM ="     Boil Setup ";
const prog_uchar s26[] PROGMEM ="Current Time:";

const prog_uchar s27[] PROGMEM ="   Setup compleate";
const prog_uchar s28[] PROGMEM ="   Ready to brew!";
const prog_uchar s29[] PROGMEM ="   Is HLT Filled? ";
const prog_uchar s30[] PROGMEM ="BACK           START";

const prog_uchar s31[] PROGMEM =" Mash liquor heating";
const prog_uchar s32[] PROGMEM ="Mash liquor ready!!!";
const prog_uchar s33[] PROGMEM ="   HLT temp:";
const prog_uchar s34[] PROGMEM ="     Target:";
const prog_uchar s35[] PROGMEM ="CHANGE    OFF   MASH";
const prog_uchar s36[] PROGMEM ="CHANGE    ON    MASH";

const prog_uchar s37[] PROGMEM ="CHANGE    ON     END";
const prog_uchar s38[] PROGMEM ="CHANGE    OFF    END";

const prog_uchar s39[] PROGMEM ="  Mash temp:";
const prog_uchar s40[] PROGMEM ="  Time left:";
const prog_uchar s41[] PROGMEM ="BACK   CHANGE   STOP"; 

const prog_uchar s42[] PROGMEM ="    Mash Complete!  ";
const prog_uchar s43[] PROGMEM =" BACK  HLT ON   BOIL";
const prog_uchar s44[] PROGMEM ="              START ";
const prog_uchar s45[] PROGMEM ="BACK          SPARGE";
const prog_uchar s46[] PROGMEM ="     Sparge  in  ";
const prog_uchar s47[] PROGMEM ="      Progress ";
const prog_uchar s48[] PROGMEM ="               START";
const prog_uchar s49[] PROGMEM =" BACK  HLT OFF  BOIL";

const prog_uchar s50[] PROGMEM ="  Boil temp:";
const prog_uchar s51[] PROGMEM ="BACK           CHILL";
const prog_uchar s52[] PROGMEM ="BACK     OFF     END";
const prog_uchar s53[] PROGMEM ="BACK     ON     END";

const prog_uchar s54[] PROGMEM ="   Boil finished!";
const prog_uchar s55[] PROGMEM ="CHANGE   ON    CHILL";
const prog_uchar s56[] PROGMEM ="CHANGE   OFF   CHILL";

const prog_uchar s57[] PROGMEM ="      Chilling      ";
const prog_uchar s58[] PROGMEM =" Chilling Finished! ";
const prog_uchar s59[] PROGMEM ="   Wort temp:";
const prog_uchar s60[] PROGMEM ="   Boil Finished!   ";

const prog_uchar s61[] PROGMEM =" BREWDAY  FINISHED! ";
const prog_uchar s62[] PROGMEM ="   Time:";   
const prog_uchar s63[] PROGMEM ="  Here's to a good  ";
const prog_uchar s64[] PROGMEM ="       Beer!        ";

const prog_uchar s65[] PROGMEM ="   Sparge Liquor ";
const prog_uchar s66[] PROGMEM ="      Temp:";
const prog_uchar s67[] PROGMEM ="BACK";

const prog_uchar s68[] PROGMEM =" UP    HOURS    DOWN";
const prog_uchar s69[] PROGMEM =" UP    MINS     DOWN";
const prog_uchar s70[] PROGMEM =" Cooking  Complete  ";

const prog_uchar s71[] PROGMEM ="  Cook Temp:";
const prog_uchar s72[] PROGMEM ="  Cook Time:";
const prog_uchar s73[] PROGMEM ="    Change  mins";
const prog_uchar s74[] PROGMEM ="BACK   CHANGE    OFF";
const prog_uchar s75[] PROGMEM ="BACK   CHANGE     ON"; 
const prog_uchar s76[] PROGMEM ="Pump";
const prog_uchar s77[] PROGMEM ="    Bon app tit!    ";

void PrintText (const prog_uchar str[]){ //
  char c;                                // 
  if(!str) return;                       //print text stored in ProgMem
  while((c = pgm_read_byte(str++)))      //
  lcd.print(c);}                    //

//-------------------------------------//

void StartScreen(){

/*          Welcome!
       what do you want
            to do?
    COOK S-V        BREW */
    
  lcd.clear();
  PrintText (s01);
  lcd.setCursor (0,1);
  PrintText (s02);
  lcd.setCursor (0,2);
  PrintText (s03);
  lcd.setCursor (0,3);
  PrintText (s04);
  Serial.begin(9600);
  sensors.begin();
  while (mode==0){                 //
    i  f (button1.update()) {        //Initiates Sous Vied cooking mode
      Serial.println("into cooking ");
      if (button1.read()==HIGH) {  //
          mode=COOK;               //
          }
         }
    if (button3.update()) {
      if (button3.read()==HIGH) {
          mode=BREW;         
          Serial.println("into brewing");
          }
         }
        }
       }
       
//-------------------------------------//

void CookWelcome(){

/*    Welcome to Fil's
      Sous Vide Cooker!
      Press any button  
        to go forward   */

  lcd.clear();
 while (CookMenu==1){
  PrintText (s09);
  lcd.setCursor(0,1);
  PrintText(s10);
  lcd.setCursor(0,2);
  PrintText (s11);
  lcd.setCursor(0,3);
  PrintText (s12);
  
   if (button1.update()||button2.update()||button3.update()) {
     if ((button1.read()||button2.read()||button3.read())==HIGH){
        CookMenu++;
        CookStartTime=millis();
        }
       }
      }
     }
     
//-------------------------------------//

void Cooking(){
  
/*    Cook Temp: 56.2°C
         Target: 56.0°C
      Time Left: 1h 38m
    BACK   CHANGE    OFF  */

  lcd.clear();
  float h,m;
  unsigned long over;
  CookTime=(CookHrs*3600000)+(CookMins*60000);
  CookHrsSet=false;
  CookMinsSet=false;
while (CookMenu==2){  
  if ((sensors.getDeviceCount())==0){      //
      Serial.println("Failed device count cook");
      Serial.print("num of sensors found = ");
      Serial.print(sensors.getDeviceCount());
     lcd.setCursor(0,0);                 //
     PrintText (s20);                    //
     lcd.setCursor(0,1);                 // Display warning
     lcd.print(" *temprature probe* ");  // if temp probe
     lcd.setCursor(0,2);                 // not attached  
     lcd.print("   *not attached!*  ");  // 
     lcd.setCursor(0,3);                 //
     PrintText (s20);                    //
   }else{
   time = CookTime - (millis()-CookStartTime)/60000;
   h=int(time/3600000);
   over=time%3600000;
   m=int(over/60000);
   sensors.requestTemperatures();
   Mash_CookTemp=sensors.getTempCByIndex(2);
   Input = Mash_CookTemp;
   Setpoint = CookTarget;
   myPID.Compute();
   if(millis() - windowStartTime>WindowSize){
   windowStartTime += WindowSize;}
   if(Output > millis() - windowStartTime) digitalWrite(Mash_CookRelay,HIGH);
   else digitalWrite(Mash_CookRelay,LOW);
   PrintText(s71);
   lcd.print(Mash_CookTemp);
   lcd.setCursor(16,0);
   degC();
   lcd.setCursor(0,1);
   PrintText(s34);
   lcd.print(CookTarget);
   lcd.setCursor(0,2);
   PrintText(s40);
   lcd.print(h,0);
   lcd.print("h ");
   lcd.print(m,0);
   lcd.print("m ");
   lcd.setCursor(0,3);
   PrintText(s74);
      
   PumpControl();    //HERMS pump used to recirculate water to maintain uniform water temp.
   CookMenuButons(); //back - forward buttons
   
    if (button2.update()){        //
      if (button2.read()==HIGH){  //Change target cooking temp.
         CookTargetSet=false;     //
      }
    }  

    /* Cook Temp: 56.2°C
          Target: 58.0°C
       Time Left: 2h 38m
      UP    HOURS    DOWN  */ 
    
   while (!CookTargetSet){
       lcd.setCursor(0,3);
       PrintText(s68);
    if (button1.update()) {
      if (button1.read()) {
         CookTarget++;
         }
        }  
   if (button3.update()) {
     if (button3.read()) {
         CookTarget--;
         }
        }
   lcd.setCursor(12,1);
   lcd.print(CookTarget);
   degCTarget();
  if (CookTarget > 100){
      CookTarget=0;}
  if (CookTarget < 100){
      lcd.setCursor(14,1);
      degCTarget();}
  if (CookTarget < 10){
      lcd.setCursor(13,1);
      degCTarget();}
  if (button2.update()) {
   if (button2.read()){
     lcd.setCursor(0,3);
     PrintText(s68);
     CookTargetSet=true;
     CookMenu++;
     }
    }
   } 
   if (time<60000)CookMenu=5;
  }
 }
}
//-------------------------------------//

void CookTimeSetHours(){

/*    Cook Temp: 56.2°C
         Target: 56.0°C
      Time Left: 3h 8m
    UP     MINS     DOWN  */ 

  while (CookMenu==3){
       lcd.setCursor(12,2);
       lcd.print(CookHrs);
       if (CookHrs > 72){
    CookHrs=0;}
     if (CookHrs < 10){
      lcd.setCursor(11,2);}
     if (CookHrs < 0){
      CookHrs = 72;}
      lcd.setCursor(0,3);
      PrintText(s69);
    if (button1.update()) {
     if (button1.read()) {
        CookHrs++;
        }  
       }
     if (button3.update()) {
      if (button3.read()) {
        CookHrs--;
        }
       }
 if (button2.update()) {
   if (button2.read()){
     lcd.setCursor(0,3);
     PrintText(s69);
     CookMenu++;
   }
  }
 }   
}

//-------------------------------------//

void CookTimeSetMins(){

/*    Cook Temp: 56.2°C
         Target: 56.0°C
      Time Left: 3h 15m
    UP      SET     DOWN  */ 

  while (CookMenu==4){
     lcd.setCursor(15,2);
     lcd.print(CookMins);
     if (CookMins > 59){
        CookMins=0;}
     if (CookMins < 1){
        CookMins=59;}
     if (CookHrs < 10){
      lcd.setCursor(14,2);
      degCTarget();}
       lcd.setCursor(0,3);
       PrintText(s23);
    if (button1.update()) {
     if (button1.read()) {
        CookMins++;
        }  
       }
   if (button3.update()) {
     if (button3.read()) {
       CookMins--;
       }
      }
   if (button2.update()) {
     if (button2.read()){
        CookMenu=2;
   }
  }
 }
}

//-------------------------------------//
 
void CookFinished(){
 
/*    Cooking  Complete

         Bon appétit!    */

  lcd.clear();
  digitalWrite(Mash_CookRelay,LOW);
 while (CookMenu==5){
  PrintText(s70);
  lcd.setCursor(0,1);
  lcd.print("                    ");
  lcd.setCursor(0,3);
  PrintText(s77);
  lcd.setCursor(0,3);
  lcd.setCursor(10,3);
  lcd.write(eAcute);
 }
}

//-------------------------------------//

void BrewWelcome(){

/*  Welcome to Fil's
        Brewery
    Press any button
     to go forward    */
  Serial.println("started brewing");
  lcd.clear();
  PrintText(s05);
  lcd.setCursor(0,1);
  PrintText(s06);
  lcd.setCursor(0,2);
  PrintText(s07);
  lcd.setCursor(0,3);
  PrintText(s08);
  
 while (BrewMenu==1){
   if (button1.update()||button2.update()||button3.update()) {
      if ((button1.read()||button2.read()||button3.read())==HIGH){
        BrewMenu++;
    }
   }
  }
 }

//-------------------------------------//

void BrewStart(){

/*      HLT: 22.5°C
         MT: 21.8°C
     Boiler: 22.1°C
    PRESS ANY BUTTON   */

  BrewStartTime = millis(); 
  lcd.clear();
  lcd.setCursor(0,0);
  PrintText(s13);  
  lcd.setCursor(0,1);
  PrintText(s14);  
  lcd.setCursor(0,2);
  PrintText(s15); 
  lcd.setCursor(0,3);
  PrintText(s16);
  Serial.println("testing sensors?");
  Serial.print(" brewmenu?= ");
  Serial.print(BrewMenu);
  
 while (BrewMenu==2){
   if (sensors.getDeviceCount()<3){      //
       Serial.println(sensors.getDeviceCount());
     lcd.setCursor(0,0);                 //
     PrintText (s20);                    //
     lcd.setCursor(0,1);                 // Display warning if
     lcd.print("*I HATE DEBUGGIN!");  // all 3 temp probes 
     lcd.setCursor(0,2);                 // are not attached  
     lcd.print("Fil's BrewPuter.. ");
     lcd.print(sensors.getDeviceCount());  // 
     lcd.setCursor(0,3);                 //
      lcd.print("Comming Soon *  ");
     PrintText (s20);                    //
   }else{
    sensors.requestTemperatures();
    HLTtemp=sensors.getTempCByIndex(1);
    Mash_CookTemp=sensors.getTempCByIndex(2);
    BoilTemp=sensors.getTempCByIndex(0);
    lcd.setCursor(11,0);
    lcd.print (HLTtemp);
   if (HLTtemp<10){
      lcd.setCursor(14,0);
      degC();
   }else{
    lcd.setCursor(15,0);
    degC();}    
    lcd.setCursor(11,1);
    lcd.print(Mash_CookTemp);
   if (Mash_CookTemp<10){
      lcd.setCursor(14,1);
      degC();
   }else{
    lcd.setCursor(15,1);
    degC();}
    lcd.setCursor(11,2);
    lcd.print(BoilTemp);
   if (BoilTemp<10){
      lcd.setCursor(14,2);
      degC();
   }else{
    lcd.setCursor(15,2);
    degC();}
   if (button1.update()||button2.update()||button3.update()) {
      if ((button1.read()||button2.read()||button3.read())==HIGH){
        BrewMenu++;
    }
   }
  }
 }
}

//-------------------------------------//

void MashLiquorHeating(){ 

  /* Mash liquor heating
     HLT temp:62.7°C
       Target:78.0°C
   CHANGE    OFF   MASH  */
   
  digitalWrite(Mash_CookRelay,LOW);
  digitalWrite(BoilerRelay,LOW);
  analogWrite (HERMSpumpFET,0);
  lcd.clear();
 while (BrewMenu == 3){
   sensors.requestTemperatures();
   HLTtemp=sensors.getTempCByIndex(1);
   lcd.setCursor(0,1);
   PrintText(s33);
   lcd.print(HLTtemp);
   if (HLTtemp<10){
      lcd.setCursor(15,1);
      degC();
   }else{
    lcd.setCursor(16,1);
    degC();}
   lcd.setCursor(0,2);
   PrintText(s34);
   lcd.print(HLTtarget);
   degCTarget();
     
   if (button3.update()) {
    if (button3.read() == HIGH) {
     BrewMenu++; 
    }
   }
  if (button1.update()) {
    if (button1.read() == HIGH) {
     set=false;
     }
    }
     while (!set){
       lcd.setCursor(0,3);
       PrintText(s23);
         if (button1.update()) {
    if (button1.read()) {
      HLTtarget++;
      }
     }  
   if (button3.update()) {
    if (button3.read()) {
      HLTtarget--;
      }
     }
   lcd.setCursor(12,2);
   lcd.print(HLTtarget);
  if (HLTtarget<10){
    lcd.setCursor(14,2);
    degCTarget();
   }else{
    lcd.setCursor(15,2);
    degCTarget();}
  if (HLTtarget > 100){
      HLTtarget=0;}
  if (HLTtarget < 100){
      lcd.setCursor(14,2);
      degCTarget();}
  if (HLTtarget < 10){
      lcd.setCursor(13,2);
      degCTarget();}
    
  if (button2.update()) {
   if (button2.read()){
      set=true;
      }
     }  
    }
   if (button2.update()) {
    if (button2.read() == HIGH) {
     if (!HLTon) HLTon=true;
     else HLTon=false;
     }
    }
     HTLcontrol();
    }
   }

//-------------------------------------//

void HTLcontrol(){

/*  Mash liquor ready!!!
       HLT temp:78.1°C
         Target:78.0°C
     CHANGE    ON   MASH  */

   lcd.setCursor(0,3);
   analogWrite (HERMSpumpFET,0);
  if (!HLTon){
   PrintText(s36);
   digitalWrite(HLTrelay,LOW);
  }else{ 
   PrintText(s35);
  if (HLTtemp > HLTtarget){
    digitalWrite(buzzer,HIGH);
    digitalWrite(HLTrelay,LOW);
    lcd.setCursor(0,0);
    PrintText(s32);
  }else{ 
    digitalWrite(HLTrelay,HIGH);
    digitalWrite(buzzer,LOW);
    lcd.setCursor(0,0);
    PrintText(s31);
    }
   }
  }
  
//-------------------------------------//

void PumpControl(){    // Controls pump speed via MOSFET by reading potentiometer value
  PotValue = analogRead(PotPin);
  PotValue = map(PotValue, 0, 1023, 0, 255);
  analogWrite (HERMSpumpFET,PotValue); 
}

//-------------------------------------//

void MashStart(){

/*  Ready to start mash!
    Prime pump&fill HLT
     for sparge liquor
      PRESS ANY BUTTON    */
      
  lcd.clear();
   digitalWrite(buzzer,LOW);
   digitalWrite(HLTrelay,LOW);
  while (BrewMenu==4){
    PrintText(s17);
    lcd.setCursor(0,1);
    PrintText(s18);
    lcd.setCursor(0,2);
    PrintText(s19);
    lcd.setCursor(0,3);
    PrintText(s16);
    
    if (button1.update()||button2.update()||button3.update()) {
      if ((button1.read()||button2.read()||button3.read())==HIGH){
        BrewMenu++;
      }
    }
  }
}

//-------------------------------------//

void Mashing(){

/*    Mash temp:65.8°C
         Target:66.0°C
      Time left:38mins
    BACK   CHANGE   STOP  */
    
   lcd.clear();
   MashStartTime=millis();
  while (BrewMenu==5){ 
   sensors.requestTemperatures();
   Mash_CookTemp=sensors.getTempCByIndex(2);
   HLTtemp=sensors.getTempCByIndex(1);
   Input = Mash_CookTemp;
   Setpoint = MashTarget;
   myPID.Compute();
   if(millis() - windowStartTime>WindowSize){
   windowStartTime += WindowSize;}
   if(Output > millis() - windowStartTime) digitalWrite(Mash_CookRelay,HIGH);
  else digitalWrite(Mash_CookRelay,LOW);
   time = MashTime - (millis()-MashStartTime)/60000;
   PrintText(s39);
   lcd.setCursor(12,0);
   lcd.print(Mash_CookTemp);
   lcd.setCursor(16,0);
   degC();
   lcd.setCursor(0,1);
   PrintText(s34);
   lcd.print(MashTarget);
   degCTarget();
   lcd.setCursor(0,2);
   PrintText(s40);
   lcd.print (time);
   lcd.print("mins ");
   lcd.setCursor(0,3);
   PrintText(s41);
   
   SpargeLiquorHeating();  //heat sarge liquor whilst mashing
   PumpControl();
   
 if (time<1)BrewMenu++, analogWrite (HERMSpumpFET,0);
 
   if (button1.update()) {
    if (button1.read()) {
      digitalWrite (Mash_CookRelay, LOW);
      analogWrite (HERMSpumpFET,0);
      BrewMenu--;
      }
     }
 if (button3.update()) {
   if (button3.read()) {
     digitalWrite (Mash_CookRelay, LOW);
     analogWrite (HERMSpumpFET,0);
     BrewMenu++;
     }
    } 
 if (button2.update()) {
   if (button2.read() == HIGH) {
     set=false;
 while (!set){
     lcd.setCursor(0,3);
     PrintText(s23);
  if (button1.update()) {
    if (button1.read()) {
      MashTarget++;
     }
    }  
  if (button3.update()) {
   if (button3.read()) {
     MashTarget--;
    }
   }
   lcd.setCursor(12,1);
   lcd.print(MashTarget);
   degCTarget();
  if (MashTarget > 100){
    MashTarget=0;}
  if (MashTarget < 100){
    lcd.setCursor(14,1);
    degCTarget();
   }
  if (MashTarget < 10){
    lcd.setCursor(13,1);
    degCTarget();
   }
  if (button2.update()) {
    if (button2.read()){
    lcd.setCursor(0,0);
    set=true;
      }
     }
    }
   }
  }
 }
}

//-------------------------------------//

void SpargeLiquorHeating(){ 
  digitalWrite(BoilerRelay,LOW);
  sensors.requestTemperatures();
  HLTtemp=sensors.getTempCByIndex(1);
if (HLTtemp < SpargeTarget){
  digitalWrite (HLTrelay, HIGH);}
if (HLTtemp > SpargeTarget+5){
  digitalWrite (HLTrelay, LOW);}
}

//-------------------------------------//

void MashFinished(){

/*  Mash Complete!

            START
  BACK      SPARGE */

  digitalWrite(buzzer,HIGH);
  digitalWrite(Mash_CookRelay,LOW);
  digitalWrite(HLTrelay,LOW);
  lcd.clear();
 while (BrewMenu==6){
   PrintText(s42);
   lcd.setCursor(0,2);
   PrintText(s44);
   lcd.setCursor(0,3);
   PrintText(s45);
   BrewMenuButons();
 }
}

//-------------------------------------//

void Sparging(){ 

/*   Sparge  in
      Progress
               START
 BACK  HLT OFF  BOIL  */

 digitalWrite(buzzer,LOW);
 lcd.clear(); 
 while (BrewMenu==7){
   SpargeLiquorHeating();
   PrintText(s46);
   lcd.setCursor(0,1);
   PrintText(s47);
   lcd.setCursor(0,2);
   PrintText(s48);
   
   BrewMenuButons(); 
   SpargeLiquorHeating();
  
   if (button2.update()) {
    if (button2.read() == HIGH);{
      digitalWrite(HLTrelay, HIGH);
      lcd.setCursor(0,3);  
      PrintText(s49);}
    }else{
      digitalWrite(HLTrelay, LOW);
      lcd.setCursor(0,3);  
      PrintText(s43);}
 }
}

//-------------------------------------//

void Boiling(){
  
/*   Boil temp:88.0°C
        Target:100.0°C
     Time left:89mins
   BACK   CHANGE   STOP    */

   digitalWrite(HLTrelay,LOW);  
   digitalWrite(Mash_CookRelay,LOW);
   digitalWrite(buzzer,LOW);
   lcd.clear();
   
 while (BrewMenu==8){
   digitalWrite(HLTrelay,LOW);  
   digitalWrite(Mash_CookRelay,LOW);
   sensors.requestTemperatures();
   BoilTemp=sensors.getTempCByIndex(0);
  if (BoilTemp > 95){
   BoilStartTime=millis();}   
   time = BoilTime - (millis()-BoilStartTime)/60000;
   PrintText(s50);
   lcd.setCursor(12,0);
   lcd.print(BoilTemp);
  if (BoilTemp >= 100){lcd.setCursor(17,0);
   degC();
  }else{ 
   lcd.setCursor(16,0);
   degC();}
   lcd.setCursor(0,1);
   PrintText(s34);
   lcd.setCursor(12,1);
   lcd.print(BoilTarget);
   degCTarget();
   lcd.setCursor(0,2);
   PrintText(s40);
   lcd.setCursor(12,2);
   lcd.print(time);
   lcd.print("mins ");
   lcd.setCursor(0,3);
   PrintText(s41);
   if (time<1)BrewMenu++;
   if (BoilTarget>BoilTemp){
    digitalWrite(BoilerRelay, HIGH);
   }else{
    digitalWrite(BoilerRelay,LOW);}
  if (button3.update()) {
   if (button3.read()) {
    BrewMenu++;
  }
 }
   if (button1.update()) {
    if (button1.read() == HIGH) {
     digitalWrite (BoilerRelay,LOW);
     BrewMenu--; 
    }
   }   
   if (button2.update()) {
    if (button2.read() == HIGH) {
     set=false;
    while (!set){
       lcd.setCursor(0,3);
       PrintText(s23);
   if (button1.update()) {
    if (button1.read()) {
      BoilTarget++;
   }
  }  
   if (button3.update()) {
    if (button3.read()) {
      BoilTarget--;
    }
   }
   lcd.setCursor(12,1);
   lcd.print(BoilTarget);
   degCTarget();
  if (BoilTarget > 100){
    BoilTarget=0;}
  if (BoilTarget < 100){
    lcd.setCursor(14,1);
    degCTarget();}
  if (BoilTarget < 10){
      lcd.setCursor(13,1);
      degCTarget();}
  if (button2.update()){
    if (button2.read()){
      lcd.setCursor(0,0);
      set=true;
     }
    }
   }
  }
 }
 }
}

//-------------------------------------//

void BoilFinished(){

/*   Boil Finished!  


  BACK           CHILL  */

  lcd.clear();
 while (BrewMenu==9){
   digitalWrite(buzzer,HIGH);
   digitalWrite(HLTrelay,LOW);  
   digitalWrite(Mash_CookRelay,LOW);
   digitalWrite(BoilerRelay,LOW);
   PrintText(s60);
   lcd.setCursor(0,3);
   PrintText(s51);
   BrewMenuButons();
  }
}

//-------------------------------------//

void Chilling(){
  
  /*     Chilling    
      Wort temp:28.2°C
         Target:25.0°C
    BACK   CHANGE   STOP    */
   
  digitalWrite(buzzer,LOW);
    lcd.clear();
  while (BrewMenu==10){
    digitalWrite(HLTrelay,LOW);  
    digitalWrite(Mash_CookRelay,LOW);
    digitalWrite(BoilerRelay,LOW);
    sensors.requestTemperatures();
    BoilTemp=sensors.getTempCByIndex(0);
    PrintText(s57);
    lcd.setCursor(0,1);
    PrintText(s59);
    lcd.print(BoilTemp);
    lcd.setCursor(17,1);
    degC();
    lcd.setCursor(0,2);
    PrintText(s34);
    lcd.print(ChillTarget);
    degCTarget();
    lcd.setCursor(0,3);
    PrintText(s41);

  if (button3.update()) {
    if (button3.read() == HIGH) {
     BrewMenu++; 
     }
   }
  if (button1.update()) {
    if (button1.read() == HIGH) {
     BrewMenu--; 
    }
  }   
  if (button2.update()) {
    if (button2.read() == HIGH) {
     set=false;
   while (!set){
       lcd.setCursor(0,3);
       PrintText(s23);
   if (button1.update()) {
    if (button1.read()) {
      ChillTarget++;
    }
  }  
   if (button3.update()) {
    if (button3.read()) {
      ChillTarget++;
     }
   }
   lcd.setCursor(12,2);
   lcd.print(ChillTarget);
   degCTarget();
  if (ChillTarget > 100){
    ChillTarget=0;}
    if (ChillTarget < 100){
      lcd.setCursor(14,2);
      degCTarget();
    }
    if (ChillTarget < 10){
      lcd.setCursor(13,2);
      degCTarget();
    }
if (button2.update()) {
      if (button2.read()){
      set=true;
    }
  }  
}
   if (button2.update()) {
    if (button2.read() == HIGH) {
     if (!ChillOn) ChillOn=true;
     else ChillOn=false;
     }
    }
   }     
  }
 }
}

//-------------------------------------//

void ChillingControl(){
   lcd.setCursor(0,3);
  if (!ChillOn){
   PrintText(s36);
   digitalWrite(HLTrelay,LOW);
  }else{ 
   PrintText(s35);
  if (BoilTemp > ChillTarget){
    digitalWrite(buzzer,HIGH);
    lcd.setCursor(0,0);
    PrintText(s32);
  }else{
    digitalWrite(buzzer,LOW);
    lcd.setCursor(0,0);
    PrintText(s31);
    }
   }
  }
  
//-------------------------------------//

void BrewdayFinished(){
  
  /*  BREWDAY  FINISHED!
       Time:6hrs 35mins
       Here's to a good
           Beer!     */
 
  float h,m;
  unsigned long over;
  BrewEndTime=millis();
  BrewDuration=BrewEndTime-BrewStartTime;
  h=int(BrewDuration/3600000);
  over=BrewDuration%3600000;
  m=int(over/60000);
  lcd.clear();
  while (BrewMenu==11){
    PrintText(s61);
    lcd.setCursor(0,1);
    PrintText(s62);
    lcd.print(h,0);
    lcd.print("hrs ");
    lcd.print(m,0);
    lcd.print("mins"); 
    lcd.setCursor(0,2);
    PrintText(s63);
    lcd.setCursor(0,3);
    PrintText(s64);
      }
    }

void CookMenuButons(){             //Back and forward cook menu buttons
  if (button1.update()){           
    if (button1.read() == HIGH){   
      if (CookMenu>1) CookMenu--;  
      }                            
    }                               
    if (button3.update()){         
      if (button3.read()==HIGH){   
         CookMenu++;                
    }                              
  }
}

void BrewMenuButons(){            //Back and forward brew menu buttons
  if (button1.update()){      
    if (button1.read()==HIGH){
      if (BrewMenu>1) BrewMenu--;   
      }
    }
    if (button3.update()){
      if (button3.read()==HIGH){
         BrewMenu++;
    }
  }
}

void degC(){            //prints '°C' and masks the two  
  lcd.print((char)223); //least signigicant figures from
  lcd.print("C  ");     //temp sensor reading
}
void degCTarget(){      //
  lcd.print(".0");      //prints '0°C'
  lcd.print((char)223); //
  lcd.print("C ");      //
}
   
void setup(){
  lcd.begin(20,4);
  sensors.begin();
  pinMode (Mash_CookRelay,OUTPUT);
  pinMode(HLTrelay,OUTPUT);
  pinMode (BoilerRelay,OUTPUT); 
  
  windowStartTime = millis();           //
  myPID.SetOutputLimits(0, WindowSize); //PID set-up
  myPID.SetMode(AUTOMATIC);             //
  
  lcd.createChar(eAcute,CustomChar);//initialse custom letter 'é'
}

void loop(){    
    
 switch (mode) {
    case 0:
     StartScreen();
    break;
    case 1:
     switch (CookMenu){
       case 1:
        CookWelcome ();
       break;
       case 2:
        Cooking ();
       break;
       case 3:
       CookTimeSetHours();
       break;
       case 4:
       CookTimeSetMins();
       break;
       case 5:
       CookFinished();
       break;
   }
    break;
    case 2:
      switch (BrewMenu){
        case 1:
         BrewWelcome ();
        break;
        case 2:
         BrewStart();
        case 3:
         MashLiquorHeating();
        break;
        case 4:
         MashStart();
        break;
        case 5:
         Mashing();
        break;
        case 6:
         MashFinished();
        break;
        case 7:
         Sparging();
        break;
         case 8:
         Boiling();
        break;
        case 9:
         BoilFinished();
        break;
        case 10:
         Chilling();
        break;
        case 11:
         BrewdayFinished();
        break;
      }
      break;
   }
}
 
Back
Top