#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal_I2C.h>
//#include <Time.h>
// Data wire (containing the Temp Sensors) is plugged into pin 3 on the Arduino
#define ONE_WIRE_BUS 3
// Setup a oneWire instance to communicate with any OneWire device
OneWire oneWire(ONE_WIRE_BUS);
// Pass the oneWire reference to Dallas Temperature.
DallasTemperature sensor(&oneWire);
// Assign the addresses of the 1-Wire DS18B20 Temp sensors.
DeviceAddress TEMPSENSOR = { 0x28, 0xC3, 0x14, 0xAC, 0x04, 0x00, 0x00, 0x9E };
//LCD Library
LiquidCrystal_I2C lcd(0x38);
const char degree = 223; //Degree symbol
//////////////////////BLYNK CODE
#define BLYNK_PRINT Serial // Comment this out to disable prints and save space
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "da8b62f0ecec4fd283a1121c7821b6c4";
//////////////////////USER INPUTS from Blynk Terminal
BLYNK_WRITE(V0) // Terminal
{
String fromTerminal = param.asStr();
if (fromTerminal.endsWith("MASHTEMP") ){
float MASHTEMP = fromTerminal.toFloat();
}
else if (fromTerminal.endsWith("MASHTIME") ) {
const int MASHTIME = fromTerminal.toFloat();
}
else if (fromTerminal.endsWith("BOILTIME") ) {
const int BOILTIME = fromTerminal.toFloat();
}
else if (fromTerminal.endsWith("CHILLTIME") ) {
const int CHILLTIME = fromTerminal.toFloat();
}
else if (fromTerminal.endsWith("HOPADDS") ) {
const int HOPADDS = fromTerminal.toFloat();
}
else {
string HAPADDSINFO = fromTerminal;
}
}
////////Setting up variables to be declared by Blynk app
const int MASHTEMP; // Desired Mash Temp(deg F)
const int MASHTIME; //Desired Mash Time(milli sec.)
const int BOILTIME; //Desired Boil Time(milli sec.)
const int CHILLTIME; //Desired time to pump all wort through the wort chiller (milli sec.)
//HOP ADDITIONS, HOPADDS and HOPADDSINFO must be the same array length
int HOPADDS []; //Hop times
const char* HOPADDSINFO []//Hop adds contents
float HopAddtime; //Creating variable for for loop below
int h; //Declare the for loop variable
////////////////////////Assign variables
float mashtanktemp; //Declaring temperature variables
unsigned long minutes = (millis()/60000); //Code to switch elapsed time from milliseconds to minutes
unsigned long MashStartTime; //used for MASH TIME
unsigned long ElapsedMashTime; //Time minutes-mashstarttime
unsigned long BoilStartTime; //used for BOIL TIME
unsigned long ElapsedBoilTime; // time minutes-boilstarttime
unsigned long ChillStartTime; //used for BOIL TIME
unsigned long ElapsedChillTime; // time minutes-boilstarttime
//Setup all states
boolean mashcycle = true;
boolean premash;
boolean mashstart;
boolean mashrun;
boolean mashend;
boolean boilcycle;
boolean preboil;
boolean boilstart;
boolean boilrun;
boolean boilend;
boolean chillstart;
boolean chillrun;
boolean chillend;
//Pin Inputs/Outputs to Arduino:
//BUZZER module = Pin 5, called by tone function so doesnt need to be initialized
const int PUMP = 9;
const int HEATER1 = 10;
const int HEATER2 = 11;
const int START = 0;
const int PAUSE = 1;
const int PUMPBUTTON = 2;
const int HEATER1BUTTON = 3;
const int HEATER2BUTTON = 4;
//Status variables for buttons
int val_start = 0;
int val_pause = 0;
int val_pumpbutton = 0;
int val_heater1button = 0;
int val_heater2button = 0;
void setup()
{
// start serial port to report back values and status
Serial.begin(9600);
//Start Blynk
Blynk.begin(auth,"ssid", "pass");
// Start up the library
sensor.begin();
// set the resolution to 9 bit
sensor.setResolution(TEMPSENSOR, 9); //Resolution of 9 means 0.5degC increments.
//initialize pin locations as output or input
pinMode(PUMP, OUTPUT);
pinMode(HEATER1, OUTPUT);
pinMode(HEATER2, OUTPUT);
pinMode(START, INPUT);
pinMode(PAUSE, INPUT);
pinMode(PUMPBUTTON, INPUT);
pinMode(HEATER1BUTTON, INPUT);
pinMode(HEATER2BUTTON, INPUT);
//Initialize LCD to 16 characters by 2 lines
lcd.begin(16, 2);
//lcd.setBacklightPin(3,POSITIVE); MIGHT NEED TO CONTROL BACKLIGHT ETC
//lcd.setBacklight(HIGH);
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("Phil's beer is on the way, Ready?");
}
//The Control System script starts here:
void loop()
{
Blynk.run();
timer.run();
val_start = digitalRead(START);
val_pause = digitalRead(PAUSE);
val_pumpbutton = digitalRead(PUMPBUTTON);
val_heater1button = digitalRead(HEATER1BUTTON);
val_heater2button = digitalRead(HEATER2BUTTON);
if (val_start == HIGH && val_pause == HIGH){
analogWrite(HEATER1, 0);
analogWrite(HEATER2, 0);
analogWrite(PUMP, 0);
lcd.clear();
lcd.setCursor(0,1);
lcd.print("Start and Pause Pressed, Fix issue");
delay(1000);
}
if (val_start == LOW && val_pause == HIGH){
analogWrite(HEATER1, 0);
analogWrite(HEATER2, 0);
analogWrite(PUMP, 0);
lcd.clear();
lcd.setCursor(0,1);
lcd.print("Manual Pause");
delay(1000);
}
if (val_start == LOW && val_pause == LOW && val_pumpbutton == HIGH){
tone(5, 500, 5000);
lcd.clear();
lcd.setCursor(0,1);
lcd.print("Pump starting, need to open ball valve!!");
delay(30000);
analogWrite(PUMP, 255);
lcd.clear();
lcd.setCursor(0,1);
lcd.print("Manual Pump On");
delay(1000);
}
if (val_start == LOW && val_pause == LOW && val_heater1button == HIGH){
tone(5, 500, 5000);
lcd.clear();
lcd.setCursor(0,1);
lcd.print("Heat 1 starting, need cover w water!!");
delay(30000);
analogWrite(HEATER1, 255);
lcd.clear();
lcd.setCursor(0,1);
lcd.print("Manual Heater 1 On");
delay(1000);
}
if (val_start == LOW && val_pause == LOW && val_heater2button == HIGH){
tone(5, 500, 5000);
lcd.clear();
lcd.setCursor(0,1);
lcd.print("Heat 2 starting, need cover w water!!");
delay(30000);
analogWrite(HEATER2, 255);
lcd.clear();
lcd.setCursor(0,1);
lcd.print("Manual Heater 2 On");
delay(1000);
}
if (val_start == HIGH && val_pause == LOW && val_pumpbutton == LOW && val_heater1button == LOW && val_heater2button == LOW){
delay(2000); //give a reading every 2.0 sec
sensor.requestTemperatures();
mashtanktemp = sensor.getTempF(TEMPSENSOR);
ElapsedMashTime = minutes-MashStartTime; //If this global formulas dont work then have to put the raw formula into each line like it used to be
ElapsedBoilTime = minutes-BoilStartTime;
ElapsedChillTime = minutes-ChillStartTime;
//////////////////SETTING UP STATES CODE
//premash
if (mashtanktemp < MASHTEMP && mashcycle == true) {
premash=true;
}
//mashstart
if (mashtanktemp >= MASHTEMP - 2.0 && mashtanktemp <= MASHTEMP + 2.0 && premash == true) {
mashstart = true;
premash=false;
}
//mashrun
if (mashstart = true) {
MashStartTime = minutes;
mashrun = true;
mashstart = false;
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("Mash Elapsed Time Test: Should be very low");
lcd.print(ElapsedMashTime);
delay(1000);
}
//mashsend
if (ElapsedMashTime >= MASHTIME) {
mashend = true;
mashrun = false;
mashcycle = false;
}
//preboil
if (mashend = true) {
boilcycle = true;
preboil = true;
mashend= false;
}
//boilstart
if (preboil = true && mashtanktemp >= 212) {
boilstart = true;
preboil = false;
}
//boilrun
if (boilstart = true) {
BoilStartTime = minutes;
boilrun = true;
boilstart = false;
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("Boil Elapsed Time Test: Should be very low");
lcd.print(ElapsedBoilTime);
delay(1000);
}
//boilend
if (ElapsedBoilTime >= BOILTIME) {
boilend = true;
boilrun = false;
boilcycle = false;
}
//chill start
if (boilend = true && mashtanktemp <= 100) {
chillstart = true;
boilend = false;
}
//chill run
if (chillstart = true) {
ChillStartTime = minutes;
chillrun = true;
chillstart = false;
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("Chil Elapsed Time Test: Should be very low");
lcd.print(ElapsedChillTime);
delay(1000);
}
//chill end
if (ElapsedChillTime >= CHILLTIME) {
chillend = true;
chillrun = false;
}
////////////////////ACTIONS CODES
//premash = Heater 1 & 2 on, pump on
if (premash = true) {
tone(5, 500, 5000);
lcd.clear();
lcd.setCursor(0,1);
lcd.print("Pump & Heat starting, need to open ball valve!!");
delay(10000);
analogWrite(HEATER1, 255);
analogWrite(HEATER2, 255);
analogWrite(PUMP, 255);
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("T:");
lcd.print(mashtanktemp);
lcd.print(degree);
lcd.print("F");
lcd.setCursor(0, 2);
lcd.print(" Pump and Heaters On");
delay(1000);
}
//mashrun == mashstart is skipped because that is only used to initialize the time, mashrun heaters off, pump on
if (mashrun = true) {
analogWrite(HEATER1, 0);
analogWrite(HEATER2, 0);
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("Mash Temp hit");
lcd.print(mashtanktemp);
lcd.print(degree);
lcd.print("F");
delay(1000);
}
//mashend = heaters both on, pump off
if(mashend = true){
analogWrite(HEATER1, 255);
analogWrite(HEATER2, 255);
analogWrite(PUMP, 0);
tone(5, 500, 2000);
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("Mash Complete, heat on, pump off");
lcd.print(mashtanktemp);
lcd.print(degree);
lcd.print("F");
delay(1000);
}
//boilrun == skip preboil and boilstart as they are both just used to initialize the boil timer, boilrun hits heaters stay on (need to test to see if both heat needs to be on) pump off
if (boilrun = true){
analogWrite(HEATER1, 255);
analogWrite(HEATER2, 255);
analogWrite(PUMP, 0);
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("Boiling, heaters on, pump off");
lcd.print(mashtanktemp);
lcd.print(degree);
lcd.print("F");
delay(1000);
}
//Hop Additions Code
if (boilrun == true) {
for (h=0 ; h=sizeof(HOPADDS); 1) {
HopAddtime = HOPADDS[h];
if (ElapsedBoilTime >= (HopAddtime - 1) && ElapsedBoilTime <= (HopAddtime + 1)) { //BE SURE THAT THE +/- of the elapsedboil time doesnt result in overlay of two hop additions or else it could be confusing
tone(5, 500, 2000);
lcd.setCursor(0,1);
lcd.print(ElapsedBoilTime);
lcd.print("Add");
lcd.print(HOPADDSINFO[h]);
delay(15000);
}
}
}
//boilend = heat off , pump off
if (boilend = true){
chillrun = true;
boilend = false;
analogWrite(HEATER1, 0);
analogWrite(HEATER2, 0);
analogWrite(PUMP, 0);
lcd.setCursor(0, 1);
lcd.print("Boil Complete");
lcd.print(mashtanktemp);
lcd.print(degree);
lcd.print("F");
delay(1000);
}
//chillrun = skip chillstart as that just initialized the chill timer, chill run turn pump on
if (chillrun = true){
tone(5, 500, 2000);
lcd.clear();
lcd.setCursor(0,1);
lcd.print("Pump starting, need to open ball valve!!");
delay(10000);
analogWrite(HEATER1, 0);
analogWrite(HEATER2, 0);
analogWrite(PUMP, 127);
}
//chillend == turn pump off once chill time is over THIS NEEDS TO BE TEST AND FIGURED OUT.
if (chillend = true){
tone(5, 500, 5000);
analogWrite(PUMP, 0);
analogWrite(HEATER1, 0);
analogWrite(HEATER2, 0);
lcd.clear();
lcd.setCursor(0,1);
lcd.print("Auto Brewing Complete");
}
}
}
Hardware context:
2 heating elements, one water pump
one temperature sensor
5 buttons: Start Auto code, Pause to stop code, 3 buttons to independently control the heating elements and pumps as needed