diff --git a/brew.ino b/brew.ino new file mode 100644 index 0000000000000000000000000000000000000000..9109699f2087b71e9990ec8f7cb7d6ab998071fc --- /dev/null +++ b/brew.ino @@ -0,0 +1,1039 @@ +// ######################### DECLARE ######################### +// ++++++++++++++++++++++++ ERROR ++++++++++++++++++++++++ +//#include "error.h" +// ++++++++++++++++++++++++ ERROR ++++++++++++++++++++++++ +// ++++++++++++++++++++++++ Library - DHT ++++++++++++++++++++++++ +//#include "DHT.h" //DHT humidity/temperature sensors +//#define DHTPIN 2 // What pin we're connected to +//#define DHTTYPE DHT11 // DHT 11 +#define ponto1 A4// +#define ponto2 A5// +#define R1 462.0 +#define R2 460.0 +#define R3 460.0 +#define calibragem 3.8515352672 +float amostra1;// +float amostra2;// +float diferenca; +float temperatura, temperatura1;// +float tabela[] = {100.00, 100.39, 100.78, 101.17, 101.56, 101.95, 102.34, 102.73, 103.12, 103.51, 103.90, 104.29, 104.68, 105.07, 105.46, 105.85, 106.24, 106.63, 107.02, 107.40, 107.79, 108.18, 108.57, 108.96, 109.35, 109.73, 110.12, 110.51, 110.90, 111.29, 111.67, 112.06, 112.45, 112.83, 113.22, 113.61, 114.00, 114.38, 114.77, 115.15, 115.54, 115.93, 116.31, 116.70, 117.08, 117.47, 117.86, 118.24, 118.63, 119.01, 119.40, 119.78, 120.17, 120.55, 120.94, 121.32, 121.71, 122.09, 122.47, 122.86, 123.24, 123.63, 124.01, 124.39, 124.78, 125.16, 125.54, 125.93, 126.31, 126.69, 127.08, 127.46, 127.84, 128.22, 128.61, 128.99, 129.37, 129.75, 130.13, 130.52, 130.90, 131.28, 131.66, 132.04, 132.42, 132.80, 133.18, 133.57, 133.95, 134.33, 134.71, 135.09, 135.47, 135.85, 136.23, 136.61, 136.99, 137.37, 137.75, 138.13, 138.51, 138.88, 139.26, 139.64, 140.02, 140.40, 140.78, 141.16, 141.54, 141.91, 142.29, 142.67, 143.05, 143.43, 143.80, 144.18, 144.56, 144.94, 145.31, 145.69, 146.07, 146.44, 146.82, 147.20, 147.57, 147.95, 148.33, 148.70, 149.08, 149.46, 149.83, 150.21, 150.58, 150.96, 151.33, 151.71, 152.08, 152.46, 152.83, 153.21, 153.58, 153.96, 154.33, 154.71, 155.08, 155.46, 155.83, 156.20, 156.58, 156.95, 157.33, 157.70, 158.07, 158.45, 158.82, 159.19, 159.56, 159.94, 160.31, 160.68, 150.00, 160.00, 161.05, 161.43, 161.80, 162.17, 162.54, 162.91, 163.29, 163.66, 164.03, 164.40, 164.77, 165.14, 165.51, 165.89, 166.26, 166.63, 167.00, 167.37, 167.74, 168.11, 168.48, 168.85, 169.22, 169.59, 169.96, 170.33, 170.70, 171.07, 171.43, 171.80, 172.17, 172.54, 172.91, 173.28, 173.65, 174.02, 174.38, 174.75, 175.12, 175.49, 175.86, 176.22, 176.59, 176.96, 177.33, 177.69, 178.06, 178.43, 178.79, 179.16}; + +float tensaoPorAmostra; +float Vg; +float Vs; +float a; +float Rx; +// ++++++++++++++++++++++++ Library - DHT ++++++++++++++++++++++++ +// ++++++++++++++++++++++++ Library - LiquidCrystal_I2C ++++++++++++++++++++++++ +#include +#include +#include +#define LCD_I2C_ADDR 0x27 // <<----- Add your address here. Find it from I2C Scanner +#define LCD_X 16 +#define LCD_Y 2 +#define BACKLIGHT_PIN 3 +#define En_pin 2 +#define Rw_pin 1 +#define Rs_pin 0 +#define D4_pin 4 +#define D5_pin 5 +#define D6_pin 6 +#define D7_pin 7 +// ++++++++++++++++++++++++ Library - LiquidCrystal_I2C ++++++++++++++++++++++++ +// ++++++++++++++++++++++++ Heating Element Relay ++++++++++++++++++++++++ +#include +#define HEATING_ELEMENT 24 +// ++++++++++++++++++++++++ Heating Element Relay ++++++++++++++++++++++++ +// ++++++++++++++++++++++++ State Machine ++++++++++++++++++++++++ +#define SETTING_WELCOME_TIMEOUT 2000 +#define MENU_MAX_DEPTH 10 +#define MENU_INIT_VALUES -1,-1,-1,-1,-1,-1,-1,-1,-1,-1 +// ++++++++++++++++++++++++ State Machine ++++++++++++++++++++++++ +// ######################### DECLARE ######################### + + +// ######################### INITIALIZE ######################### +// ++++++++++++++++++++++++ Library - DHT ++++++++++++++++++++++++ +//DHT dht(DHTPIN, DHTTYPE); +// ++++++++++++++++++++++++ Library - DHT ++++++++++++++++++++++++ +// ++++++++++++++++++++++++ Library - LiquidCrystal_I2C ++++++++++++++++++++++++ +int n = 1; +LiquidCrystal_I2C lcd(LCD_I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin); +// ++++++++++++++++++++++++ Library - LiquidCrystal_I2C ++++++++++++++++++++++++ +// ++++++++++++++++++++++++ Rotary Encoder ++++++++++++++++++++++++ +volatile int virtualPosition = 0; +volatile int maxPosition = 120; +volatile int menuSize = 2; +const int PinCLK = 3; // Used for generating interrupts using CLK signal +const int PinDT = 22; // Used for reading DT signal +const int PinSW = 23; // Used for the push button switch +// ++++++++++++++++++++++++ Rotary Encoder ++++++++++++++++++++++++ +// ++++++++++++++++++++++++ Heating Element Relay ++++++++++++++++++++++++ +//Define Variables we'll be connecting to +double Setpoint, Input, Output; + +//Specify the links and initial tuning parameters +float Kp = 200; +float Ki = 50; +float Kd = 0; +PID myPID(&Input, &Output, &Setpoint,Kp,Ki,Kd, DIRECT); +//PID myPID(&Input, &Output, &Setpoint,1000,50,0, DIRECT); + +int WindowSize = 5000; +unsigned long windowStartTime; +// ++++++++++++++++++++++++ Heating Element Relay ++++++++++++++++++++++++ +// ++++++++++++++++++++++++ Error ++++++++++++++++++++++++ +enum sys_error { + no_error, + catastrofic_failure_sensor_temperature, + catastrofic_failure_program, + catastrofic_failure_logic_auto_manual +}; +sys_error error = no_error; +// ++++++++++++++++++++++++ Error ++++++++++++++++++++++++ +// ++++++++++++++++++++++++ State Machine ++++++++++++++++++++++++ +// global +enum state_machine { + state_welcome, + state_menu, + state_manual_time, + state_manual_temperature, + state_manual_mode, + state_error +}; +state_machine state = state_welcome; +// menu +enum main_menu_list { + main_manual, + main_auto +}; +enum manual_menu_list { + manual_temperature, + manual_time, + manual_mode, + manual_start, + manual_back +}; +enum auto_menu_list { + auto_recipe, + auto_start, + auto_back +}; +int menu_position[MENU_MAX_DEPTH]= {MENU_INIT_VALUES}; +// cooking +//int cookTime = 600; +//int cookTemperature = 100; +int cookTime = 3600; +int cookTemperature = 70; +enum cook_mode_list { + quick_start, + start_at_temperature +}; +cook_mode_list cookMode = quick_start; +// ++++++++++++++++++++++++ State Machine ++++++++++++++++++++++++ +// ++++++++++++++++++++++++ Global Variables ++++++++++++++++++++++++ +//float currentTemperatureCelsius; +//float targetTemperatureCelsius = -1; +// ++++++++++++++++++++++++ Global Variables ++++++++++++++++++++++++ +// ######################### INITIALIZE ######################### + +// ######################### INTERRUPTS ######################### +static unsigned long lastInterruptTime = 0; +void isr () { // Interrupt service routine is executed when a HIGH to LOW transition is detected on CLK + + unsigned long interruptTime = millis(); + + // If interrupts come faster than 5ms, assume it's a bounce and ignore + if ((interruptTime - lastInterruptTime) > 5) { + switch(state) { + case state_manual_mode: + case state_menu: { + if (!digitalRead(PinDT)) { + virtualPosition = (virtualPosition + 1); + } + else { + virtualPosition = virtualPosition - 1; + } + if (virtualPosition >= menuSize) { + virtualPosition = 0; + } + if (virtualPosition < 0) { + virtualPosition = menuSize -1; + } + + break; + } + case state_manual_time: { + if (!digitalRead(PinDT)) { + if(virtualPosition >= 60) { + virtualPosition = (virtualPosition + 30); + } + else { + virtualPosition = (virtualPosition + 1); + } + } + else { + if(virtualPosition == 0) { + virtualPosition = (virtualPosition + 60); + } + else { + if(virtualPosition >= 90) { + virtualPosition = (virtualPosition - 30); + } + else { + virtualPosition = virtualPosition - 1; + } + } + } + if (virtualPosition > 7200) { + virtualPosition = 7200; + } + if (virtualPosition < 0) { + virtualPosition = 0; + } + + break; + } + case state_manual_temperature: { + if (!digitalRead(PinDT)) { + if ((interruptTime - lastInterruptTime) < 10) { + virtualPosition = (virtualPosition + 5); + } + else { + virtualPosition = (virtualPosition + 1); + } + } + else { + if ((interruptTime - lastInterruptTime) < 10) { + virtualPosition = (virtualPosition - 5); + } + else { + virtualPosition = (virtualPosition - 1); + } + } + if (virtualPosition > maxPosition) { + virtualPosition = maxPosition; + } + if (virtualPosition < 0) { + virtualPosition = 0; + } + + break; + } + default: { + + } + } + } + + lastInterruptTime = interruptTime; +} +// ######################### INTERRUPTS ######################### + +// ######################### START ######################### +void setup() { +// ++++++++++++++++++++++++ Library - DHT ++++++++++++++++++++++++ + //dht.begin(); +// ++++++++++++++++++++++++ Library - DHT ++++++++++++++++++++++++ +// ++++++++++++++++++++++++ Library - LiquidCrystal_I2C ++++++++++++++++++++++++ + lcd.begin (LCD_X,LCD_Y); // <<----- My LCD was 16x2 + // Switch on the backlight + lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE); + lcd.setBacklight(HIGH); +// ++++++++++++++++++++++++ Library - LiquidCrystal_I2C ++++++++++++++++++++++++ +// ++++++++++++++++++++++++ Rotary Encoder ++++++++++++++++++++++++ + pinMode(PinCLK,INPUT); + pinMode(PinDT, INPUT); + pinMode(PinSW, INPUT); + attachInterrupt(1, isr, FALLING); // interrupt 0 is always connected to pin 2 on Arduino UNO +// ++++++++++++++++++++++++ Rotary Encoder ++++++++++++++++++++++++ +// ++++++++++++++++++++++++ Heating Element Relay ++++++++++++++++++++++++ + pinMode(HEATING_ELEMENT, OUTPUT); + digitalWrite(HEATING_ELEMENT,LOW); + + windowStartTime = millis(); + + //initialize the variables we're linked to + Setpoint = 100; + + //tell the PID to range between 0 and the full window size + myPID.SetOutputLimits(0, WindowSize); + + //turn the PID on + myPID.SetMode(AUTOMATIC); +// ++++++++++++++++++++++++ Heating Element Relay ++++++++++++++++++++++++ + Serial.begin(9600); + Serial.println("Let's start Brewing!"); +} +// ######################### START ######################### + +void loop() { + switch(state) { + case state_welcome: { + runWelcome(); + + break; + } + case state_menu: { + runMenu(); + + break; + } + case state_manual_time: { + //runManualTime(); + + break; + } + case state_manual_temperature: { + //runManualTemp(); + + break; + } + case state_error: { + runError(); + + break; + } + default: { + lcdPrint("Error", "The brewer has stoped working properly. Please shutdown NOW for your safety!"); + state = state_error; + error = catastrofic_failure_program; + } + } +} + +void runWelcome() { + // Write welcome + lcd.clear(); + lcd.home (); // go home + lcd.print(" Let's start"); + lcd.setCursor (0,1); // go to start of 2nd line + lcd.print(" Brewing!"); + + delay(SETTING_WELCOME_TIMEOUT); + + //state = state_manual_temp; + //state = state_manual_time; + state = state_menu; +} + +void runMenu() { + digitalWrite(HEATING_ELEMENT,LOW); + + switch(menu_position[0]) { + case main_manual: { + switch(menu_position[1]) { + case manual_temperature: { + // do work + cookTemperature = getTemperature(cookTemperature); + + menu_position[1] = -1; + virtualPosition = manual_temperature; + + break; + } + case manual_time: { + // do work + cookTime = getTimer(cookTime); + + menu_position[1] = -1; + virtualPosition = manual_time; + + break; + } + case manual_mode: { + // do work + int returnMode = getMode(); + switch(returnMode) { + case quick_start: { + cookMode = quick_start; + break; + } + case start_at_temperature: { + cookMode = start_at_temperature; + + break; + } + default: { + cookMode = quick_start; + } + } + + menu_position[1] = -1; + virtualPosition = manual_mode; + + break; + } + case manual_start: { + // do work + runStart(); + + menu_position[1] = -1; + virtualPosition = manual_start; + + break; + } + case manual_back: { + menu_position[0] = -1; + menu_position[1] = -1; + + virtualPosition = manual_back; + + break; + } + default: { + // reset menu variables + //virtualPosition = 0; + menuSize = 5; + + // display menu + lcd.clear(); + lcd.home (); // go home + lcd.print("Manual Menu"); + + while(true) { + switch(virtualPosition) { + case manual_temperature: { + lcd.setCursor (0,1); // go to start of 2nd line + lcd.print("-> Temperature "); + delay(100); + break; + } + case manual_time: { + lcd.setCursor (0,1); // go to start of 2nd line + lcd.print("-> Time "); + delay(100); + break; + } + case manual_mode: { + lcd.setCursor (0,1); // go to start of 2nd line + lcd.print("-> Mode "); + delay(100); + break; + } + case manual_start: { + lcd.setCursor (0,1); // go to start of 2nd line + lcd.print("-> Start "); + delay(100); + break; + } + case manual_back: { + lcd.setCursor (0,1); // go to start of 2nd line + lcd.print("-> Back "); + delay(100); + break; + } + default: { + //lcd.setCursor (0,1); // go to start of 2nd line + //lcd.print("*** Error ***"); + virtualPosition = 0; + } + } + + if (!(digitalRead(PinSW))) { // check if pushbutton is pressed + menu_position[1] = virtualPosition; + while (!digitalRead(PinSW)) {} // wait til switch is released + delay(10); // debounce + break; + } + } + } + } + break; + } + case main_auto: { + switch(menu_position[1]) { + case auto_recipe: { + // do work + + menu_position[1] = -1; + virtualPosition = auto_recipe; + + break; + } + case auto_start: { + // do work + + menu_position[1] = -1; + virtualPosition = auto_start; + + break; + } + case auto_back: { + // reset choces + menu_position[0] = -1; + menu_position[1] = -1; + + // set menu position + virtualPosition = main_auto; + + break; + } + default: { + // reset menu variables + //virtualPosition = 0; + menuSize = 3; + + // display menu + lcd.clear(); + lcd.home (); // go home + lcd.print("Automatic Menu"); + + while(true) { + switch(virtualPosition) { + case auto_recipe: { + lcd.setCursor (0,1); // go to start of 2nd line + lcd.print("-> Recipe "); + delay(100); + break; + } + case auto_start: { + lcd.setCursor (0,1); // go to start of 2nd line + lcd.print("-> Start "); + delay(100); + break; + } + case auto_back: { + lcd.setCursor (0,1); // go to start of 2nd line + lcd.print("-> Back "); + delay(100); + break; + } + default: { + //lcd.setCursor (0,1); // go to start of 2nd line + //lcd.print("*** Error ***"); + virtualPosition = 0; + } + } + + if (!(digitalRead(PinSW))) { // check if pushbutton is pressed + menu_position[1] = virtualPosition; + while (!digitalRead(PinSW)) {} // wait til switch is released + delay(10); // debounce + break; + } + } + } + } + break; + } + default: { + // reset menu variables + //virtualPosition = 0; + menuSize = 2; + + // display menu + lcd.clear(); + lcd.home (); // go home + lcd.print("Main Menu"); + + while(true) { + switch(virtualPosition) { + case main_manual: { + lcd.setCursor (0,1); // go to start of 2nd line + lcd.print("-> Manual "); + delay(100); + break; + } + case main_auto: { + lcd.setCursor (0,1); // go to start of 2nd line + lcd.print("-> Automatic "); + delay(100); + break; + } + default: { + //lcd.setCursor (0,1); // go to start of 2nd line + //lcd.print("*** Error ***"); + virtualPosition = 0; + } + } + + if (!(digitalRead(PinSW))) { // check if pushbutton is pressed + menu_position[0] = virtualPosition; + while (!digitalRead(PinSW)) {} // wait til switch is released + delay(10); // debounce + break; + } + } + } + } +} + +int getTimer(int init) { + state_machine initialState = state; + + // set operation state + state = state_manual_time; + virtualPosition = init; + + // initialize variables + int lastCount = 0; + int minutes = 0; + int seconds = 0; + + // Setup Screen + lcd.clear(); + lcd.home(); + lcd.print("Set Time"); + lcd.setCursor (0,LCD_Y-1); + lcd.print(" 0:00"); + + while(true) { + // Check for timer set + if (!(digitalRead(PinSW))) { // check if pushbutton is pressed + while (!digitalRead(PinSW)) {} // wait til switch is released + delay(10); // debounce + break; + } + + // display current timer + if (virtualPosition != lastCount) { + lastCount = virtualPosition; + minutes = virtualPosition/60; + seconds = virtualPosition-minutes*60; + + lcd.setCursor (0,LCD_Y-1); + lcd.print(" "); + lcd.print(minutes); + lcd.print(":"); + if(seconds<10) { + lcd.print("0"); + } + lcd.print(seconds); + lcd.println(" "); + } + } + + state = initialState; + return virtualPosition; +} + +int getTemperature(int init) { + state_machine initialState = state; + + // set operation state + state = state_manual_temperature; + virtualPosition = init; + + // initialize variables + int lastCount = 0; + + // Setup Screen + lcd.clear(); + lcd.home(); + lcd.print("Set Temperature"); + lcd.setCursor (0,LCD_Y-1); + lcd.print(" 0 *C"); + + while(true) { + // Check for timer set + if (!(digitalRead(PinSW))) { // check if pushbutton is pressed + while (!digitalRead(PinSW)) {} // wait til switch is released + delay(10); // debounce + break; + } + + // display current timer + if (virtualPosition != lastCount) { + lastCount = virtualPosition; + + lcd.setCursor (0,LCD_Y-1); + lcd.print(" "); + if(virtualPosition<10) { + lcd.print(" "); + } + else { + if(virtualPosition<100) { + lcd.print(" "); + } + } + lcd.print(virtualPosition); + lcd.print(" *C"); + lcd.println(" "); + } + } + + state = initialState; + return virtualPosition; +} + +int getMode() { + state_machine initialState = state; + int initialMenuSize = menuSize; + + // set operation state + state = state_manual_mode; + menuSize = 2; + virtualPosition = cookMode; + + // initialize variables + int lastCount = 0; + + // Setup Screen + lcd.clear(); + lcd.home(); + lcd.print("Set Mode"); + lcd.setCursor (0,LCD_Y-1); + lcd.print(" Quick Start"); + + while(true) { + // Check for timer set + if (!(digitalRead(PinSW))) { // check if pushbutton is pressed + while (!digitalRead(PinSW)) {} // wait til switch is released + delay(10); // debounce + break; + } + + // display current timer + if (virtualPosition != lastCount) { + lastCount = virtualPosition; + + lcd.setCursor (0,LCD_Y-1); + + switch(virtualPosition) { + case quick_start: { + lcd.print(" Quick Start "); + + break; + } + case start_at_temperature: { + lcd.print("Start After Temp"); + + break; + } + default: { + lcd.print("*** error ***"); + } + } + lcd.println(" "); + } + } + + state = initialState; + menuSize = initialMenuSize; + return virtualPosition; +} + +void runStart() { + // Configure environment + long runCurrentTemperature; + long runTargetTemperature; + unsigned long runStartTime; + unsigned long runTargetTime; + cook_mode_list runCurrentMode; + boolean clockStart = false; + boolean clockEnd = false; + + while(true) { + // Build Instructions + switch(menu_position[0]) { + case main_manual: { + // everything is set, lets run! + runTargetTemperature = cookTemperature; + runTargetTime = cookTime; + runCurrentMode = cookMode; + + if(clockStart && clockEnd) { + delay(1000); + return; + } + + break; + } + case main_auto: { + // set the next instruction + + break; + } + default: { + lcdPrint("Error", "The system has failed to be set into manual or automatic mode!"); + state = state_error; + error = catastrofic_failure_logic_auto_manual; + return; + } + } + + // Run Instructions + // Setup LCD + lcd.clear(); + lcd.home(); + lcd.print("Hot: 000*C/000*C"); + //lcd.print("Cool:000*C/000*C"); + lcd.setCursor (0,LCD_Y-1); + if(runCurrentMode == quick_start) { + lcd.print("Quick 00:00"); + + clockStart = true; + runStartTime = millis(); + } + else { + lcd.print("Wait 00:00"); + } + + //int lastCount = 0; + + while(true) { + //Serial.println("From second while"); + // Wait a few seconds between measurements. + //delay(100); + + /* Read temperature from sensor + runCurrentTemperature = dht.readTemperature(); // Reading temperature + if (isnan(runCurrentTemperature)) { // Check if any reads failed and exit early (to try again). + // Got an error + state = state_error; + error = catastrofic_failure_sensor_temperature; + + return; + } + */ + + amostra1= analogRead(ponto1); + amostra2= analogRead(ponto2); + Serial.print("O valor das entradas sao: ["); + Serial.print(amostra1); + Serial.print(", "); + Serial.print(amostra2); + Serial.println("]"); + + diferenca = amostra2 - amostra1; + Serial.print("diferenca: ["); + Serial.print(diferenca, 6); + tensaoPorAmostra = 5.0 / 1024.0; + Serial.print("] tensao por amortra: ["); + Serial.print(tensaoPorAmostra, 6); + Vg = ( diferenca ) * tensaoPorAmostra; + Serial.print("] Vg: ["); + Serial.print(Vg, 6); + Vs = 5.0; + Serial.print("] Vs: ["); + Serial.print(Vs); + a = R2 / (R1 + R2) - Vg / Vs; + Serial.print("] a: ["); + Serial.print(a, 6); + Rx = (a * R3) / (1 - a); + Serial.print("] Rx: ["); + Serial.print(Rx, 6); + + Rx = Rx - calibragem; + + int i; + int tabelaSize = sizeof(tabela) / sizeof(float); + for( i = 0; i <= tabelaSize; i++) { + if((tabela[i]) > Rx) { + if(i == 0) { + runCurrentTemperature = -1.0; + } + else { + if(i == tabelaSize) { + runCurrentTemperature = 210.0; + } + else { + runCurrentTemperature = (i - 1) + ((Rx - tabela[i-1])/(tabela[i] - tabela[i-1])); + + //temperatura = map(Rx, tabela[i-1], tabela[i], i-1, i); + } + } + + break; + } + } + + + + /* Initialize target temperature with current temperature + if(runTargetTemperature<0) { + runTargetTemperature = runCurrentTemperature; + virtualPosition = runCurrentTemperature; + }*/ + + /* Read push button from the rotary encoder + if (!(digitalRead(PinSW))) { // check if pushbutton is pressed + virtualPosition = currentTemperatureCelsius; // if YES, then reset counter to ZERO + while (!digitalRead(PinSW)) {} // wait til switch is released + delay(10); // debounce + Serial.println("Reset"); // Using the word RESET instead of COUNT here to find out a buggy encoder + }*/ + + /* Read target temperature from the rotary encoder + if (virtualPosition != lastCount) { + lastCount = virtualPosition; + runTargetTemperature = virtualPosition; + Serial.print("Count: "); + Serial.println(virtualPosition); + }*/ + + // Operate the heating element + Input = runCurrentTemperature; + Setpoint = runTargetTemperature; + myPID.Compute(); + + /************************************************ + * turn the output pin on/off based on pid output + ************************************************/ + unsigned long now = millis(); + + if(now - windowStartTime>WindowSize) + { //time to shift the Relay Window + windowStartTime += WindowSize; + } + + if(Output > now - windowStartTime) { + digitalWrite(HEATING_ELEMENT,HIGH); + + if(Output != 0) { + /* + Serial.print("+++ Diff: "); + Serial.print(now - windowStartTime); + Serial.print(" | Output: "); + Serial.println(Output); + */ + } + } + else { + digitalWrite(HEATING_ELEMENT,LOW); + + if(Output != 0) { + /* + Serial.print("--- Diff: "); + Serial.print(now - windowStartTime); + Serial.print(" | Output: "); + Serial.println(Output); + */ + } + } + + // Print status to serial connection + //Serial.print("[Temperature Sensor] "); + //Serial.print("Temperature: "); + //Serial.print(runCurrentTemperature); + //Serial.print("*C | "); + //Serial.print(runTargetTemperature); + //Serial.println("*C "); + + if(runCurrentMode == start_at_temperature) { + + } + + // Print status to LCD + lcd.setCursor (5,0); + if (runCurrentTemperature < 10) { + lcd.print(" "); + } + else { + if (runCurrentTemperature < 100) { + lcd.print(" "); + } + } + lcd.print(runCurrentTemperature); + + lcd.setCursor (11,0); + if (runTargetTemperature < 10) { + lcd.print(" "); + } + else { + if (runTargetTemperature < 100) { + lcd.print(" "); + } + } + lcd.print(runTargetTemperature); + + // Display time + // Start the clock for "wait" mode + if(runCurrentTemperature == runTargetTemperature && clockStart == false) { + clockStart = true; + runStartTime = now; + } + int displayTime = 0; + if(clockStart) { + displayTime = runTargetTime - ((now - runStartTime) / 1000); + + if(displayTime <= 0) { + displayTime = 0; + clockEnd = true; + + break; + } + } + else { + displayTime = runTargetTime; + } + int minutes = displayTime/60; + int seconds = displayTime-minutes*60; + + lcd.setCursor (10,1); + //lcd.print(" "); + if (minutes < 10) { + lcd.print(" 0"); + } + else { + if (minutes < 100) { + lcd.print(" "); + } + } + lcd.print(minutes); + lcd.print(":"); + if(seconds<10) { + lcd.print("0"); + } + lcd.print(seconds); + } + } +} + +void runError() { + if(error != no_error) { + if (error == catastrofic_failure_sensor_temperature) + { + Serial.println("[Error] catastrofic_failure_sensor_temperature!"); + + lcdPrint("ERROR", "A catastrofic failure was detected on the temperature sensor!"); + /* + if (!isnan(dht.readTemperature())) { // Check if any reads failed and exit early (to try again). + error = no_error; + return; + } + */ + } + } + else { + state = state_welcome; + } +} + +void lcdPrint(String title, String message) { + int messageLength = message.length(); + + lcd.clear(); + + // print title + lcd.home(); + lcd.print(title); + + // print message + if(messageLength <= LCD_X) { + lcd.setCursor(0,LCD_Y-1); + lcd.print(message); + delay(1000); + } + // print scrolling message + else { + String output_message = " "; + output_message += message; + messageLength = output_message.length(); + + // Adjust the message size for proper printing + if ( messageLength & 1 == 1 ) { + output_message+=" "; + messageLength+=2; + } + + // print scrolling message + for (int cursor = 0; cursor < messageLength - LCD_X; cursor+=2) { + lcd.setCursor(0,LCD_Y-1); + lcd.print(output_message.substring(cursor, cursor+16)); + delay(500); + } + } +} +