Commit 6eecd9b6 authored by João Lino's avatar João Lino

rough draft of the code for the new version.

I'll call it 2.0.001
parent 959b24bc
// ######################### DECLARE ######################### #define DEBUG
// ++++++++++++++++++++++++ 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 99.45
//#define R2 100.2
//#define R3 100.05
//#define calibragem 12.709066573
//float amostra1;//
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 amostras[] = {630.00,630.00,630.00}; //,630.00,630.00,630.00,630.00,630.00,630.00,630.00,630.00,630.00,630.00,630.00,630.00,630.00,630.00,630.00,630.00,630.00};
float Vout;
float Rx;
/* // ######################### CONSTANTS #########################
float amostra2;//
float diferenca; // ######################### SETTINGS #########################
float tensaoPorAmostra;
float Vg;
float Vs;
float a;
float Rx;
*/
// ++++++++++++++++++++++++ Library - DHT ++++++++++++++++++++++++
// ++++++++++++++++++++++++ Library - LiquidCrystal_I2C ++++++++++++++++++++++++
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#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 <PID_v1.h>
#define HEATING_ELEMENT 24
// ++++++++++++++++++++++++ Heating Element Relay ++++++++++++++++++++++++ // ++++++++++++++++++++++++ Heating Element Relay ++++++++++++++++++++++++
#define HEATING_ELEMENT_DEFAULT_WINDOW_SIZE 1000
#define HEATING_ELEMENT_OUTPUT_PIN 24
#define HEATING_ELEMENT_MAX_HEAT_PWM_INTEGER 5
#define HEATING_ELEMENT_MAX_HEAT_PWM_FLOAT 5.0
#define HEATING_ELEMENT_MAX_WATTAGE 3000.0 // Minimum = 2000.0
#define HEATING_ELEMENT_AC_FREQUENCY_HZ 50.0
// ++++++++++++++++++++++++ Temperature ++++++++++++++++++++++++ // ++++++++++++++++++++++++ Temperature ++++++++++++++++++++++++
#define TEMPERATURE_SENSOR_PIN 30 #define PT100_BASE_INPUT_PIN A4
#define TEMPERATURE_MAX_POSITION 120 #define PT100_BASE_OUTPUT_PIN 30
// ++++++++++++++++++++++++ Temperature ++++++++++++++++++++++++ #define PT100_BASE_TIME_BETWEEN_READINGS 100
// ++++++++++++++++++++++++ Mixer ++++++++++++++++++++++++ #define PT100_UP_INPUT_PIN A5
#define MIXER_PIN 12 #define PT100_UP_OUTPUT_PIN 31
#define MIXER_MAX_POSITION 255 #define PT100_UP_TIME_BETWEEN_READINGS 100
#define PT100_DOWN_INPUT_PIN A6
#define PT100_DOWN_OUTPUT_PIN 32
#define PT100_DOWN_TIME_BETWEEN_READINGS 100
#define PT100_BASE_DEFAULT_ADC_VMAX 1.081
#define PT100_BASE_DEFAULT_VS 4.87
#define PT100_BASE_DEFAULT_R1_RESISTENCE 606.0
#define PT100_BASE_DEFAULT_LINE_RESISTENCE 0.7
#define PT100_BASE_DEFAULT_OPERATION_RESISTENCE 0.0
#define PT100_UP_DEFAULT_ADC_VMAX 1.081
#define PT100_UP_DEFAULT_VS 4.87
#define PT100_UP_DEFAULT_R1_RESISTENCE 606.0
#define PT100_UP_DEFAULT_LINE_RESISTENCE 0.7
#define PT100_UP_DEFAULT_OPERATION_RESISTENCE 0.0
#define PT100_DOWN_DEFAULT_ADC_VMAX 1.081
#define PT100_DOWN_DEFAULT_VS 4.87
#define PT100_DOWN_DEFAULT_R1_RESISTENCE 606.0
#define PT100_DOWN_DEFAULT_LINE_RESISTENCE 0.7
#define PT100_DOWN_DEFAULT_OPERATION_RESISTENCE 0.0
// ++++++++++++++++++++++++ Mixer ++++++++++++++++++++++++ // ++++++++++++++++++++++++ Mixer ++++++++++++++++++++++++
//#define MIXER_PIN 12
//#define MIXER_MAX_POSITION 255
// ++++++++++++++++++++++++ Rotary Encoder ++++++++++++++++++++++++
#define ROTARY_ENCODER_INTERRUPT_NUMBER 1 // On Mega2560 boards, interrupt 1 is on pin 3
#define ROTARY_ENCODER_CLK_PIN 3 // Used for generating interrupts using CLK signal
#define ROTARY_ENCODER_DT_PIN 22 // Used for reading DT signal
#define ROTARY_ENCODER_SW_PIN 23 // Used for the push button switch
#define ROTARY_ENCODER_DEBOUNCE_TIME 10 // Number of miliseconds to ignore new signals a signal is received
// ++++++++++++++++++++++++ State Machine ++++++++++++++++++++++++ // ++++++++++++++++++++++++ State Machine ++++++++++++++++++++++++
#define SETTING_WELCOME_TIMEOUT 2000 #define SETTING_WELCOME_TIMEOUT 100
#define MENU_MAX_DEPTH 10 #define SETTING_MAX_INACTIVITY_TIME 3000
#define MENU_INIT_VALUES -1,-1,-1,-1,-1,-1,-1,-1,-1,-1 #define MENU_MAX_DEPTH 10
// ++++++++++++++++++++++++ State Machine ++++++++++++++++++++++++ #define MENU_INIT_VALUES -1,-1,-1,-1,-1,-1,-1,-1,-1,-1
// ######################### DECLARE ######################### #define MENU_SIZE_MAIN_MENU 16
#define SETTING_SERIAL_MONITOR_BAUD_RATE 9600
#define SETTING_SERIAL_MONITOR_WELCOME_MESSAGE "Let's start Brewing!"
// ######################### LIBRARIES #########################
// ++++++++++++++++++++++++ LiquidCrystal_I2C ++++++++++++++++++++++++
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
// ######################### INITIALIZE ######################### #define LCD_I2C_ADDR 0x27 // <<----- Add your address here. Find it from I2C Scanner
// ++++++++++++++++++++++++ Library - DHT ++++++++++++++++++++++++ #define LCD_HORIZONTAL_RESOLUTION 16
//DHT dht(DHTPIN, DHTTYPE); #define LCD_VERTICAL_RESOLUTION 2
// ++++++++++++++++++++++++ Library - DHT ++++++++++++++++++++++++ #define LCD_BACKLIGHT_PIN 3
// ++++++++++++++++++++++++ Library - LiquidCrystal_I2C ++++++++++++++++++++++++ #define LCD_EN_PIN 2
int n = 1; #define LCD_RW_PIN 1
LiquidCrystal_I2C lcd(LCD_I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin); #define LCD_RS_PIN 0
// ++++++++++++++++++++++++ Library - LiquidCrystal_I2C ++++++++++++++++++++++++ #define LCD_D4_PIN 4
#define LCD_D5_PIN 5
#define LCD_D6_PIN 6
#define LCD_D7_PIN 7
// ++++++++++++++++++++++++ PT100 +++++++++++++++++++++++++++++++++
#include <PT100.h>
// ######################### VARIABLES #########################
// ++++++++++++++++++++++++ Rotary Encoder ++++++++++++++++++++++++ // ++++++++++++++++++++++++ Rotary Encoder ++++++++++++++++++++++++
volatile int rotaryEncoderVirtualPosition = 0; volatile int rotaryEncoderVirtualPosition;
volatile int rotaryEncoderMaxPosition; volatile int rotaryEncoderMaxPosition;
volatile int menuSize = 2; volatile int rotaryEncoderMinPosition;
const int PinCLK = 3; // Used for generating interrupts using CLK signal volatile int rotaryEncoderSingleStep;
const int PinDT = 22; // Used for reading DT signal volatile int rotaryEncoderMultiStep;
const int PinSW = 23; // Used for the push button switch
// ++++++++++++++++++++++++ Rotary Encoder ++++++++++++++++++++++++
// ++++++++++++++++++++++++ Heating Element Relay ++++++++++++++++++++++++ // ++++++++++++++++++++++++ Heating Element Relay ++++++++++++++++++++++++
//Define Variables we'll be connecting to int WindowSize; // Time frame to operate in
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);
PID myPID(&Input, &Output, &Setpoint,200,50,0, DIRECT);
int WindowSize = 1000;
unsigned long windowStartTime; unsigned long windowStartTime;
// ++++++++++++++++++++++++ Heating Element Relay ++++++++++++++++++++++++ unsigned long dWattPerPulse;
// ++++++++++++++++++++++++ Mixer ++++++++++++++++++++++++
//const int mixerSpeed = 130;
// ++++++++++++++++++++++++ Mixer ++++++++++++++++++++++++
// ++++++++++++++++++++++++ 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 ++++++++++++++++++++++++
// ++++++++++++++++++++++++ State Machine ++++++++++++++++++++++++
// global // global
enum state_machine { enum TRotaryEncoderMode {
state_welcome, eRotaryEncoderMode_Menu,
state_menu, eRotaryEncoderMode_Time,
state_manual_time, eRotaryEncoderMode_Generic,
state_manual_temperature, eRotaryEncoderMode_Disabled
state_manual_mode,
state_manual_mixer,
state_error
}; };
state_machine state = state_welcome; TRotaryEncoderMode rotaryEncoderMode;
// menu // menu
enum main_menu_list { enum eMainMenuOptions {
main_manual, eMainMenu_GO,
main_auto eMainMenu_Presets,
eMainMenu_Malt,
eMainMenu_Startpoint,
eMainMenu_BetaGlucanase,
eMainMenu_Debranching,
eMainMenu_Proteolytic,
eMainMenu_BetaAmylase,
eMainMenu_AlphaAmylase,
eMainMenu_Mashout,
eMainMenu_Recirculation,
eMainMenu_Sparge,
eMainMenu_Boil,
eMainMenu_Hops,
eMainMenu_Cooling,
eMainMenu_Settings
};
eMainMenuOptions mainMenuOption;
enum ePresetsMenuOptions {
ePresetsMenu_Trigo,
ePresetsMenu_IPA,
ePresetsMenu_Belga,
ePresetsMenu_Red,
ePresetsMenu_APA,
ePresetsMenu_Back,
}; };
enum manual_menu_list { ePresetsMenuOptions presetsMenuOption;
manual_temperature,
manual_time, enum eMaltMenuOptions {
manual_mode, eMaltMenu_CastleMalting_Chteau_Pilsen_2RS,
manual_mixer, eMaltMenu_CastleMalting_Wheat_Blanc,
manual_start, eMaltMenu_Back,
manual_back
}; };
enum auto_menu_list { eMaltMenuOptions maltMenuOption;
auto_recipe,
auto_start, enum eSettingsMenuOptions {
auto_back eSettingsMenu_PT100_Element,
eSettingsMenu_PT100_Up,
eSettingsMenu_PT100_Down,
eSettingsMenu_Back,
}; };
int menu_position[MENU_MAX_DEPTH]= {MENU_INIT_VALUES}; eSettingsMenuOptions settingsMenuOption;
// cooking // cooking
enum cook_mode_list { enum eCookingStages {
quick_start, eCookingStage_Startpoint,
start_at_temperature eCookingStage_BetaGlucanase,
eCookingStage_Debranching,
eCookingStage_Proteolytic,
eCookingStage_BetaAmylase,
eCookingStage_AlphaAmylase,
eCookingStage_Mashout,
eCookingStage_Recirculation,
eCookingStage_Sparge,
eCookingStage_Boil,
eCookingStage_Cooling,
eCookingStage_Done
}; };
int cookTime = 3600; eCookingStages cookingStage;
int cookTemperature = 36;
cook_mode_list cookMode = quick_start;
int cookMixerSpeed = 180; //0; //130;
// ++++++++++++++++++++++++ State Machine ++++++++++++++++++++++++
// ++++++++++++++++++++++++ Global Variables ++++++++++++++++++++++++
//float currentTemperatureCelsius;
//float targetTemperatureCelsius = -1;
// ++++++++++++++++++++++++ Global Variables ++++++++++++++++++++++++ // ++++++++++++++++++++++++ Global Variables ++++++++++++++++++++++++
boolean cooking;
int clockStartTime;
int clockCounter;
int clockIgnore;
boolean clockStart;
boolean clockEnd;
int cookTime;
int cookTemperature;
//cook_mode_list cookMode;
//int cookMixerSpeed;
int cookHeatPWM;
int startpointTime;
int betaGlucanaseTime;
int debranchingTime;
int proteolyticTime;
int betaAmylaseTime;
int alphaAmylaseTime;
int mashoutTime;
int recirculationTime;
int spargeTime;
int boilTime;
int coolingTime;
int startpointTemperature;
int betaGlucanaseTemperature;
int debranchingTemperature;
int proteolyticTemperature;
int betaAmylaseTemperature;
int alphaAmylaseTemperature;
int mashoutTemperature;
int recirculationTemperature;
int spargeTemperature;
int boilTemperature;
int coolingTemperature;
//int menuSize;
int menu_position[MENU_MAX_DEPTH] = {MENU_INIT_VALUES};
boolean refresh;
boolean repaint;
// ++++++++++++++++++++++++ Interrupts ++++++++++++++++++++++++
static unsigned long lastInterruptTime;
// ######################### INITIALIZE ######################### // ######################### INITIALIZE #########################
// ++++++++++++++++++++++++ Library - LiquidCrystal_I2C ++++++++++++++++++++++++
LiquidCrystal_I2C lcd(LCD_I2C_ADDR, LCD_EN_PIN, LCD_RW_PIN, LCD_RS_PIN, LCD_D4_PIN, LCD_D5_PIN, LCD_D6_PIN, LCD_D7_PIN);
// +++++++++++++++++++++++ PT100 +++++++++++++++++++++++
PT100 basePT100(PT100_BASE_OUTPUT_PIN, PT100_BASE_INPUT_PIN, PT100_BASE_TIME_BETWEEN_READINGS, PT100_BASE_DEFAULT_ADC_VMAX, PT100_BASE_DEFAULT_VS, PT100_BASE_DEFAULT_R1_RESISTENCE, PT100_BASE_DEFAULT_LINE_RESISTENCE, PT100_BASE_DEFAULT_OPERATION_RESISTENCE);
PT100 upPT100(PT100_UP_OUTPUT_PIN, PT100_UP_INPUT_PIN, PT100_UP_TIME_BETWEEN_READINGS, PT100_UP_DEFAULT_ADC_VMAX, PT100_UP_DEFAULT_VS, PT100_UP_DEFAULT_R1_RESISTENCE, PT100_UP_DEFAULT_LINE_RESISTENCE, PT100_UP_DEFAULT_OPERATION_RESISTENCE);
PT100 downPT100(PT100_DOWN_OUTPUT_PIN, PT100_DOWN_INPUT_PIN, PT100_DOWN_TIME_BETWEEN_READINGS, PT100_DOWN_DEFAULT_ADC_VMAX, PT100_DOWN_DEFAULT_VS, PT100_DOWN_DEFAULT_R1_RESISTENCE, PT100_DOWN_DEFAULT_LINE_RESISTENCE, PT100_DOWN_DEFAULT_OPERATION_RESISTENCE);
// ######################### INTERRUPTS ######################### // ######################### INTERRUPTS #########################
static unsigned long lastInterruptTime = 0; void xSetupRotaryEncoder( TRotaryEncoderMode newMode, int newPosition, int newMaxPosition, int newMinPosition, int newSingleStep, int newMultiStep ) {
void isr () { // Interrupt service routine is executed when a HIGH to LOW transition is detected on CLK if( newMode >= 0 ) rotaryEncoderMode = newMode;
if( newPosition >= 0 ) rotaryEncoderVirtualPosition = newPosition;
if( newMaxPosition >= 0 ) rotaryEncoderMaxPosition = newMaxPosition;
if( newMinPosition >= 0 ) rotaryEncoderMinPosition = newMinPosition;
if( newSingleStep >= 0 ) rotaryEncoderSingleStep = newSingleStep;
if( newMultiStep >= 0 ) rotaryEncoderMultiStep = newMultiStep;
}
void isr () { // Interrupt service routine is executed when a HIGH to LOW transition is detected on CLK
repaint = true;
refresh = true;
unsigned long interruptTime = millis();
unsigned long interruptTime = millis(); // If interrupts come faster than [ROTARY_ENCODER_DEBOUNCE_TIME]ms, assume it's a bounce and ignore
if ((interruptTime - lastInterruptTime) > ROTARY_ENCODER_DEBOUNCE_TIME) {
switch(rotaryEncoderMode) {
// If interrupts come faster than 5ms, assume it's a bounce and ignore // Input of rotary encoder controling menus
if ((interruptTime - lastInterruptTime) > 5) { case eRotaryEncoderMode_Menu: {
switch(state) { if (!digitalRead(ROTARY_ENCODER_DT_PIN)) {
rotaryEncoderVirtualPosition = (rotaryEncoderVirtualPosition + rotaryEncoderSingleStep);
// Input of rotay encoder controling menus
case state_manual_mode:
case state_menu: {
if (!digitalRead(PinDT)) {
rotaryEncoderVirtualPosition = (rotaryEncoderVirtualPosition + 1);
} }
else { else {
rotaryEncoderVirtualPosition = rotaryEncoderVirtualPosition - 1; rotaryEncoderVirtualPosition = rotaryEncoderVirtualPosition - rotaryEncoderSingleStep;
} }
if (rotaryEncoderVirtualPosition >= menuSize) { if (rotaryEncoderVirtualPosition > rotaryEncoderMaxPosition) {
rotaryEncoderVirtualPosition = 0; rotaryEncoderVirtualPosition = rotaryEncoderMinPosition;
} }
if (rotaryEncoderVirtualPosition < 0) { if (rotaryEncoderVirtualPosition < rotaryEncoderMinPosition) {
rotaryEncoderVirtualPosition = menuSize -1; rotaryEncoderVirtualPosition = rotaryEncoderMaxPosition;
} }
break; break;
} }
// Input of rotay encoder controling time variables // Input of rotary encoder controling time variables
case state_manual_time: { case eRotaryEncoderMode_Time: {
if (!digitalRead(PinDT)) { xDecodeRotaryEncoder();
if (!digitalRead(ROTARY_ENCODER_DT_PIN)) {
if(rotaryEncoderVirtualPosition >= 60) { if(rotaryEncoderVirtualPosition >= 60) {
rotaryEncoderVirtualPosition = (rotaryEncoderVirtualPosition + 30); rotaryEncoderVirtualPosition = (rotaryEncoderVirtualPosition + rotaryEncoderMultiStep);
} }
else { else {
rotaryEncoderVirtualPosition = (rotaryEncoderVirtualPosition + 1); rotaryEncoderVirtualPosition = (rotaryEncoderVirtualPosition + rotaryEncoderSingleStep);
} }
} }
else { else {
if(rotaryEncoderVirtualPosition == 0) { if(rotaryEncoderVirtualPosition == rotaryEncoderMinPosition) {
rotaryEncoderVirtualPosition = (rotaryEncoderVirtualPosition + 60); rotaryEncoderVirtualPosition = (rotaryEncoderVirtualPosition + 60);
} }
else { else {
if(rotaryEncoderVirtualPosition >= 90) { if(rotaryEncoderVirtualPosition >= (60 + rotaryEncoderMultiStep)) {
rotaryEncoderVirtualPosition = (rotaryEncoderVirtualPosition - 30); rotaryEncoderVirtualPosition = (rotaryEncoderVirtualPosition - rotaryEncoderMultiStep);
} }
else { else {
rotaryEncoderVirtualPosition = rotaryEncoderVirtualPosition - 1; rotaryEncoderVirtualPosition = rotaryEncoderVirtualPosition - rotaryEncoderSingleStep;
} }
} }
} }
if (rotaryEncoderVirtualPosition > 7200) { if (rotaryEncoderVirtualPosition > rotaryEncoderMaxPosition) {
rotaryEncoderVirtualPosition = 7200; rotaryEncoderVirtualPosition = rotaryEncoderMaxPosition;
} }
if (rotaryEncoderVirtualPosition < 0) { if (rotaryEncoderVirtualPosition < rotaryEncoderMinPosition) {
rotaryEncoderVirtualPosition = 0; rotaryEncoderVirtualPosition = rotaryEncoderMinPosition;
} }
break; break;
} }
// Input of rotay encoder controling integer variables within a range between 0 and rotaryEncoderMaxPosition // Input of rotary encoder controling generic integer variables within a range between rotaryEncoderMinPosition and rotaryEncoderMaxPosition
case state_manual_mixer: case eRotaryEncoderMode_Generic: {
case state_manual_temperature: { if (!digitalRead(ROTARY_ENCODER_DT_PIN)) {
if (!digitalRead(PinDT)) { if ((interruptTime - lastInterruptTime) < ROTARY_ENCODER_DEBOUNCE_TIME) {
if ((interruptTime - lastInterruptTime) < 10) { rotaryEncoderVirtualPosition = (rotaryEncoderVirtualPosition + rotaryEncoderMultiStep);
rotaryEncoderVirtualPosition = (rotaryEncoderVirtualPosition + 5);
} }
else { else {
rotaryEncoderVirtualPosition = (rotaryEncoderVirtualPosition + 1); rotaryEncoderVirtualPosition = (rotaryEncoderVirtualPosition + rotaryEncoderSingleStep);
} }
} }
else { else {
if ((interruptTime - lastInterruptTime) < 10) { if ((interruptTime - lastInterruptTime) < ROTARY_ENCODER_DEBOUNCE_TIME) {
rotaryEncoderVirtualPosition = (rotaryEncoderVirtualPosition - 5); rotaryEncoderVirtualPosition = (rotaryEncoderVirtualPosition - rotaryEncoderMultiStep);
} }
else { else {
rotaryEncoderVirtualPosition = (rotaryEncoderVirtualPosition - 1); rotaryEncoderVirtualPosition = (rotaryEncoderVirtualPosition - rotaryEncoderSingleStep);
} }
} }
if (rotaryEncoderVirtualPosition > rotaryEncoderMaxPosition) { if (rotaryEncoderVirtualPosition > rotaryEncoderMaxPosition) {
rotaryEncoderVirtualPosition = rotaryEncoderMaxPosition; rotaryEncoderVirtualPosition = rotaryEncoderMaxPosition;
} }
if (rotaryEncoderVirtualPosition < 0) { if (rotaryEncoderVirtualPosition < rotaryEncoderMinPosition) {
rotaryEncoderVirtualPosition = 0; rotaryEncoderVirtualPosition = rotaryEncoderMinPosition;
} }
break; break;
...@@ -259,372 +328,854 @@ void isr () { // Interrupt service routine is executed when ...@@ -259,372 +328,854 @@ void isr () { // Interrupt service routine is executed when
lastInterruptTime = interruptTime; lastInterruptTime = interruptTime;
} }
// ######################### INTERRUPTS #########################
// ######################### START ######################### // ######################### START #########################
void xSafeHardwarePowerOff() {
// analogWrite(MIXER_PIN, 0); // Turn mixer OFF for safety
digitalWrite(HEATING_ELEMENT_OUTPUT_PIN, LOW); // Turn heading element OFF for safety
//basePT100.xSafeHardwarePowerOff(); // Turn temperature sensor OFF for safety
}
void displayWelcome() {
lcdPrint(" Let's start", " Brewing!"); // Write welcome
delay(SETTING_WELCOME_TIMEOUT); // pause for effect
}
void setup() { void setup() {
// ++++++++++++++++++++++++ Library - DHT ++++++++++++++++++++++++ // ++++++++++++++++++++++++ Rotary Encoder ++++++++++++++++++++++++
//dht.begin(); pinMode (ROTARY_ENCODER_CLK_PIN,INPUT);
// ++++++++++++++++++++++++ Library - DHT ++++++++++++++++++++++++ pinMode (ROTARY_ENCODER_DT_PIN, INPUT);
// ++++++++++++++++++++++++ Library - LiquidCrystal_I2C ++++++++++++++++++++++++ pinMode (ROTARY_ENCODER_SW_PIN, INPUT);
lcd.begin (LCD_X,LCD_Y); // <<----- My LCD was 16x2 attachInterrupt (ROTARY_ENCODER_INTERRUPT_NUMBER, isr, FALLING);
// 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 // ++++++++++++++++++++++++ Heating Element Relay ++++++++++++++++++++++++
Setpoint = 100; pinMode (HEATING_ELEMENT_OUTPUT_PIN, OUTPUT);
digitalWrite (HEATING_ELEMENT_OUTPUT_PIN, LOW);
windowStartTime = millis();
dWattPerPulse = HEATING_ELEMENT_MAX_WATTAGE / HEATING_ELEMENT_AC_FREQUENCY_HZ;
//tell the PID to range between 0 and the full window size myPID.SetOutputLimits (0, WindowSize); // tell the PID to range between 0 and the full window size
myPID.SetOutputLimits(0, WindowSize); myPID.SetMode (AUTOMATIC); // turn the PID on
//turn the PID on // ++++++++++++++++++++++++ Mixer ++++++++++++++++++++++++
myPID.SetMode(AUTOMATIC); // pinMode (MIXER_PIN, OUTPUT);
// ++++++++++++++++++++++++ Heating Element Relay ++++++++++++++++++++++++ // analogWrite (MIXER_PIN, 0);
// ++++++++++++++++++++++++ Mixer ++++++++++++++++++++++++
pinMode(MIXER_PIN, OUTPUT); // ++++++++++++++++++++++++ Temperature Sensor PT100 ++++++++++++++++++++++++
analogWrite(MIXER_PIN, 0); //basePT100.setup();
// ++++++++++++++++++++++++ Mixer ++++++++++++++++++++++++ /*
// ++++++++++++++++++++++++ Temperature Sensor PT100 ++++++++++++++++++++++++ analogReference (INTERNAL1V1); // EXTERNAL && INTERNAL2V56 && INTERNAL1V1
// analogReference(EXTERNAL); pinMode (PT100_OUTPUT_PIN, OUTPUT); // setup temperature sensor input pin
analogReference(INTERNAL1V1); digitalWrite (PT100_OUTPUT_PIN, LOW); // initialize sensor off
// analogReference(INTERNAL2V56); */
// ++++++++++++++++++++++++ Serial Monitor ++++++++++++++++++++++++
pinMode(TEMPERATURE_SENSOR_PIN, OUTPUT); Serial.begin(SETTING_SERIAL_MONITOR_BAUD_RATE); // setup terminal baud rate
digitalWrite(TEMPERATURE_SENSOR_PIN, LOW); Serial.println(SETTING_SERIAL_MONITOR_WELCOME_MESSAGE); // print a start message to the terminal
// ++++++++++++++++++++++++ Temperature Sensor PT100 ++++++++++++++++++++++++
Serial.begin(9600); // ++++++++++++++++++++++++ Library - LiquidCrystal_I2C ++++++++++++++++++++++++
Serial.println("Let's start Brewing!"); lcd.begin (LCD_HORIZONTAL_RESOLUTION,LCD_VERTICAL_RESOLUTION); // <<----- My LCD was 16x2
lcd.setBacklightPin(LCD_BACKLIGHT_PIN,POSITIVE); // Setup backlight pin
lcd.setBacklight(HIGH); // Switch on the backlight
// ######################### INITIALIZE #########################
// ++++++++++++++++++++++++ Rotary Encoder ++++++++++++++++++++++++
// set operation state | INPUT : TRotaryEncoderMode newMode, int newPosition, int newMaxPosition, int newMinPosition, int newSingleStep, int newMultiStep
xSetupRotaryEncoder( eRotaryEncoderMode_Disabled, 0, 0, 0, 0, 0 );
// ++++++++++++++++++++++++ State Machine ++++++++++++++++++++++++
presetsMenuOption = ePresetsMenu_Trigo;
maltMenuOption = eMaltMenu_CastleMalting_Chteau_Pilsen_2RS;
settingsMenuOption = eSettingsMenu_PT100_Element;
cookingStage = eCookingStage_Startpoint;
// ++++++++++++++++++++++++ Global Variables ++++++++++++++++++++++++
cooking = false;
clockStartTime = 0;
clockCounter = 0;
clockIgnore = 0;
clockStart = false;
clockEnd = false;
cookTime = 3600;
cookTemperature = 25;
//cookMode = quick_start;
//cookMixerSpeed = 120;
cookHeatPWM = 5;
startpointTime = 120;
betaGlucanaseTime = 0;
debranchingTime = 0;
proteolyticTime = 0;
betaAmylaseTime = 3600;
alphaAmylaseTime = 1800;
mashoutTime = 300;
recirculationTime = 1200;
spargeTime = 1200;
boilTime = 5400;
coolingTime = 120;
startpointTemperature = 45;
betaGlucanaseTemperature = 40;
debranchingTemperature = 40;
proteolyticTemperature = 50;
betaAmylaseTemperature = 60;
alphaAmylaseTemperature = 70;
mashoutTemperature = 80;
recirculationTemperature = 80;
spargeTemperature = 80;
boilTemperature = 100;
coolingTemperature = 25;
refresh = true;
repaint = true;
// ++++++++++++++++++++++++ Interrupts ++++++++++++++++++++++++
lastInterruptTime = 0;
// ++++++++++++++++++++++++ PID ++++++++++++++++++++++++
WindowSize = HEATING_ELEMENT_DEFAULT_WINDOW_SIZE; // Time frame to operate in
// ######################### Code - Run Once #########################
xSafeHardwarePowerOff();
displayWelcome();
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eMainMenu_GO, MENU_SIZE_MAIN_MENU - 1, 0, 1, 1 );
} }
// ######################### START ######################### // ######################### START #########################
void loop() { void loop() {
switch(state) { unsigned long inactivityTime = millis() - lastInterruptTime;
case state_welcome: {
runWelcome(); if(inactivityTime > SETTING_MAX_INACTIVITY_TIME) { // Inactivity check
if(refresh) {
repaint = true;
refresh = false;
}
displayStatus();
}
else {
displayMainMenu();
}
operateMachine();
}
void xPaintStatusTemplate() {
// Clear LCD
lcd.clear();
// Position the cursor at the begining of where the temperature template goes onto the screen
lcd.home();
// Print the target and measured temperature template
if(cooking) {
lcd.print("ON : 000*C/000*C");
}
else {
lcd.print("OFF: 000*C/000*C");
}
// Position the cursor at the begining of where the mode and time template goes onto the screen
lcd.setCursor (0,LCD_VERTICAL_RESOLUTION-1);
lcd.print("**** 00:00");
}
void displayStatus() {
// Check whether a template repaint is required
if(repaint) {
// Repaint the LCD template
xPaintStatusTemplate();
// Reset the repaint flag after the repaint has been done
repaint = false;
}
// Print positions with no numbers, before the measured temperature value
lcd.setCursor (3,0);
if (basePT100.getCurrentTemperature() < 10) {
lcd.print(" ");
}
else {
if (basePT100.getCurrentTemperature() < 100) {
lcd.print(" ");
}
}
// Print measured temperature value onto the LCD
lcd.print(basePT100.getCurrentTemperature(), 1);
// Print positions with no numbers, before the target temperature value
lcd.setCursor (11,0);
if (cookTemperature < 10) {
lcd.print(" ");
}
else {
if (cookTemperature < 100) {
lcd.print(" ");
}
}
// Print target temperature value onto the LCD
lcd.print(cookTemperature);
// Calculate the numbers on the timer clock
int minutes = (clockCounter - clockIgnore) / 60;
int seconds = (clockCounter - clockIgnore) - minutes * 60;
// Position the cursor at the begining of where the timer goes onto the screen
lcd.setCursor (10, 1);
// Print the timer values onto the LCD
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 displayMainMenu() {
switch(menu_position[0]) {
case eMainMenu_GO: {
MainMenu_GO();
menu_position[0] = -1;
// reset operation state | INPUT : TRotaryEncoderMode newMode, int newPosition, int newMaxPosition, int newMinPosition, int newSingleStep, int newMultiStep
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eMainMenu_GO, MENU_SIZE_MAIN_MENU - 1, 0, 1, 1 );
break; break;
} }
case state_menu: { case eMainMenu_Presets: {
runMenu(); MainMenu_Presets();
menu_position[0] = -1;
// reset operation state | INPUT : TRotaryEncoderMode newMode, int newPosition, int newMaxPosition, int newMinPosition, int newSingleStep, int newMultiStep
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eMainMenu_Presets, MENU_SIZE_MAIN_MENU - 1, 0, 1, 1 );
break; break;
} }
/*case state_manual_time: { case eMainMenu_Malt: {
//runManualTime(); MainMenu_Malt();
menu_position[0] = -1;
// reset operation state | INPUT : TRotaryEncoderMode newMode, int newPosition, int newMaxPosition, int newMinPosition, int newSingleStep, int newMultiStep
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eMainMenu_Malt, MENU_SIZE_MAIN_MENU - 1, 0, 1, 1 );
break; break;
} }
case state_manual_temperature: { case eMainMenu_Startpoint: {
//runManualTemp(); MainMenu_Startpoint();
menu_position[0] = -1;
// reset operation state | INPUT : TRotaryEncoderMode newMode, int newPosition, int newMaxPosition, int newMinPosition, int newSingleStep, int newMultiStep
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eMainMenu_Startpoint, MENU_SIZE_MAIN_MENU - 1, 0, 1, 1 );
break; break;
} }
case state_manual_mixer: { case eMainMenu_BetaGlucanase: {
//runManualTemp(); MainMenu_BetaGlucanase();
menu_position[0] = -1;
// reset operation state | INPUT : TRotaryEncoderMode newMode, int newPosition, int newMaxPosition, int newMinPosition, int newSingleStep, int newMultiStep
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eMainMenu_BetaGlucanase, MENU_SIZE_MAIN_MENU - 1, 0, 1, 1 );
break; break;
}*/ }
case state_error: { case eMainMenu_Debranching: {
runError(); MainMenu_Debranching();
menu_position[0] = -1;
// reset operation state | INPUT : TRotaryEncoderMode newMode, int newPosition, int newMaxPosition, int newMinPosition, int newSingleStep, int newMultiStep
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eMainMenu_Settings, MENU_SIZE_MAIN_MENU - 1, 0, 1, 1 );
break; break;
} }
default: { case eMainMenu_Proteolytic: {
lcdPrint("Error", "The brewer has stoped working properly. Please shutdown NOW for your safety!"); MainMenu_Proteolytic();
state = state_error;
error = catastrofic_failure_program; menu_position[0] = -1;
// reset operation state | INPUT : TRotaryEncoderMode newMode, int newPosition, int newMaxPosition, int newMinPosition, int newSingleStep, int newMultiStep
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eMainMenu_Proteolytic, MENU_SIZE_MAIN_MENU - 1, 0, 1, 1 );
break;
} }
} case eMainMenu_BetaAmylase: {
} MainMenu_BetaAmylase();
void runWelcome() { menu_position[0] = -1;
// Write welcome
lcd.clear(); // reset operation state | INPUT : TRotaryEncoderMode newMode, int newPosition, int newMaxPosition, int newMinPosition, int newSingleStep, int newMultiStep
lcd.home (); // go home xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eMainMenu_BetaAmylase, MENU_SIZE_MAIN_MENU - 1, 0, 1, 1 );
lcd.print(" Let's start");
lcd.setCursor (0,1); // go to start of 2nd line
lcd.print(" Brewing!");
delay(SETTING_WELCOME_TIMEOUT);
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;
rotaryEncoderVirtualPosition = manual_temperature;
break;
}
case manual_time: {
// do work
cookTime = getTimer(cookTime);
menu_position[1] = -1;
rotaryEncoderVirtualPosition = 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;
rotaryEncoderVirtualPosition = manual_mode;
break;
}
case manual_mixer: {
// do work
cookMixerSpeed = getMixerSpeed(cookMixerSpeed);
menu_position[1] = -1;
rotaryEncoderVirtualPosition = manual_time;
break;
}
case manual_start: {
// do work
runStart();
menu_position[1] = -1;
rotaryEncoderVirtualPosition = manual_start;
break;
}
case manual_back: {
menu_position[0] = -1;
menu_position[1] = -1;
rotaryEncoderVirtualPosition = manual_back;
break;
}
default: {
// reset menu variables
menuSize = 6;
// display menu
lcd.clear();
lcd.home (); // go home
lcd.print("Manual Menu");
while(true) {
switch(rotaryEncoderVirtualPosition) {
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_mixer: {
lcd.setCursor (0,1); // go to start of 2nd line
lcd.print("-> Mixer Speed ");
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 ***");
rotaryEncoderVirtualPosition = 0;
}
}
if (!(digitalRead(PinSW))) { // check if pushbutton is pressed
menu_position[1] = rotaryEncoderVirtualPosition;
while (!digitalRead(PinSW)) {} // wait til switch is released
delay(10); // debounce
break;
}
}
}
}
break; break;
} }
case main_auto: { case eMainMenu_AlphaAmylase: {
switch(menu_position[1]) { MainMenu_AlphaAmylase();
case auto_recipe: {
// do work menu_position[0] = -1;
menu_position[1] = -1; // reset operation state | INPUT : TRotaryEncoderMode newMode, int newPosition, int newMaxPosition, int newMinPosition, int newSingleStep, int newMultiStep
rotaryEncoderVirtualPosition = auto_recipe; xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eMainMenu_AlphaAmylase, MENU_SIZE_MAIN_MENU - 1, 0, 1, 1 );
break;
}
case auto_start: {
// do work
menu_position[1] = -1;
rotaryEncoderVirtualPosition = auto_start;
break;
}
case auto_back: {
// reset choces
menu_position[0] = -1;
menu_position[1] = -1;
// set menu position
rotaryEncoderVirtualPosition = main_auto;
break;
}
default: {
// reset menu variables
//rotaryEncoderVirtualPosition = 0;
menuSize = 3;
// display menu
lcd.clear();
lcd.home (); // go home
lcd.print("Automatic Menu");
while(true) {
switch(rotaryEncoderVirtualPosition) {
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 ***");
rotaryEncoderVirtualPosition = 0;
}
}
if (!(digitalRead(PinSW))) { // check if pushbutton is pressed
menu_position[1] = rotaryEncoderVirtualPosition;
while (!digitalRead(PinSW)) {} // wait til switch is released
delay(10); // debounce
break;
}
}
}
}
break; break;
} }
default: { case eMainMenu_Mashout: {
// reset menu variables MainMenu_Mashout();
//rotaryEncoderVirtualPosition = 0;
menuSize = 2; menu_position[0] = -1;
// reset operation state | INPUT : TRotaryEncoderMode newMode, int newPosition, int newMaxPosition, int newMinPosition, int newSingleStep, int newMultiStep
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eMainMenu_Mashout, MENU_SIZE_MAIN_MENU - 1, 0, 1, 1 );
break;
}
case eMainMenu_Recirculation: {
MainMenu_Recirculation();
menu_position[0] = -1;
// reset operation state | INPUT : TRotaryEncoderMode newMode, int newPosition, int newMaxPosition, int newMinPosition, int newSingleStep, int newMultiStep
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eMainMenu_Recirculation, MENU_SIZE_MAIN_MENU - 1, 0, 1, 1 );
// display menu break;
lcd.clear(); }
lcd.home (); // go home case eMainMenu_Sparge: {
lcd.print("Main Menu"); MainMenu_Sparge();
while(true) { menu_position[0] = -1;
// reset operation state | INPUT : TRotaryEncoderMode newMode, int newPosition, int newMaxPosition, int newMinPosition, int newSingleStep, int newMultiStep
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eMainMenu_Sparge, MENU_SIZE_MAIN_MENU - 1, 0, 1, 1 );
break;
}
case eMainMenu_Boil: {
MainMenu_Boil();
menu_position[0] = -1;
// reset operation state | INPUT : TRotaryEncoderMode newMode, int newPosition, int newMaxPosition, int newMinPosition, int newSingleStep, int newMultiStep
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eMainMenu_Boil, MENU_SIZE_MAIN_MENU - 1, 0, 1, 1 );
break;
}
case eMainMenu_Hops: {
MainMenu_Hops();
menu_position[0] = -1;
// reset operation state | INPUT : TRotaryEncoderMode newMode, int newPosition, int newMaxPosition, int newMinPosition, int newSingleStep, int newMultiStep
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eMainMenu_Hops, MENU_SIZE_MAIN_MENU - 1, 0, 1, 1 );
break;
}
case eMainMenu_Cooling: {
MainMenu_Cooling();
menu_position[0] = -1;
// reset operation state | INPUT : TRotaryEncoderMode newMode, int newPosition, int newMaxPosition, int newMinPosition, int newSingleStep, int newMultiStep
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eMainMenu_Cooling, MENU_SIZE_MAIN_MENU - 1, 0, 1, 1 );
break;
}
case eMainMenu_Settings: {
MainMenu_Settings();
menu_position[0] = -1;
// reset operation state | INPUT : TRotaryEncoderMode newMode, int newPosition, int newMaxPosition, int newMinPosition, int newSingleStep, int newMultiStep
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eMainMenu_Settings, MENU_SIZE_MAIN_MENU - 1, 0, 1, 1 );
break;
}
default: {
if(repaint) {
// display menu
lcd.clear();
lcd.home (); // go home
lcd.print("Brewery Menu");
switch(rotaryEncoderVirtualPosition) { switch(rotaryEncoderVirtualPosition) {
case main_manual: { case eMainMenu_GO: {
lcd.setCursor (0,1); // go to start of 2nd line
lcd.print("-> GO ");
break;
}
case eMainMenu_Presets: {
lcd.setCursor (0,1); // go to start of 2nd line
lcd.print("-> Presets ");
break;
}
case eMainMenu_Malt: {
lcd.setCursor (0,1); // go to start of 2nd line
lcd.print("-> Malt ");
break;
}
case eMainMenu_Startpoint: {
lcd.setCursor (0,1); // go to start of 2nd line
lcd.print("-> Startpoint ");
break;
}
case eMainMenu_BetaGlucanase: {
lcd.setCursor (0,1); // go to start of 2nd line
lcd.print("-> BetaGlucanase");
break;
}
case eMainMenu_Debranching: {
lcd.setCursor (0,1); // go to start of 2nd line
lcd.print("-> Debranching ");
break;
}
case eMainMenu_Proteolytic: {
lcd.setCursor (0,1); // go to start of 2nd line
lcd.print("-> Proteolytic ");
break;
}
case eMainMenu_BetaAmylase: {
lcd.setCursor (0,1); // go to start of 2nd line
lcd.print("-> Beta Amylase ");
break;
}
case eMainMenu_AlphaAmylase: {
lcd.setCursor (0,1); // go to start of 2nd line
lcd.print("-> Alpha Amylase");
break;
}
case eMainMenu_Mashout: {
lcd.setCursor (0,1); // go to start of 2nd line lcd.setCursor (0,1); // go to start of 2nd line
lcd.print("-> Manual "); lcd.print("-> Mashout ");
delay(100);
break; break;
} }
case main_auto: { case eMainMenu_Recirculation: {
lcd.setCursor (0,1); // go to start of 2nd line lcd.setCursor (0,1); // go to start of 2nd line
lcd.print("-> Automatic "); lcd.print("-> Recirculation");
delay(100); break;
}
case eMainMenu_Sparge: {
lcd.setCursor (0,1); // go to start of 2nd line
lcd.print("-> Sparge ");
break;
}
case eMainMenu_Boil: {
lcd.setCursor (0,1); // go to start of 2nd line
lcd.print("-> Boil ");
break;
}
case eMainMenu_Hops: {
lcd.setCursor (0,1); // go to start of 2nd line
lcd.print("-> Hops ");
break;
}
case eMainMenu_Cooling: {
lcd.setCursor (0,1); // go to start of 2nd line
lcd.print("-> Cooling ");
break;
}
case eMainMenu_Settings: {
lcd.setCursor (0,1); // go to start of 2nd line
lcd.print("-> Settings ");
break; break;
} }
default: { default: {
//lcd.setCursor (0,1); // go to start of 2nd line // reset operation state | INPUT : TRotaryEncoderMode newMode, int newPosition, int newMaxPosition, int newMinPosition, int newSingleStep, int newMultiStep
//lcd.print("*** Error ***"); xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eMainMenu_GO, MENU_SIZE_MAIN_MENU - 1, 0, 1, 1 );
rotaryEncoderVirtualPosition = 0;
} }
} }
if (!(digitalRead(PinSW))) { // check if pushbutton is pressed repaint = false;
menu_position[0] = rotaryEncoderVirtualPosition; }
while (!digitalRead(PinSW)) {} // wait til switch is released
delay(10); // debounce if ((digitalRead(ROTARY_ENCODER_SW_PIN))) { // check if pushbutton is pressed
break; menu_position[0] = rotaryEncoderVirtualPosition;
} while (digitalRead(ROTARY_ENCODER_SW_PIN)) {} // wait til switch is released
delay(10); // debounce
break;
} }
} }
} }
} }
void MainMenu_GO() {
startBrewing();
backToStatus();
}
void MainMenu_Presets() {
}
void MainMenu_Malt() {
}
void MainMenu_Startpoint() {
startpointTime = getTimer( startpointTime );
startpointTemperature = xSetGenericValue( startpointTemperature, 0, 120, "temperature", "*C" );
}
void MainMenu_BetaGlucanase() {
betaGlucanaseTime = getTimer( betaGlucanaseTime );
betaGlucanaseTemperature = xSetGenericValue( betaGlucanaseTemperature, 0, 120, "temperature", "*C" );
}
void MainMenu_Debranching() {
debranchingTime = getTimer( debranchingTime );
debranchingTemperature = xSetGenericValue( debranchingTemperature, 0, 120, "temperature", "*C" );
}
void MainMenu_Proteolytic() {
proteolyticTime = getTimer( proteolyticTime );
proteolyticTemperature = xSetGenericValue( proteolyticTemperature, 0, 120, "temperature", "*C" );
}
void MainMenu_BetaAmylase() {
betaAmylaseTime = getTimer( betaAmylaseTime );
betaAmylaseTemperature = xSetGenericValue( betaAmylaseTemperature, 0, 120, "temperature", "*C" );
}
void MainMenu_AlphaAmylase() {
alphaAmylaseTime = getTimer( alphaAmylaseTime );
alphaAmylaseTemperature = xSetGenericValue( alphaAmylaseTemperature, 0, 120, "temperature", "*C" );
}
void MainMenu_Mashout() {
mashoutTime = getTimer( mashoutTime );
mashoutTemperature = xSetGenericValue( mashoutTemperature, 0, 120, "temperature", "*C" );
}
void MainMenu_Recirculation() {
recirculationTime = getTimer( recirculationTime );
recirculationTemperature = xSetGenericValue( recirculationTemperature, 0, 120, "temperature", "*C" );
}
void MainMenu_Sparge() {
spargeTime = getTimer( spargeTime );
spargeTemperature = xSetGenericValue( spargeTemperature, 0, 120, "temperature", "*C" );
}
void MainMenu_Boil() {
boilTime = getTimer( boilTime );
boilTemperature = xSetGenericValue( boilTemperature, 0, 120, "temperature", "*C" );
}
void MainMenu_Hops() {
}
void MainMenu_Coooling() {
coolingTime = getTimer( coolingTime );
coolingTemperature = xSetGenericValue( coolingTemperature, 0, 120, "temperature", "*C" );
}
void MainMenu_Settings() {
}
void xCountTheTime( int temperatureRange ) {
// Check if the machine is in the right temperature range, for the current mode,
if(!(basePT100.getCurrentTemperature() > (cookTemperature - temperatureRange) && basePT100.getCurrentTemperature() < (cookTemperature + temperatureRange))) {
clockIgnore += millis() - clockStartTime - clockCounter;
}
// Calculate the remaining time on the clock
clockCounter = cookTime - ((millis() - clockStartTime - clockIgnore) / 1000);
}
bool isTimeLeft() {
if( clockCounter >= cookTime ) {
return false;
}
return true;
}
unsigned long ulWattToWindowTime( unsigned long appliedWatts ) {
unsigned long ulPulsesRequired = ulAppliedWatts / dWattPerPulse;
return windowSize / 1000.0 * ulPulsesRequired;
}
bool xRegulateTemperature() {
double diference = basePT100.getCurrentTemperature() - cookTemperature;
bool overTemperature = false;
unsigned long wattage = 0.0;
// Deviation between the cook temperature set and the cook temperature measured
if( diference < 0.0 ) {
diference = diference * (-1.0);
overTemperature = true;
}
// Calculate applied wattage, based on the distance from the target temperature
if( overTemperature ) {
// turn it off
wattage = 0.0;
} else {
if(diffrence <= 1) {
// turn it off
wattage = 0.0;
} else {
if(diffrence <= 3) {
// pulse lightly at 500 watt
wattage = 500.0;
} else {
if(diffrence <= 6) {
// pulse moderately at 1000 watt
wattage = 1000.0;
} else {
if(diffrence <= 9) {
// pulse hardly at 2000 watt
wattage = 2000.0;
} else {
//pulse constantly at HEATING_ELEMENT_MAX_WATTAGE watt
wattage = HEATING_ELEMENT_MAX_WATTAGE;
}
}
}
}
}
// Update the recorded time for the begining of the window, if the previous window has passed
while((millis() - windowStartTime) > WindowSize) { // Check if it's time to vary the pulse width modulation and if so do it by shifting the "Relay in ON" Window
windowStartTime += WindowSize;
}
// Apply wattage to the element at the right time
if( ulWattToWindowTime( wattage ) > (millis() - windowStartTime)) {
digitalWrite(HEATING_ELEMENT_OUTPUT_PIN,HIGH);
} else {
digitalWrite(HEATING_ELEMENT_OUTPUT_PIN,LOW);
}
}
void xWarnClockEnded() {
/// TODO
}
void xStageFirstRun( int stageTime, int stageTemperature ) {
// Set the clock
cookTime = stageTime;
// Set the target temperature
cookTemperature = stageTemperature;
// Reset the clock
clockStartTime = millis();
clockIgnore = 0;
}
void xTransitionIntoStage_GlobalVariables(eCookingStages nextStage) {
// Reset global stage variables
stageFirstRun = true;
cookingStage = nextStage;
}
void xTransitionIntoStage(eCookingStages nextStage) {
// Turn off all hardware that can damage itself if the machine is not cooking
xSafeHardwarePowerOff();
// Warn the user a stage has ended
xWarnClockEnded();
// Reset global stage variables
xTransitionIntoStage_GlobalVariables( nextStage );
}
void xBasicStageOperation( int iStageTime, int iStageTemperature, int iStageTemperatureRange, eCookingStages nextStage ) {
if(stageFirstRun) {
// Don't run this again
stageFirstRun = false;
// When the stage should be skipped
if( iStageTime == 0) {
// Continue to the next stage
xTransitionIntoStage_GlobalVariables( nextStage );
// There is nothing to do, in this stage
return;
} else {
// Set the clock, target temperature and Reset the clock
xStageFirstRun( iStageTime, iStageTemperature );
}
} else {
// Account for time spent at the target temperature | Input 1: range in ºC within which the target temperature is considered to be reached
xCountTheTime( iStageTemperatureRange );
if( isTimeLeft() ) {
// Do temperature control
xRegulateTemperature();
} else {
// Continue to the next stage
xTransitionIntoStage( nextStage );
// There is nothing to do, in this stage
return;
}
}
// There is nothing to do, in this iteration
return;
}
void xWarnCookEnded() {
/// TODO
}
bool stageFirstRun = true;
void operateMachine() {
// Measure temperature, for effect
basePT100.measure();
upPT100.measure();
downPT100.measure();
// If cooking is done, return (this is a nice place to double check safety and ensure the cooking parts aren't on.
if(!cooking) {
xSafeHardwarePowerOff();
return;
}
// Operate the machine according to the current mode
switch(cookingStage) {
case eCookingStage_Startpoint: {
// A basic operation for a basic stage
xBasicStageOperation( startpointTime, startpointTemperature, 1, eCookingStage_BetaGlucanase );
// There is nothing to do, in this iteration
break;
}
case eCookingStage_BetaGlucanase: {
// A basic operation for a basic stage
xBasicStageOperation( betaGlucanaseTime, betaGlucanaseTemperature, 1, eCookingStage_Debranching );
// There is nothing to do, in this iteration
break;
}
case eCookingStage_Debranching: {
// A basic operation for a basic stage
xBasicStageOperation( debranchingTime, debranchingTemperature, 1, eCookingStage_Proteolytic );
// There is nothing to do, in this iteration
break;
}
case eCookingStage_Proteolytic: {
// A basic operation for a basic stage
xBasicStageOperation( proteolyticTime, proteolyticTemperature, 1, eCookingStage_BetaAmylase );
// There is nothing to do, in this iteration
break;
}
case eCookingStage_BetaAmylase: {
// A basic operation for a basic stage
xBasicStageOperation( betaAmylaseTime, betaAmylaseTemperature, 1, eCookingStage_AlphaAmylase );
// There is nothing to do, in this iteration
break;
}
case eCookingStage_AlphaAmylase: {
// A basic operation for a basic stage
xBasicStageOperation( alphaAmylaseTime, alphaAmylaseTemperature, 1, eCookingStage_Mashout );
// There is nothing to do, in this iteration
break;
}
case eCookingStage_Mashout: {
// A basic operation for a basic stage
xBasicStageOperation( mashoutTime, mashoutTemperature, 1, eCookingStage_Recirculation );
// There is nothing to do, in this iteration
break;
}
case eCookingStage_Recirculation: {
// A basic operation for a basic stage
xBasicStageOperation( recirculationTime, recirculationTemperature, 1, eCookingStage_Sparge );
// There is nothing to do, in this iteration
break;
}
case eCookingStage_Sparge: {
// A basic operation for a basic stage
xBasicStageOperation( spargeTime, spargeTemperature, 1, eCookingStage_Boil );
// There is nothing to do, in this iteration
break;
}
case eCookingStage_Boil: {
// A basic operation for a basic stage
xBasicStageOperation( boilTime, boilTemperature, 1, eCookingStage_Cooling );
// There is nothing to do, in this iteration
break;
}
case eCookingStage_Cooling: {
// A basic operation for a basic stage
xBasicStageOperation( coolingTime, coolingTemperature, 1, eCookingStage_Done );
// There is nothing to do, in this iteration
break;
}
default : {
// Update state
cooking = false;
// Warn the user that the cooking is done
xWarnCookEnded();
}
}
}
// #################################################### Helpers ##################################################################
void startBrewing() {
cooking = true;
}
void stopBrewing() {
cooking = false;
}
void backToStatus() {
lastInterruptTime = millis() - SETTING_MAX_INACTIVITY_TIME - 1;
}
// #################################################### Helpers ##################################################################
// #################################################### Set Variables ##################################################################
int getTimer(int init) { int getTimer(int init) {
state_machine initialState = state; // set operation state | INPUT : TRotaryEncoderMode newMode, int newPosition, int newMaxPosition, int newMinPosition, int newSingleStep, int newMultiStep
xSetupRotaryEncoder( eRotaryEncoderMode_Time, init, 7200, 0, 1, 30 );
// set operation state
state = state_manual_time;
rotaryEncoderVirtualPosition = init;
// initialize variables // initialize variables
int rotaryEncoderPreviousPosition = 0; int rotaryEncoderPreviousPosition = 0;
...@@ -635,16 +1186,24 @@ int getTimer(int init) { ...@@ -635,16 +1186,24 @@ int getTimer(int init) {
lcd.clear(); lcd.clear();
lcd.home(); lcd.home();
lcd.print("Set Time"); lcd.print("Set Time");
lcd.setCursor (0,LCD_Y-1); lcd.setCursor (0,LCD_VERTICAL_RESOLUTION-1);
lcd.print(" 0:00"); lcd.print(" 0:00");
while(true) { while(true) {
// Check for timer set // Check if pushbutton is pressed
if (!(digitalRead(PinSW))) { // check if pushbutton is pressed if ((digitalRead(ROTARY_ENCODER_SW_PIN))) {
while (!digitalRead(PinSW)) {} // wait til switch is released // Wait until switch is released
delay(10); // debounce while (digitalRead(ROTARY_ENCODER_SW_PIN)) {}
// debounce
delay(10);
// Job is done, break the circle
break; break;
} } else {
// Don't forget to keep an eye on the cooking
operateMachine();
}
// display current timer // display current timer
if (rotaryEncoderVirtualPosition != rotaryEncoderPreviousPosition) { if (rotaryEncoderVirtualPosition != rotaryEncoderPreviousPosition) {
...@@ -652,7 +1211,7 @@ int getTimer(int init) { ...@@ -652,7 +1211,7 @@ int getTimer(int init) {
minutes = rotaryEncoderVirtualPosition/60; minutes = rotaryEncoderVirtualPosition/60;
seconds = rotaryEncoderVirtualPosition-minutes*60; seconds = rotaryEncoderVirtualPosition-minutes*60;
lcd.setCursor (0,LCD_Y-1); lcd.setCursor (0,LCD_VERTICAL_RESOLUTION-1);
lcd.print(" "); lcd.print(" ");
lcd.print(minutes); lcd.print(minutes);
lcd.print(":"); lcd.print(":");
...@@ -664,15 +1223,16 @@ int getTimer(int init) { ...@@ -664,15 +1223,16 @@ int getTimer(int init) {
} }
} }
state = initialState; backToStatus();
rotaryEncoderMode = initialState;
return rotaryEncoderVirtualPosition; return rotaryEncoderVirtualPosition;
} }
int getTemperature(int init) { int getTemperature(int init) {
state_machine initialState = state; TRotaryEncoderMode initialState = rotaryEncoderMode;
// set operation state // set operation state
state = state_manual_temperature; rotaryEncoderMode = eRotaryEncoderMode_Generic;
rotaryEncoderVirtualPosition = init; rotaryEncoderVirtualPosition = init;
// initialize variables // initialize variables
...@@ -682,24 +1242,32 @@ int getTemperature(int init) { ...@@ -682,24 +1242,32 @@ int getTemperature(int init) {
lcd.clear(); lcd.clear();
lcd.home(); lcd.home();
lcd.print("Set Temperature"); lcd.print("Set Temperature");
lcd.setCursor (0,LCD_Y-1); lcd.setCursor (0,LCD_VERTICAL_RESOLUTION-1);
lcd.print(" 0 *C"); lcd.print(" 0 *C");
rotaryEncoderMaxPosition = TEMPERATURE_MAX_POSITION; rotaryEncoderMaxPosition = TEMPERATURE_SETTING_MAX_VALUE;
while(true) { while(true) {
// Check for timer set // Check if pushbutton is pressed
if (!(digitalRead(PinSW))) { // check if pushbutton is pressed if ((digitalRead(ROTARY_ENCODER_SW_PIN))) {
while (!digitalRead(PinSW)) {} // wait til switch is released // Wait until switch is released
delay(10); // debounce while (digitalRead(ROTARY_ENCODER_SW_PIN)) {}
// debounce
delay(10);
// Job is done, break the circle
break; break;
} } else {
// Don't forget to keep an eye on the cooking
operateMachine();
}
// display current timer // display current timer
if (rotaryEncoderVirtualPosition != rotaryEncoderPreviousPosition) { if (rotaryEncoderVirtualPosition != rotaryEncoderPreviousPosition) {
rotaryEncoderPreviousPosition = rotaryEncoderVirtualPosition; rotaryEncoderPreviousPosition = rotaryEncoderVirtualPosition;
lcd.setCursor (0,LCD_Y-1); lcd.setCursor (0,LCD_VERTICAL_RESOLUTION-1);
lcd.print(" "); lcd.print(" ");
if(rotaryEncoderVirtualPosition<10) { if(rotaryEncoderVirtualPosition<10) {
lcd.print(" "); lcd.print(" ");
...@@ -715,426 +1283,69 @@ int getTemperature(int init) { ...@@ -715,426 +1283,69 @@ int getTemperature(int init) {
} }
} }
state = initialState; backToStatus();
rotaryEncoderMode = initialState;
return rotaryEncoderVirtualPosition; return rotaryEncoderVirtualPosition;
} }
int getMode() { int xSetGenericValue(int init, int min, int max, char *valueName, char *unit) {
state_machine initialState = state; // set operation state | INPUT : TRotaryEncoderMode newMode, int newPosition, int newMaxPosition, int newMinPosition, int newSingleStep, int newMultiStep
int initialMenuSize = menuSize; xSetupRotaryEncoder( eRotaryEncoderMode_Generic, init, max, min, 1, 5 );
// set operation state
state = state_manual_mode;
menuSize = 2;
rotaryEncoderVirtualPosition = cookMode;
// initialize variables // initialize variables
int rotaryEncoderPreviousPosition = 0; int rotaryEncoderPreviousPosition = 0;
// Setup Screen // Setup Screen
lcd.clear(); lcd.clear();
lcd.home(); lcd.home();
lcd.print("Set Mode"); lcd.print( "Set " );
lcd.setCursor (0,LCD_Y-1); lcd.print( valueName );
lcd.print(" Quick Start"); lcd.setCursor ( 0 , LCD_VERTICAL_RESOLUTION - 1 );
lcd.print( " 0 " );
lcd.print( unit );
rotaryEncoderMaxPosition = TEMPERATURE_SETTING_MAX_VALUE;
while(true) { while(true) {
// Check for timer set // Check if pushbutton is pressed
if (!(digitalRead(PinSW))) { // check if pushbutton is pressed if ( digitalRead(ROTARY_ENCODER_SW_PIN) ) {
while (!digitalRead(PinSW)) {} // wait til switch is released // Wait until switch is released
delay(10); // debounce while ( digitalRead(ROTARY_ENCODER_SW_PIN) ) {}
break;
}
// display current timer
if (rotaryEncoderVirtualPosition != rotaryEncoderPreviousPosition) {
rotaryEncoderPreviousPosition = rotaryEncoderVirtualPosition;
lcd.setCursor (0,LCD_Y-1);
switch(rotaryEncoderVirtualPosition) { // debounce
case quick_start: { delay( 10 );
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 rotaryEncoderVirtualPosition;
}
int getMixerSpeed(int init) {
state_machine initialState = state;
// set operation state
state = state_manual_mixer;
rotaryEncoderVirtualPosition = init;
// initialize variables // Job is done, break the circle
int rotaryEncoderPreviousPosition = 0;
int mixerSpeed = 0;
// Setup Screen
lcd.clear();
lcd.home();
lcd.print("Set Mixer Speed");
lcd.setCursor (0,LCD_Y-1);
lcd.print(" 000");
rotaryEncoderMaxPosition = MIXER_MAX_POSITION;
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; break;
} } else {
// Don't forget to keep an eye on the cooking
operateMachine();
}
// display current timer // Check if there was an update by the rotary encoder
if (rotaryEncoderVirtualPosition != rotaryEncoderPreviousPosition) { if( rotaryEncoderVirtualPosition != rotaryEncoderPreviousPosition ) {
rotaryEncoderPreviousPosition = rotaryEncoderVirtualPosition; rotaryEncoderPreviousPosition = rotaryEncoderVirtualPosition;
lcd.setCursor (0,LCD_Y-1); lcd.setCursor( 0, LCD_VERTICAL_RESOLUTION - 1 );
lcd.print(" "); lcd.print( " " );
//lcd.print(minutes); if( rotaryEncoderVirtualPosition < 10 ) {
//lcd.print(":"); lcd.print( " " );
if(rotaryEncoderVirtualPosition<100) {
lcd.print("0");
if(rotaryEncoderVirtualPosition<10) {
lcd.print("0");
}
}
lcd.print(rotaryEncoderVirtualPosition);
lcd.println(" ");
// DEBUG
analogWrite(MIXER_PIN, rotaryEncoderVirtualPosition);
}
}
state = initialState;
return rotaryEncoderVirtualPosition;
}
void runStart() {
// Working environment variables
float runCurrentTemperature;
long runTargetTemperature;
unsigned long runStartTime;
unsigned long runTargetTime;
cook_mode_list runCurrentMode;
unsigned long runMixerSpeed;
// Configure environment
boolean clockStart = false;
boolean clockEnd = false;
// Iterative work
while(true) {
// Build Instructions
switch(menu_position[0]) {
case main_manual: {
// whenever changes are made to the cook variables, they must be applied to the running variables
runTargetTemperature = cookTemperature;
runTargetTime = cookTime;
runCurrentMode = cookMode;
runMixerSpeed = cookMixerSpeed;
// check if time ended and is time to stop and return to menu
if(clockStart && clockEnd) {
// Turn mixer OFF for safety
analogWrite(MIXER_PIN, 0);
// Turn heading element OFF for safety
digitalWrite(HEATING_ELEMENT,LOW);
// Pause for efect
delay(1000);
return;
}
break;
}
case main_auto: {
// get the next instruction
// if it's time for a new instruction
// if human interaction is required
// display message
// sound buzzer
// check if rotary encoder press to continue
// check what variables are afected
// check what the new values are
// apply the values
// if it's NOT time for a new instruction
//delay(1000);
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");
}
float amostra1 = -1;
float amostraAnterior = -1;
unsigned long lastTemperatureRead = millis();
while(true) {
if(millis() - lastTemperatureRead >= 1000) {
amostraAnterior = amostra1;
digitalWrite(TEMPERATURE_SENSOR_PIN, HIGH);
//delay(20);
amostra1 = analogRead(ponto1);
digitalWrite(TEMPERATURE_SENSOR_PIN, LOW);
lastTemperatureRead = millis();
}
float Vs = 1.081; //4.9345;
float Vin = 4.87; //8.8345;
float adcStepCount = 1024.0;
float R1 = 606.0;
float Rl = 2.7; //2.9;
float R_OpTemp = 0; //19.7; //21.597; //24.37;
//Vout = amostra1 * Vs / adcStepCount;// + 0.0079816667;
Vout = (amostra1+amostraAnterior) / 2 * Vs / adcStepCount;// + 0.0079816667;
//Rx = 151.5 * Vout / ( 11.01 - Vout ) - 30;
Rx = R1 / ( Vin / Vout - 1.0) - Rl - R_OpTemp;
runCurrentTemperature = 1.08271 * pow(10.0, -13.0) * (3.12508 * pow(10.0, 16.0) - 5.65566 * pow(10.0, 6.0) * sqrt(3.51501 * pow(10.0, 19.0) - 4.61805 * pow(10.0, 16.0) * Rx));
/*
Serial.print("O valor das entradas sao: [");
Serial.print(amostra1);
Serial.print(", ");
Serial.print(amostra2);
Serial.print("]");
Serial.print("diferenca: [");
Serial.print(diferenca, 6);
Serial.print("] tensao por amortra: [");
Serial.print(tensaoPorAmostra, 6);
Serial.print("] Vg: [");
Serial.print(Vg, 6);
Serial.print("] Vs: [");
Serial.print(Vs);
Serial.print("] a: [");
Serial.print(a, 6);
Serial.print("] Rx: [");
Serial.print(Rx, 6);
*/
// Operate mixer
analogWrite(MIXER_PIN, runMixerSpeed);
// Operate the heating element
Input = runCurrentTemperature;
Setpoint = runTargetTemperature;
myPID.Compute();
// Get time and use as "date" of the sensor readings
unsigned long now = millis();
// Check if it's time to vary the pulse width modulation and if so do it by shifting the "Relay in ON" Window
if(now - windowStartTime>WindowSize)
{
windowStartTime += WindowSize;
}
// Check if the "date" is inside the "Relay ON" window and turn it ON; if not, turn it OFF
if(Output > now - windowStartTime) {
digitalWrite(HEATING_ELEMENT,HIGH);
if(Output != 0) {
Serial.print("O valor das entradas sao: [");
Serial.print(amostra1);
Serial.print("] Vout[");
Serial.print(Vout,6);
Serial.print("] Rx[");
Serial.print(Rx,6);
Serial.print("] Temperature[");
Serial.print(runCurrentTemperature,6);
Serial.print("] ");
Serial.print("+++ Diff: ");
Serial.print(now - windowStartTime);
Serial.print(" | Output: ");
Serial.println(Output);
}
} }
else { else {
digitalWrite(HEATING_ELEMENT,LOW); if( rotaryEncoderVirtualPosition < 100 ) {
lcd.print( " " );
if(Output != 0) {
Serial.print("O valor das entradas sao: [");
Serial.print(amostra1);
Serial.print("] Vout[");
Serial.print(Vout,6);
Serial.print("] Rx[");
Serial.print(Rx,6);
Serial.print("] Temperature[");
Serial.print(runCurrentTemperature,6);
Serial.print("] ");
Serial.print("--- Diff: ");
Serial.print(now - windowStartTime);
Serial.print(" | Output: ");
Serial.println(Output);
}
else {
Serial.print("O valor das entradas sao: [");
Serial.print(amostra1);
Serial.print("] Vout[");
Serial.print(Vout,6);
Serial.print("] Rx[");
Serial.print(Rx,6);
Serial.print("] Temperature[");
Serial.print(runCurrentTemperature,6);
Serial.println("]");
} }
} }
lcd.print( rotaryEncoderVirtualPosition );
// Print status to LCD lcd.print( " *C" );
//if(runCurrentTemperature > 0) { lcd.println( " " );
lcd.setCursor (5,0);
if (runCurrentTemperature < 10) {
lcd.print(" ");
}
else {
if (runCurrentTemperature < 100) {
lcd.print(" ");
}
}
lcd.print(runCurrentTemperature, 1);
lcd.setCursor (11,0);
if (runTargetTemperature < 10) {
lcd.print(" ");
}
else {
if (runTargetTemperature < 100) {
lcd.print(" ");
}
}
lcd.print(runTargetTemperature);
//}
// Check if the target temperature has been reached so the clock can move forward.
if(runCurrentTemperature == runTargetTemperature && clockStart == false) {
clockStart = true;
runStartTime = now;
}
// If the clock can move forward, calculate it's display time; if not, set it to the total cooking time
int displayTime = 0;
if(clockStart) {
displayTime = runTargetTime - ((now - runStartTime) / 1000);
if(displayTime <= 0) {
displayTime = 0;
clockEnd = true;
break;
}
}
else {
displayTime = runTargetTime;
}
// Print the clock to the LCD
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);
} }
} }
return rotaryEncoderVirtualPosition;
} }
void runError() { // ###################### Set Variables ##################################################
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) { void lcdPrint(String title, String message) {
int messageLength = message.length(); int messageLength = message.length();
...@@ -1146,8 +1357,8 @@ void lcdPrint(String title, String message) { ...@@ -1146,8 +1357,8 @@ void lcdPrint(String title, String message) {
lcd.print(title); lcd.print(title);
// print message // print message
if(messageLength <= LCD_X) { if(messageLength <= LCD_HORIZONTAL_RESOLUTION) {
lcd.setCursor(0,LCD_Y-1); lcd.setCursor(0,LCD_VERTICAL_RESOLUTION-1);
lcd.print(message); lcd.print(message);
delay(1000); delay(1000);
} }
...@@ -1164,8 +1375,8 @@ void lcdPrint(String title, String message) { ...@@ -1164,8 +1375,8 @@ void lcdPrint(String title, String message) {
} }
// print scrolling message // print scrolling message
for (int cursor = 0; cursor < messageLength - LCD_X; cursor+=2) { for (int cursor = 0; cursor < messageLength - LCD_HORIZONTAL_RESOLUTION; cursor+=2) {
lcd.setCursor(0,LCD_Y-1); lcd.setCursor(0,LCD_VERTICAL_RESOLUTION-1);
lcd.print(output_message.substring(cursor, cursor+16)); lcd.print(output_message.substring(cursor, cursor+16));
delay(500); delay(500);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment