/*
brauduino semi automated single vessel RIMS
created by s.mathison
Copyright (C) 2012 Stephen Mathison
compiled on Arduino V1.0
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .*/
//libraries
#include
#include
#include
#include
OneWire ds(11);
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
// push buttons
const char Button_up = A3;
const char Button_dn = A2;
const char Button_prev = A1;
const char Button_nxt = A0;
// outputs
const int Heat = 9;
const int Pump = 8;
const int Buzz = 10;
// global variables
unsigned int WindowSize;
unsigned long windowStartTime;
unsigned long start;
double Setpoint, Input, Output,eepromKp, eepromKi, eepromKd;
//boolean autoLoop = false;
boolean manualLoop = false;
boolean waterAdd = false;
boolean Conv_start = false;
boolean mpump = false;
boolean mheat = false;
boolean wtBtn = false;
boolean autoEnter = false;
boolean tempReached = false;
boolean pumpRest = false;
//boolean boilLoop = false;
boolean resume = false;
float mset_temp = 35;
float Temp_c, stageTemp,pumptempError,Temp_PID;
int x;
int stageTime,hopTime;
byte mainMenu = 0;
byte pumpTime;
byte data[2];
byte second;
//byte minute;
//byte i;
byte Busy = 0;
byte nmbrStgs;
byte nmbrHops;
byte tempHAddr;
byte tempLAddr;
byte timeAddr;
byte blhpAddr;
byte hopAdd;
char* stgName[] ={
"MashIn","Stage1","Stage2","Stage3","Stage4","Stage5","Stage6","Stage7","Stage8","Boil "};
// degree c sybmol
byte degc[8] =
{
B01000,
B10100,
B01000,
B00011,
B00100,
B00100,
B00011,
B00000,
};
//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint,100,20,5, DIRECT);
//****** start of the funtions**************
void Buzzer(int number)
{
for (int i=0; i < number; i++)
{
digitalWrite (Buzz,HIGH);
delay (500);
digitalWrite(Buzz,LOW);
delay(100);
}
}
void pause_stage(void){
boolean stage_pause = false;
if (Button_1sec_press(Button_prev)){
Buzzer(1);
stage_pause = true;
digitalWrite(Heat,LOW);
digitalWrite(Pump,LOW);
display_lcd(0,0," Paused " );
while (stage_pause)
{
if (Button_1sec_press(Button_prev))stage_pause=false;
}
}
}
void display_lcd (int pos , int line ,const char* lable){
lcd.setCursor(pos,line);
lcd.print(lable);
}
// 1 second button press
int Button_1sec_press (int Button_press){
if (digitalRead(Button_press)==0){
delay (1000);
if (digitalRead(Button_press)==0){
lcd.clear();
while(digitalRead(Button_press)==0){
}
return 1;
}
}
return 0;
}
// repeat button press
int Button_repeat (int Button_press){
if (digitalRead(Button_press)==0){
delay(200);
return 1;
}
return 0;
}
// holds whilst button pressed
int Button_hold_press (int Button_press){
if (digitalRead (Button_press)==0){
delay(50);
while (digitalRead (Button_press)==0){
}
return 1;
}
return 0;
}
// reads the DS18B20 temerature probe
void Temperature(void){
ds.reset();
ds.skip();
// start conversion and return
if (!(Conv_start)){
ds.write(0x44,0);
Conv_start = true;
return;
}
// check for conversion if it isn't complete return if it is then convert to decimal
if (Conv_start){
Busy = ds.read_bit();
if (Busy == 0){
return;
}
ds.reset();
ds.skip();
ds.write(0xBE);
for ( int i = 0; i < 2; i++) { // we need 2 bytes
data[i] = ds.read();
}
unsigned int raw = (data[1] 5){
digitalWrite(Heat,HIGH);
if ((Setpoint - Input)WindowSize)
{ //time to shift the Relay Window
windowStartTime += WindowSize;
}
if((Output*(WindowSize/100)) > now - windowStartTime) digitalWrite(Heat,HIGH);
else digitalWrite(Heat,LOW);
}
}
void load_pid_settings (void)
{
eepromKp = word(EEPROM.read(0),EEPROM.read(1));// read the PID settings from the EEPROM
eepromKi = word(EEPROM.read(2),EEPROM.read(3));
eepromKd = word(EEPROM.read(4),EEPROM.read(5));
eepromKi = eepromKi/100;
myPID.SetTunings(eepromKp,eepromKi,eepromKd); // send the PID settings to the PID
WindowSize = word(EEPROM.read(33),EEPROM.read(34));
myPID.SetOutputLimits(0, 100);
myPID.SetSampleTime(5000);
}
boolean wait_for_confirm (boolean& test)
{
wtBtn = true;
while (wtBtn){ // wait for comfirmation
if (Button_hold_press(Button_prev)){
test = true;
wtBtn = false;
lcd.clear();
}
if (Button_hold_press(Button_nxt)){
test = false;
wtBtn = false;
lcd.clear();
}
}
}
float change_temp(float& temp_change,int upper_limit,int lower_limit)
{
// Increase set temp
if (Button_repeat(Button_up)){
if (temp_change>=100){
temp_change++;
}
else{
temp_change+=0.25;
}
if (temp_change > upper_limit)temp_change = upper_limit;
}
// decrease temp
if (Button_repeat(Button_dn))
{
if(temp_change>=100){
temp_change--;
}
else{
temp_change-=0.25;
}
if ( temp_change < lower_limit) temp_change = lower_limit;
}
}
void quit_mode (boolean& processLoop)
{
if ((digitalRead(Button_dn)==0) && (digitalRead(Button_up)==0)){
digitalWrite(Heat,LOW);
digitalWrite(Pump,LOW);
processLoop = false;
lcd.clear();
}
}
void heat_control(void)
{
//turns heat on or off
if (Button_hold_press(Button_prev)){
if (mheat==false){
mheat = true;
windowStartTime = millis();
}
else{
mheat = false;
digitalWrite(Heat,LOW);
}
}
}
void pump_control(void)
{
//turns the pump on or off
if (Button_hold_press(Button_nxt)){
if (mpump == false){
mpump = true;
digitalWrite(Pump,HIGH);
}
else{
mpump = false;
digitalWrite(Pump,LOW);
}
}
}
void prompt_for_water (void){
display_lcd(0,0," Water added? ");
Buzzer(3);
display_lcd(0,1," Ok Quit");
}
void pump_prime(void)
{
lcd.clear();
lcd.print(" Pump Prime "); // priming the pump
digitalWrite(Pump,HIGH);
delay (1000);
digitalWrite(Pump,LOW);
delay(200);
digitalWrite(Pump,HIGH);
delay (1000);
digitalWrite(Pump,LOW);
delay(200);
digitalWrite(Pump,HIGH);
delay (1000);
digitalWrite(Pump,LOW);
lcd.clear();
}
void pump_rest (int stage)
{
if (stage==9){
pumpRest = false;
if (Temp_c= 95)tempReached = true;
}
else{
pumptempError = stageTemp-Temp_c;
if (pumptempError = 10)){ // pump rest
digitalWrite(Pump,LOW);
digitalWrite(Heat,LOW);
pumpRest = true;
if(pumpTime>=12 || (pumptempError > 1.0))pumpTime = 0;
}
}
}
void check_for_resume(void){
if(EEPROM.read(35)){ // read the auto started byte to see if it has been set and if so ask to resume
display_lcd (0,0," Resume Process?");
display_lcd (0,1," Yes No");
wait_for_confirm(resume);
if(resume==true){
tempHAddr = (EEPROM.read(36)*3)+6;
tempLAddr = tempHAddr+1;
timeAddr = tempHAddr+2;
x = EEPROM.read(36);
autoEnter = true;
lcd.clear();
}
}
}
void load_stage_settings (void){
tempHAddr = 6; // setup intitial stage addresses
tempLAddr = 7;
timeAddr = 8;
nmbrStgs = EEPROM.read(38);// read the number of steps
nmbrHops = EEPROM.read(39);//read the number of hop additions
}
void start_time (void)
{
start = millis();
// windowStartTime = millis();
second = 0;
// minute = 0;
}
void stage_timing (int stage)
{
if ((millis()-start)>1000){ // timing routine
start = millis();
second++;
if(!(tempReached))second=0;// starts counting down when temp reached
if (second>59){
display_lcd(10,0," ");
second = 0;
pumpTime++;
if(stage == 0)pumpTime = 0;
stageTime--;
EEPROM.write(37,lowByte(stageTime));// saves stage time incase of interuption
}
}
}
void hop_add (void)
{
if(hopAdd 0)&&(autoEnter)){
lastminute=stageTime;
stage_timing(stage);
Temperature();// get temp
pause_stage();
if (pumpRest){
display_lcd(0,0," Pump Rest ");
display_lcd(0,1," ");
}
else{
display_lcd(0,0,stgName[stage]);
display_lcd(6,0," ");
display_lcd(11,0,"T=");
lcd.print(stageTime);
display_lcd(0,1,"S/A=");
lcd.print(stageTemp);
display_lcd(9,1,"/");
lcd.print(Temp_c);
lcd.write((uint8_t)0);
}
change_temp(stageTemp,H_temp,L_temp);
pump_rest(stage);
if (pumpRest==false)PID_HEAT();
if (stage==9){
if(stageTime upper_limit)set_change = upper_limit;
// decrease temp
if (Button_repeat(Button_dn))
{
set_change-=step_size;
display_lcd(0,1," ");
}
if ( set_change < lower_limit) set_change = lower_limit;
}
int change_set(byte& set_change,int upper_limit,int lower_limit,int step_size)
{
// Increase set temp
if (Button_repeat(Button_up)){
set_change+=step_size;
display_lcd(0,1," ");
}
if (set_change > upper_limit)set_change = upper_limit;
// decrease temp
if (Button_repeat(Button_dn))
{
set_change-=step_size;
display_lcd(0,1," ");
}
if ( set_change < lower_limit) set_change = lower_limit;
}
void unit_set (void)
{
int param[] ={
100,-100,1,100,-100,1,100,-100,1,5000,500,500,9,1,1,8,0,1 };
int a = 0;
boolean pidLoop = false;
int pidSet,setaddr;
int windowSizeSet;
char* setName[] ={
"Kp = ","Ki = ","Kd = ","Windowsize= ","Num of Stages=","Num of Hops=" };
setaddr = 0;
for(int i=0;i=0) && (i=4) && (i= 4){
save_settings(setaddr,lowByte(pidSet));
pidLoop = false;
}
else{
save_settings(setaddr,pidSet);
pidLoop = false;
}
}
}
if (i>=4){
setaddr+=1;
}
else{
setaddr+=2;
}
a+=3;
}
}
void set_stages (void)
{
boolean autotempLoop = false;
boolean autotimeLoop = false;
tempHAddr = 6;
tempLAddr = 7;
timeAddr = 8;
float stgtmpSet;
int stgtmpSetword;
int stgtimSet;
nmbrStgs = EEPROM.read(38);
for (int i=0; i