Commit abf959fa authored by João Lino's avatar João Lino

menus sorted

menus sorted
parent d5ea03fd
...@@ -118,6 +118,7 @@ typedef struct menuData_ { ...@@ -118,6 +118,7 @@ typedef struct menuData_ {
int _position; int _position;
int _selection; int _selection;
bool _repaint; bool _repaint;
void (*_selectionFunction)(void);
} MenuData; } MenuData;
#endif #endif
...@@ -17,6 +17,14 @@ ...@@ -17,6 +17,14 @@
#include "CustomDataStructures.h" #include "CustomDataStructures.h"
#include "debug.h" #include "debug.h"
// ++++++++++++++++++++++++ FUNCTIONS (used in configuration) +++++++++++++++++++++++++++++++++
void runMainMenuSelection();
void runStartFromStageSelection();
void runBeerProfileSelection();
void runStageSelection();
void runMaltSelection();
void runSettingsSelection();
#include "config.h" #include "config.h"
#include "Melody.h" #include "Melody.h"
...@@ -38,13 +46,9 @@ void xWelcomeUser(); ...@@ -38,13 +46,9 @@ void xWelcomeUser();
void runMenu(); void runMenu();
void runSettingsSelection(); void runMenuProcessor( MenuData *data );
void runMaltSelection(); void runStageSelection_Generic( unsigned long * selectedStageTime, int *selectedStageTemperature);
void runStageSelection();
void runBeerProfileSelection();
void xStartStage( unsigned long *stageTime, int *stageTemperature, eCookingStages nextStage, bool bPurgePump, bool bSetFinalYield, bool bSetTime, bool bSetTemperature ); void xStartStage( unsigned long *stageTime, int *stageTemperature, eCookingStages nextStage, bool bPurgePump, bool bSetFinalYield, bool bSetTime, bool bSetTemperature );
...@@ -52,10 +56,6 @@ void xStartStageHeadless( eCookingStages nextStage, bool bPurgePump ); ...@@ -52,10 +56,6 @@ void xStartStageHeadless( eCookingStages nextStage, bool bPurgePump );
void xStartStageInteractive( unsigned long *stageTime, int *stageTemperature, eCookingStages nextStage ); void xStartStageInteractive( unsigned long *stageTime, int *stageTemperature, eCookingStages nextStage );
void runStartFromStageSelection();
void runMainMenuSelection();
void xCountTheTime( int temperatureRange, boolean bAverageUpDown ); void xCountTheTime( int temperatureRange, boolean bAverageUpDown );
bool isTimeLeft(); bool isTimeLeft();
......
...@@ -18,25 +18,12 @@ eBeerProfile beerProfile; ...@@ -18,25 +18,12 @@ eBeerProfile beerProfile;
eMenuType eMenuType; eMenuType eMenuType;
MenuData mdMainMenu = { ._title = MENU_MAIN_TITLE, ._dialog = MENU_MAIN_DIALOG, ._position = MENU_MAIN_INIT_POSITION, ._selection = MENU_MAIN_INIT_SELECTION, ._repaint = MENU_MAIN_INIT_REPAINT }; MenuData mdMainMenu = { ._title = MENU_MAIN_TITLE, ._dialog = MENU_MAIN_DIALOG, ._position = MENU_MAIN_INIT_POSITION, ._selection = MENU_MAIN_INIT_SELECTION, ._repaint = MENU_MAIN_INIT_REPAINT, ._selectionFunction = MENU_MAIN_FUNCTION };
MenuData mdStartFromStageMenu = { ._title = MENU_START_TITLE, ._dialog = MENU_START_DIALOG, ._position = MENU_START_INIT_POSITION, ._selection = MENU_START_INIT_SELECTION, ._repaint = MENU_START_INIT_REPAINT }; MenuData mdBeerProfileMenu = { ._title = MENU_PROFILE_TITLE, ._dialog = MENU_PROFILE_DIALOG, ._position = MENU_PROFILE_INIT_POSITION, ._selection = MENU_PROFILE_INIT_SELECTION, ._repaint = MENU_PROFILE_INIT_REPAINT, ._selectionFunction = MENU_PROFILE_FUNCTION };
MenuData mdBeerProfileMenu = { ._title = MENU_PROFILE_TITLE, ._dialog = MENU_PROFILE_DIALOG, ._position = MENU_PROFILE_INIT_POSITION, ._selection = MENU_PROFILE_INIT_SELECTION, ._repaint = MENU_PROFILE_INIT_REPAINT }; MenuData mdStageMenu = { ._title = MENU_STAGE_TITLE, ._dialog = MENU_STAGE_DIALOG, ._position = MENU_STAGE_INIT_POSITION, ._selection = MENU_STAGE_INIT_SELECTION, ._repaint = MENU_STAGE_INIT_REPAINT, ._selectionFunction = MENU_STAGE_FUNCTION };
MenuData mdStageMenu = { ._title = MENU_STAGE_TITLE, ._dialog = MENU_STAGE_DIALOG, ._position = MENU_STAGE_INIT_POSITION, ._selection = MENU_STAGE_INIT_SELECTION, ._repaint = MENU_STAGE_INIT_REPAINT }; MenuData mdMaltMenu = { ._title = MENU_MALT_TITLE, ._dialog = MENU_MALT_DIALOG, ._position = MENU_MALT_INIT_POSITION, ._selection = MENU_MALT_INIT_SELECTION, ._repaint = MENU_MALT_INIT_REPAINT, ._selectionFunction = MENU_MALT_FUNCTION };
MenuData mdMaltMenu = { ._title = MENU_MALT_TITLE, ._dialog = MENU_MALT_DIALOG, ._position = MENU_MALT_INIT_POSITION, ._selection = MENU_MALT_INIT_SELECTION, ._repaint = MENU_MALT_INIT_REPAINT }; MenuData mdSettingsMenu = { ._title = MENU_SETTINGS_TITLE, ._dialog = MENU_SETTINGS_DIALOG, ._position = MENU_SETTINGS_INIT_POSITION, ._selection = MENU_SETTINGS_INIT_SELECTION, ._repaint = MENU_SETTINGS_INIT_REPAINT, ._selectionFunction = MENU_SETTINGS_FUNCTION };
MenuData mdSettingsMenu = { ._title = MENU_SETTINGS_TITLE, ._dialog = MENU_SETTINGS_DIALOG, ._position = MENU_SETTINGS_INIT_POSITION, ._selection = MENU_SETTINGS_INIT_SELECTION, ._repaint = MENU_SETTINGS_INIT_REPAINT }; MenuData mdStartFromStageMenu = { ._title = MENU_START_TITLE, ._dialog = MENU_START_DIALOG, ._position = MENU_START_INIT_POSITION, ._selection = MENU_START_INIT_SELECTION, ._repaint = MENU_START_INIT_REPAINT, ._selectionFunction = MENU_START_FUNCTION };
//eMainMenuOptions eMainMenuPosition;
//eMainMenuOptions eMainMenuSelection;
eStageMenuOptions eStartFromStageMenuPosition;
eStageMenuOptions eStartFromStageMenuSelection;
eBeerProfileMenuOptions eBeerProfileMenuPosition;
eBeerProfileMenuOptions eBeerProfileMenuSelection;
eStageMenuOptions eStageMenuPosition;
eStageMenuOptions eStageMenuSelection;
eMaltMenuOptions eMaltMenuPosition;
eMaltMenuOptions eMaltMenuSelection;
eSettingsMenuOptions eSettingsMenuPosition;
eSettingsMenuOptions eSettingsMenuSelection;
// ++++++++++++++++++++++++ Global Variables ++++++++++++++++++++++++ // ++++++++++++++++++++++++ Global Variables ++++++++++++++++++++++++
boolean cooking; boolean cooking;
...@@ -147,10 +134,10 @@ void isr () { // Interrupt service routine is executed when a HIGH to LOW tr ...@@ -147,10 +134,10 @@ void isr () { // Interrupt service routine is executed when a HIGH to LOW tr
rotaryEncoderVirtualPosition = rotaryEncoderVirtualPosition - rotaryEncoderSingleStep; rotaryEncoderVirtualPosition = rotaryEncoderVirtualPosition - rotaryEncoderSingleStep;
} }
if (rotaryEncoderVirtualPosition > rotaryEncoderMaxPosition) { if (rotaryEncoderVirtualPosition > rotaryEncoderMaxPosition) {
rotaryEncoderVirtualPosition = rotaryEncoderMinPosition; rotaryEncoderVirtualPosition = rotaryEncoderMaxPosition;
} }
if (rotaryEncoderVirtualPosition < rotaryEncoderMinPosition) { if (rotaryEncoderVirtualPosition < rotaryEncoderMinPosition) {
rotaryEncoderVirtualPosition = rotaryEncoderMaxPosition; rotaryEncoderVirtualPosition = rotaryEncoderMinPosition;
} }
break; break;
...@@ -301,17 +288,6 @@ void setup() { ...@@ -301,17 +288,6 @@ void setup() {
// ++++++++++++++++++++++++ State Machine ++++++++++++++++++++++++ // ++++++++++++++++++++++++ State Machine ++++++++++++++++++++++++
eMenuType = eMenuType_Main; eMenuType = eMenuType_Main;
//eMainMenuPosition = MENU_MAIN_INIT_POSITION;
//eMainMenuSelection = MENU_MAIN_INIT_SELECTION;
eBeerProfileMenuPosition = eBeerProfileMenu_Basic;
eBeerProfileMenuSelection = eBeerProfileMenu_NULL;
eStageMenuPosition = eStageMenu_Startpoint;
eStageMenuSelection = eStageMenu_NULL;
eMaltMenuPosition = eMaltMenu_CastleMalting_Chteau_Pilsen_2RS;
eMaltMenuSelection = eMaltMenu_NULL;
eSettingsMenuPosition = eSettingsMenu_PT100_Element;
eSettingsMenuSelection = eSettingsMenu_NULL;
cookingStage = eCookingStage_Startpoint; cookingStage = eCookingStage_Startpoint;
beerProfile = eBeerProfile_Basic; beerProfile = eBeerProfile_Basic;
// ++++++++++++++++++++++++ Global Variables ++++++++++++++++++++++++ // ++++++++++++++++++++++++ Global Variables ++++++++++++++++++++++++
...@@ -394,1299 +370,1110 @@ void loop() { ...@@ -394,1299 +370,1110 @@ void loop() {
// ######################### FUNCTIONS ######################## // ######################### FUNCTIONS ########################
void runMenu() {
#ifdef DEBUG_OFF
boolean debug_go = repaint;
if (debug_go) {
debugPrintFunction("runMenu");
debugPrintVar("repaint", repaint);
debugPrintVar("eMenuType", eMenuType);
debugPrintVar("rotaryEncoderVirtualPosition", rotaryEncoderVirtualPosition);
}
#endif
switch (eMenuType) {
case eMenuType_Main: {
//eMainMenuPosition = static_cast<eMainMenuOptions>(rotaryEncoderVirtualPosition);
mdMainMenu._position = rotaryEncoderVirtualPosition;
mdMainMenu._repaint = repaint;
repaint = displayGenericMenu( &lcd, &mdMainMenu );
//repaint = displayMainMenu( &lcd, eMainMenuPosition, repaint );
if ( gotButtonPress( ROTARY_ENCODER_SW_PIN ) ) {
mdMainMenu._selection = mdMainMenu._position;
//eMainMenuSelection = eMainMenuPosition;
}
runMainMenuSelection(); void xCountTheTime( int temperatureMarginRange, boolean bMaximumOfUpDown ) {
unsigned long now = millis();
break; // Get current maximum sensed temperaure
double temperatureCount = 0;
if ( bMaximumOfUpDown ) {
float tup = upPT100.getCurrentTemperature();
float tdown = downPT100.getCurrentTemperature();
if (tup > tdown) {
temperatureCount = tdown;
} }
case eMenuType_StartFromStage: { else {
eStartFromStageMenuPosition = static_cast<eStageMenuOptions>(rotaryEncoderVirtualPosition); temperatureCount = tup;
repaint = displayStageMenu( &lcd, eStartFromStageMenuPosition, repaint );
if ( gotButtonPress( ROTARY_ENCODER_SW_PIN ) ) {
eStartFromStageMenuSelection = eStartFromStageMenuPosition;
} }
} else {
runStartFromStageSelection(); temperatureCount = basePT100.getCurrentTemperature();
break;
} }
case eMenuType_BeerProfile: {
eBeerProfileMenuPosition = static_cast<eBeerProfileMenuOptions>(rotaryEncoderVirtualPosition);
repaint = displayBeerProfileMenu( &lcd, eBeerProfileMenuPosition, repaint ); // Ignote time ticks if temperature is not within the acceptable margin for this stage
unsigned long elapsedTime = now - clockLastUpdate;
if ( gotButtonPress( ROTARY_ENCODER_SW_PIN ) ) { if ( temperatureCount < (cookTemperature - temperatureMarginRange) ) {
eBeerProfileMenuSelection = eBeerProfileMenuPosition; clockIgnore += elapsedTime;
} }
runBeerProfileSelection(); // Calculate the remaining time on the clock
clockCounter = cookTime * 1000 - (elapsedTime - clockIgnore);
break; // Don't let clock get bellow 0
if ( clockCounter < 0 ) {
clockCounter = 0;
} }
case eMenuType_Stage: {
eStageMenuPosition = static_cast<eStageMenuOptions>(rotaryEncoderVirtualPosition);
repaint = displayStageMenu( &lcd, eStageMenuPosition, repaint ); clockLastUpdate = now;
if ( gotButtonPress( ROTARY_ENCODER_SW_PIN ) ) {
eStageMenuSelection = eStageMenuPosition;
}
runStageSelection(); #ifdef DEBUG_OFF
debugPrintFunction("xCountTheTime");
debugPrintVar("millis()", now);
debugPrintVar("cookTime", cookTime);
debugPrintVar("clockStartTime", clockStartTime);
debugPrintVar("clockIgnore", clockIgnore);
debugPrintVar("clockCounter", clockCounter);
#endif
}
break; bool isTimeLeft() {
if ( clockCounter > 0 ) {
return true;
} }
case eMenuType_Malt: { return false;
eMaltMenuPosition = static_cast<eMaltMenuOptions>(rotaryEncoderVirtualPosition); }
repaint = displayMaltMenu( &lcd, eMaltMenuPosition, repaint ); //HEATING_ELEMENT_MAX_WATTAGE / HEATING_ELEMENT_AC_FREQUENCY_HZ
double ulWattToWindowTime( double ulAppliedWatts ) {
double ulPulsesRequired = ulAppliedWatts / dWattPerPulse;
return (double)iWindowSize / 1000.0 * ulPulsesRequired * 1000.0 / HEATING_ELEMENT_AC_FREQUENCY_HZ;
}
if ( gotButtonPress( ROTARY_ENCODER_SW_PIN ) ) { bool xRegulateTemperature( boolean bMaximumOfUpDown ) {
eMaltMenuSelection = eMaltMenuPosition; double difference = 0;
} bool overTemperature = false;
double wattage = 0.0;
runMaltSelection(); float tup = upPT100.getCurrentTemperature();
float tdown = downPT100.getCurrentTemperature();
float tbase = basePT100.getCurrentTemperature();
break; if ( bMaximumOfUpDown ) {
if (tup > tdown) {
difference = cookTemperature - tup;
} }
case eMenuType_Settings: { else {
eSettingsMenuPosition = static_cast<eSettingsMenuOptions>(rotaryEncoderVirtualPosition); difference = cookTemperature - tdown;
repaint = displaySettingsMenu( &lcd, eSettingsMenuPosition, repaint );
if ( gotButtonPress( ROTARY_ENCODER_SW_PIN ) ) {
eSettingsMenuSelection = eSettingsMenuPosition;
} }
runSettingsSelection(); if (tbase > cookTemperature && (tbase >= (PUMP_TEMPERATURE_MAX_OPERATION - 2.0) || difference >= 5.0)) {
difference = cookTemperature - tbase;
}
break; if ( (tbase < cookTemperature) && (difference < (cookTemperature - tbase)) ) {
difference = cookTemperature - tbase;
} }
} else {
difference = cookTemperature - tbase;
} }
#ifdef DEBUG_OFF // Deviation between the cook temperature set and the cook temperature measured
if (debug_go) { if ( difference < 0.0 ) {
debugPrintVar("repaint", repaint); difference = difference * (-1.0);
overTemperature = true;
} }
#endif
}
void runSettingsSelection() { // Calculate applied wattage, based on the distance from the target temperature
switch (eSettingsMenuSelection) { if ( overTemperature ) {
case eSettingsMenu_Pump: { // turn it off
// Stuff wattage = 0.0;
if ( xSetGenericValue( iPumpSpeed ? 0 : 1, 0, 1, "pump", "bool" ) ) {
iPumpSpeed = PUMP_SPEED_MAX_MOSFET;
} else { } else {
iPumpSpeed = PUMP_SPEED_STOP_MOSFET; //if(difference <= 0.1) {
// turn it off
// wattage = 0.0;
//} else {
if (difference <= 0.5) {
// pulse lightly at 500 watt
if (cookTemperature > 99.0) {
wattage = 2000.0;
} }
analogWrite(PUMP_PIN, iPumpSpeed); else {
if (cookTemperature > 70.0) {
backToStatus(); wattage = 1000.0;
break;
} }
case eSettingsMenu_PT100_Element: { else {
// Stuff wattage = 500.0;
backToStatus();
break;
} }
case eSettingsMenu_PT100_Up: {
// Stuff
backToStatus();
break;
} }
case eSettingsMenu_PT100_Down: { } else {
// Stuff if (difference <= 1.0) {
// pulse moderately at 1000 watt
backToStatus(); if (cookTemperature > 99.0) {
wattage = 2000.0;
break; }
else {
wattage = 1000.0;
} }
case eSettingsMenu_Back: {
eMenuType = eMenuType_Main;
repaint = true;
// reset operation state | INPUT : eRotaryEncoderMode newMode, int newPosition, int newMaxPosition, int newMinPosition, int newSingleStep, int newMultiStep
//xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eMainMenuPosition, MENU_SIZE_MAIN_MENU - 1, 1, 1, 0 );
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, mdMainMenu._position, MENU_SIZE_MAIN_MENU - 1, 1, 1, 0 );
break; } else {
if (difference <= 3.0) {
// pulse hardly at 2000 watt
wattage = 2000.0;
} else {
//pulse constantly at HEATING_ELEMENT_MAX_WATTAGE watt
wattage = HEATING_ELEMENT_MAX_WATTAGE;
} }
default: {
} }
} }
//}
eSettingsMenuSelection = eSettingsMenu_NULL;
}
void runMaltSelection() {
switch (eMaltMenuSelection) {
case eMaltMenu_CastleMalting_Chteau_Pilsen_2RS: {
// Stuff
backToStatus();
break;
} }
case eMaltMenu_CastleMalting_Wheat_Blanc: {
// Stuff
backToStatus(); // Update the recorded time for the begining of the window, if the previous window has passed
while ((millis() - windowStartTime) > iWindowSize) { // Check if it's time to vary the pulse width modulation and if so do it by shifting the "Relay in ON" Window
break; windowStartTime += iWindowSize;
} }
case eMaltMenu_Back: {
eMenuType = eMenuType_Main;
repaint = true;
// reset operation state | INPUT : eRotaryEncoderMode newMode, int newPosition, int newMaxPosition, int newMinPosition, int newSingleStep, int newMultiStep
//xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eMainMenuPosition, MENU_SIZE_MAIN_MENU - 1, 1, 1, 0 );
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, mdMainMenu._position, MENU_SIZE_MAIN_MENU - 1, 1, 1, 0 );
break; // Apply wattage to the element at the right time
} if ( ulWattToWindowTime( wattage ) > (millis() - windowStartTime) ) {
default: { digitalWrite(HEATING_ELEMENT_OUTPUT_PIN, HIGH);
} bStatusElement = true;
} else {
digitalWrite(HEATING_ELEMENT_OUTPUT_PIN, LOW);
bStatusElement = false;
} }
eMaltMenuSelection = eMaltMenu_NULL; #ifdef DEBUG_OFF
//debugPrintFunction("xRegulateTemperature");
debugPrintVar("difference", difference);
//debugPrintVar("overTemperature", overTemperature);
debugPrintVar("wattage", wattage);
//debugPrintVar("ulWattToWindowTime( wattage )", ulWattToWindowTime( wattage ) );
//debugPrintVar("millis()", millis());
//debugPrintVar("windowStartTime", windowStartTime);
//debugPrintVar("test", ulWattToWindowTime( wattage ) > (millis() - windowStartTime) );
#endif
} }
void runStageSelection() { void xPurgePump() {
switch (eStageMenuSelection) { for (int i = 0; i < 2; i++) {
case eStageMenu_Startpoint: { analogWrite(PUMP_PIN, PUMP_SPEED_MAX_MOSFET); // analogWrite values from 0 to 255
startpointTime = getTimer( startpointTime ); delay(1000);
analogWrite(PUMP_PIN, PUMP_SPEED_STOP_MOSFET); // analogWrite values from 0 to 255
delay(1500);
}
}
startpointTemperature = xSetGenericValue( startpointTemperature, TEMPERATURE_MIN_VALUE, TEMPERATURE_MAX_VALUE, "temperature", "*C" ); bool xRegulatePumpSpeed() {
// analogWrite(PUMP_PIN, iPumpSpeed); // analogWrite values from 0 to 255
backToStatus(); if (basePT100.getCurrentTemperature() > PUMP_TEMPERATURE_MAX_OPERATION) {
analogWrite(PUMP_PIN, PUMP_SPEED_STOP_MOSFET); // analogWrite values from 0 to 255
break; basePT100.setPumpStatus( false );
upPT100.setPumpStatus( false );
downPT100.setPumpStatus( false );
} }
case eStageMenu_BetaGlucanase: { else {
betaGlucanaseTime = getTimer( betaGlucanaseTime ); analogWrite(PUMP_PIN, iPumpSpeed); // analogWrite values from 0 to 255
betaGlucanaseTemperature = xSetGenericValue( betaGlucanaseTemperature, TEMPERATURE_MIN_VALUE, TEMPERATURE_MAX_VALUE, "temperature", "*C" );
backToStatus();
break; basePT100.setPumpStatus( true );
upPT100.setPumpStatus( true );
downPT100.setPumpStatus( true );
} }
case eStageMenu_Debranching: { }
debranchingTime = getTimer( debranchingTime );
debranchingTemperature = xSetGenericValue( debranchingTemperature, TEMPERATURE_MIN_VALUE, TEMPERATURE_MAX_VALUE, "temperature", "*C" ); void xWarnClockEnded() {
sing(MELODY_SUPER_MARIO_START, PIEZO_PIN);
}
backToStatus(); void xWarnCookEnded() {
sing(MELODY_UNDERWORLD_SHORT, PIEZO_PIN);
}
break; void xPrepareForStage( int stageTime, int stageTemperature, int stagePumpSpeed, eCookingStages stage ) {
} #ifdef DEBUG_OFF
case eStageMenu_Proteolytic: { debugPrintFunction("xPrepareForStage");
proteolyticTime = getTimer( proteolyticTime ); debugPrintVar("cookingStage", stage);
#endif
// Reset the clock
unsigned long now = millis();
clockStartTime = now;
clockLastUpdate = now;
clockIgnore = 0;
proteolyticTemperature = xSetGenericValue( proteolyticTemperature, TEMPERATURE_MIN_VALUE, TEMPERATURE_MAX_VALUE, "temperature", "*C" ); iPumpSpeed = stagePumpSpeed; // Set the pump speed
cookingStage = stage; // Set Stage
cookTime = stageTime; // Set the clock
cookTemperature = stageTemperature; // Set the target temperature
}
backToStatus(); void xSetupStage(eCookingStages nextStage) {
#ifdef DEBUG_OFF
debugPrintFunction("xSetupStage");
debugPrintVar("cookingStage", nextStage);
#endif
// Operate the machine according to the current mode
switch (nextStage) {
case eCookingStage_Startpoint: {
switch (beerProfile) {
case eBeerProfile_Trigo: {
float wheatAmount = 0.05 * ((float) finalYield);
float pilsnerAmount = 0.2 * ((float) finalYield);
String say = "Cruch ";
say += String(wheatAmount);
say += String("Kg of Wheat and ");
say += String(pilsnerAmount);
say += String("Kg of Pilsner Malt into a pot.");
xWaitForAction("Malt", say);
repaint = true;
break; break;
} }
case eStageMenu_BetaAmylase: { case eBeerProfile_IPA: {
betaAmylaseTime = getTimer( betaAmylaseTime ); float caramelAmount = 0.013157895 * ((float) finalYield);
float wheatAmount = 0.060526316 * ((float) finalYield);
float pilsnerAmount = 0.115789474 * ((float) finalYield);
float munichAmount = 0.028947368 * ((float) finalYield);
String say = "Cruch ";
say += String(caramelAmount);
say += String("Kg of Caramel 120, ");
say += String(wheatAmount);
say += String("Kg of Wheat, ");
say += String(pilsnerAmount);
say += String("Kg of Pilsner, ");
say += String(munichAmount);
say += String("Kg of Munich into a pot.");
xWaitForAction("Malt", say);
repaint = true;
break;
}
default: {
betaAmylaseTemperature = xSetGenericValue( betaAmylaseTemperature, TEMPERATURE_MIN_VALUE, TEMPERATURE_MAX_VALUE, "temperature", "*C" ); }
}
backToStatus(); // Make sure there is water
xWaitForAction("Water", "Make sure there is water in the machine before start cooking.");
repaint = true;
xPrepareForStage( startpointTime, startpointTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_Startpoint );
break; break;
} }
case eStageMenu_AlphaAmylase: { case eCookingStage_BetaGlucanase: {
alphaAmylaseTime = getTimer( alphaAmylaseTime ); switch (beerProfile) {
case eBeerProfile_Trigo: {
alphaAmylaseTemperature = xSetGenericValue( alphaAmylaseTemperature, TEMPERATURE_MIN_VALUE, TEMPERATURE_MAX_VALUE, "temperature", "*C" ); float wheatAmount = 0.05 * ((float) finalYield);
float pilsnerAmount = 0.2 * ((float) finalYield);
String say = "Put ";
say += String(wheatAmount);
say += String("Kg of Wheat and ");
say += String(pilsnerAmount);
say += String("Kg of Pilsner Malt in.");
backToStatus(); xWaitForAction("Malt", say);
repaint = true;
break;
}
case eBeerProfile_IPA: {
float caramelAmount = 0.013157895 * ((float) finalYield);
float wheatAmount = 0.060526316 * ((float) finalYield);
float pilsnerAmount = 0.115789474 * ((float) finalYield);
float munichAmount = 0.028947368 * ((float) finalYield);
String say = "Cruch ";
say += String(caramelAmount);
say += String("Kg of Caramel 120, ");
say += String(wheatAmount);
say += String("Kg of Wheat, ");
say += String(pilsnerAmount);
say += String("Kg of Pilsner, ");
say += String(munichAmount);
say += String("Kg of Munich into a pot.");
xWaitForAction("Malt", say);
repaint = true;
break; break;
} }
case eStageMenu_Mashout: { default: {}
mashoutTime = getTimer( mashoutTime ); }
xPrepareForStage( betaGlucanaseTime, betaGlucanaseTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_BetaGlucanase );
break;
}
case eCookingStage_Debranching: {
xPrepareForStage( debranchingTime, debranchingTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_Debranching );
break;
}
case eCookingStage_Proteolytic: {
xPrepareForStage( proteolyticTime, proteolyticTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_Proteolytic );
break;
}
case eCookingStage_BetaAmylase: {
xPrepareForStage( betaAmylaseTime, betaAmylaseTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_BetaAmylase );
break;
}
case eCookingStage_AlphaAmylase: {
xPrepareForStage( alphaAmylaseTime, alphaAmylaseTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_AlphaAmylase );
break;
}
case eCookingStage_Mashout: {
xPrepareForStage( mashoutTime, mashoutTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_Mashout );
break;
}
case eCookingStage_Recirculation: {
xWaitForAction("Sparge Water", "Start heating your sparge water.");
repaint = true;
xPrepareForStage( recirculationTime, recirculationTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_Recirculation );
break;
}
case eCookingStage_Sparge: {
xWaitForAction("Sparge Water", "Start pouring the sparge water.");
repaint = true;
xPrepareForStage( spargeTime, spargeTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_Sparge );
break;
}
case eCookingStage_Boil: {
switch (beerProfile) {
case eBeerProfile_Trigo: {
String say = "Get ";
float hopAmount = 0.8 * ((float) finalYield);
say += String(hopAmount);
mashoutTemperature = xSetGenericValue( mashoutTemperature, TEMPERATURE_MIN_VALUE, TEMPERATURE_MAX_VALUE, "temperature", "*C" ); say += String("g of Magnum 9.4\% and Styrian Golding 5\% ready.");
backToStatus(); xWaitForAction("Hops", say);
break; break;
} }
case eStageMenu_Recirculation: { case eBeerProfile_IPA: {
recirculationTime = getTimer( recirculationTime ); String say = "Get ";
float hopAmount = 0.8 * ((float) finalYield);
say += String(hopAmount);
recirculationTemperature = xSetGenericValue( recirculationTemperature, TEMPERATURE_MIN_VALUE, TEMPERATURE_MAX_VALUE, "temperature", "*C" ); say += String("g of Chinook, Cascade and Styrian Golding ready.");
backToStatus(); xWaitForAction("Hops", say);
break; break;
} }
case eStageMenu_Sparge: { default: {
spargeTime = getTimer( spargeTime ); xWaitForAction("Hops", "Add the hops in the right order, at the right time.");
spargeTemperature = xSetGenericValue( spargeTemperature, TEMPERATURE_MIN_VALUE, TEMPERATURE_MAX_VALUE, "temperature", "*C" ); }
}
backToStatus(); repaint = true;
// A basic operation for a basic stage
xPrepareForStage( boilTime, boilTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_Boil );
break; break;
} }
case eStageMenu_Boil: { case eCookingStage_Cooling: {
boilTime = getTimer( boilTime ); // Make sure there is water
xWaitForAction("Coil", "Add the coil and connect it to the main water supply.");
boilTemperature = xSetGenericValue( boilTemperature, TEMPERATURE_MIN_VALUE, TEMPERATURE_MAX_VALUE, "temperature", "*C" ); repaint = true;
backToStatus(); // A basic operation for a basic stage
xPrepareForStage( coolingTime, coolingTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_Cooling );
break; break;
} }
case eStageMenu_Cooling: { case eCookingStage_Clean: {
coolingTime = getTimer( coolingTime ); // Make sure there is water
xWaitForAction("Water", "Add 13 liters.");
// Make sure there is water
xWaitForAction("Star San HB", "Add 0.89oz/26ml.");
coolingTemperature = xSetGenericValue( coolingTemperature, TEMPERATURE_MIN_VALUE, TEMPERATURE_MAX_VALUE, "temperature", "*C" ); repaint = true;
backToStatus(); // A basic operation for a basic stage
xPrepareForStage( cleaningTime, cleaningTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_Clean );
break; break;
} }
case eStageMenu_Back: { case eCookingStage_Purge: {
eMenuType = eMenuType_Main; // A basic operation for a basic stage
repaint = true; xPrepareForStage( 0, 0, PUMP_SPEED_MAX_MOSFET, eCookingStage_Purge );
// reset operation state | INPUT : eRotaryEncoderMode newMode, int newPosition, int newMaxPosition, int newMinPosition, int newSingleStep, int newMultiStep xRegulatePumpSpeed();
//xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eMainMenuPosition, MENU_SIZE_MAIN_MENU - 1, 1, 1, 0 );
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, mdMainMenu._position, MENU_SIZE_MAIN_MENU - 1, 1, 1, 0 );
break; break;
} }
default: { case eCookingStage_Done: {
// A basic operation for a basic stage
xPrepareForStage( 0, 0, PUMP_SPEED_STOP_MOSFET, eCookingStage_Done );
break;
} }
} }
eStageMenuSelection = eStageMenu_NULL;
} }
void runBeerProfileSelection() { void xTransitionIntoStage(eCookingStages nextStage) {
switch (eBeerProfileMenuSelection) { // Turn off all hardware that can damage itself if the machine is not cooking
case eBeerProfileMenu_Basic: { xSafeHardwarePowerOff();
beerProfile = eBeerProfile_Basic;
startpointTime = PROFILE_BASIC_STARTPOINT_TIME; // Warn the user a stage has ended
betaGlucanaseTime = PROFILE_BASIC_BETAGLUCANASE_TIME; xWarnClockEnded();
debranchingTime = PROFILE_BASIC_DEBRANCHING_TIME;
proteolyticTime = PROFILE_BASIC_PROTEOLYTIC_TIME;
betaAmylaseTime = PROFILE_BASIC_BETAAMYLASE_TIME;
alphaAmylaseTime = PROFILE_BASIC_ALPHAAMYLASE_TIME;
mashoutTime = PROFILE_BASIC_MASHOUT_TIME;
recirculationTime = PROFILE_BASIC_RECIRCULATION_TIME;
spargeTime = PROFILE_BASIC_SPARGE_TIME;
boilTime = PROFILE_BASIC_BOIL_TIME;
coolingTime = PROFILE_BASIC_COOLING_TIME;
startpointTemperature = PROFILE_BASIC_STARTPOINT_TEMPERATURE; // Reset global stage variables
betaGlucanaseTemperature = PROFILE_BASIC_BETAGLUCANASE_TEMPERATURE; xSetupStage( nextStage );
debranchingTemperature = PROFILE_BASIC_DEBRANCHING_TEMPERATURE; }
proteolyticTemperature = PROFILE_BASIC_PROTEOLYTIC_TEMPERATURE;
betaAmylaseTemperature = PROFILE_BASIC_BETAAMYLASE_TEMPERATURE;
alphaAmylaseTemperature = PROFILE_BASIC_ALPHAAMYLASE_TEMPERATURE;
mashoutTemperature = PROFILE_BASIC_MASHOUT_TEMPERATURE;
recirculationTemperature = PROFILE_BASIC_RECIRCULATION_TEMPERATURE;
spargeTemperature = PROFILE_BASIC_SPARGE_TEMPERATURE;
boilTemperature = PROFILE_BASIC_BOIL_TEMPERATURE;
coolingTemperature = PROFILE_BASIC_COOLING_TEMPERATURE;
backToStatus(); void xBasicStageOperation( int iStageTime, int iStageTemperature, int iStageTemperatureRange, eCookingStages nextStage, boolean bMaximumOfUpDown ) {
break; // Account for time spent at the target temperature | Input 1: range in ºC within which the target temperature is considered to be reached
} #ifdef DEBUG_OFF
case eBeerProfileMenu_Trigo: { xCountTheTime( iStageTemperatureRange, false );
beerProfile = eBeerProfile_Trigo; #else
xCountTheTime( iStageTemperatureRange, bMaximumOfUpDown );
#endif
startpointTime = PROFILE_TRIGO_STARTPOINT_TIME; if ( isTimeLeft() ) {
betaGlucanaseTime = PROFILE_TRIGO_BETAGLUCANASE_TIME; // Do temperature control
debranchingTime = PROFILE_TRIGO_DEBRANCHING_TIME; xRegulateTemperature( bMaximumOfUpDown );
proteolyticTime = PROFILE_TRIGO_PROTEOLYTIC_TIME;
betaAmylaseTime = PROFILE_TRIGO_BETAAMYLASE_TIME;
alphaAmylaseTime = PROFILE_TRIGO_ALPHAAMYLASE_TIME;
mashoutTime = PROFILE_TRIGO_MASHOUT_TIME;
recirculationTime = PROFILE_TRIGO_RECIRCULATION_TIME;
spargeTime = PROFILE_TRIGO_SPARGE_TIME;
boilTime = PROFILE_TRIGO_BOIL_TIME;
coolingTime = PROFILE_TRIGO_COOLING_TIME;
startpointTemperature = PROFILE_TRIGO_STARTPOINT_TEMPERATURE;
betaGlucanaseTemperature = PROFILE_TRIGO_BETAGLUCANASE_TEMPERATURE;
debranchingTemperature = PROFILE_TRIGO_DEBRANCHING_TEMPERATURE;
proteolyticTemperature = PROFILE_TRIGO_PROTEOLYTIC_TEMPERATURE;
betaAmylaseTemperature = PROFILE_TRIGO_BETAAMYLASE_TEMPERATURE;
alphaAmylaseTemperature = PROFILE_TRIGO_ALPHAAMYLASE_TEMPERATURE;
mashoutTemperature = PROFILE_TRIGO_MASHOUT_TEMPERATURE;
recirculationTemperature = PROFILE_TRIGO_RECIRCULATION_TEMPERATURE;
spargeTemperature = PROFILE_TRIGO_SPARGE_TEMPERATURE;
boilTemperature = PROFILE_TRIGO_BOIL_TEMPERATURE;
coolingTemperature = PROFILE_TRIGO_COOLING_TEMPERATURE;
backToStatus();
break;
}
case eBeerProfileMenu_IPA: {
beerProfile = eBeerProfile_IPA;
startpointTime = PROFILE_IPA_STARTPOINT_TIME;
betaGlucanaseTime = PROFILE_IPA_BETAGLUCANASE_TIME;
debranchingTime = PROFILE_IPA_DEBRANCHING_TIME;
proteolyticTime = PROFILE_IPA_PROTEOLYTIC_TIME;
betaAmylaseTime = PROFILE_IPA_BETAAMYLASE_TIME;
alphaAmylaseTime = PROFILE_IPA_ALPHAAMYLASE_TIME;
mashoutTime = PROFILE_IPA_MASHOUT_TIME;
recirculationTime = PROFILE_IPA_RECIRCULATION_TIME;
spargeTime = PROFILE_IPA_SPARGE_TIME;
boilTime = PROFILE_IPA_BOIL_TIME;
coolingTime = PROFILE_IPA_COOLING_TIME;
startpointTemperature = PROFILE_IPA_STARTPOINT_TEMPERATURE;
betaGlucanaseTemperature = PROFILE_IPA_BETAGLUCANASE_TEMPERATURE;
debranchingTemperature = PROFILE_IPA_DEBRANCHING_TEMPERATURE;
proteolyticTemperature = PROFILE_IPA_PROTEOLYTIC_TEMPERATURE;
betaAmylaseTemperature = PROFILE_IPA_BETAAMYLASE_TEMPERATURE;
alphaAmylaseTemperature = PROFILE_IPA_ALPHAAMYLASE_TEMPERATURE;
mashoutTemperature = PROFILE_IPA_MASHOUT_TEMPERATURE;
recirculationTemperature = PROFILE_IPA_RECIRCULATION_TEMPERATURE;
spargeTemperature = PROFILE_IPA_SPARGE_TEMPERATURE;
boilTemperature = PROFILE_IPA_BOIL_TEMPERATURE;
coolingTemperature = PROFILE_IPA_COOLING_TEMPERATURE;
backToStatus();
break;
}
case eBeerProfileMenu_Belga: {
beerProfile = eBeerProfile_Belga;
startpointTime = PROFILE_BELGA_STARTPOINT_TIME;
betaGlucanaseTime = PROFILE_BELGA_BETAGLUCANASE_TIME;
debranchingTime = PROFILE_BELGA_DEBRANCHING_TIME;
proteolyticTime = PROFILE_BELGA_PROTEOLYTIC_TIME;
betaAmylaseTime = PROFILE_BELGA_BETAAMYLASE_TIME;
alphaAmylaseTime = PROFILE_BELGA_ALPHAAMYLASE_TIME;
mashoutTime = PROFILE_BELGA_MASHOUT_TIME;
recirculationTime = PROFILE_BELGA_RECIRCULATION_TIME;
spargeTime = PROFILE_BELGA_SPARGE_TIME;
boilTime = PROFILE_BELGA_BOIL_TIME;
coolingTime = PROFILE_BELGA_COOLING_TIME;
startpointTemperature = PROFILE_BELGA_STARTPOINT_TEMPERATURE;
betaGlucanaseTemperature = PROFILE_BELGA_BETAGLUCANASE_TEMPERATURE;
debranchingTemperature = PROFILE_BELGA_DEBRANCHING_TEMPERATURE;
proteolyticTemperature = PROFILE_BELGA_PROTEOLYTIC_TEMPERATURE;
betaAmylaseTemperature = PROFILE_BELGA_BETAAMYLASE_TEMPERATURE;
alphaAmylaseTemperature = PROFILE_BELGA_ALPHAAMYLASE_TEMPERATURE;
mashoutTemperature = PROFILE_BELGA_MASHOUT_TEMPERATURE;
recirculationTemperature = PROFILE_BELGA_RECIRCULATION_TEMPERATURE;
spargeTemperature = PROFILE_BELGA_SPARGE_TEMPERATURE;
boilTemperature = PROFILE_BELGA_BOIL_TEMPERATURE;
coolingTemperature = PROFILE_BELGA_COOLING_TEMPERATURE;
backToStatus();
break;
}
case eBeerProfileMenu_Red: {
beerProfile = eBeerProfile_Red;
startpointTime = PROFILE_RED_STARTPOINT_TIME;
betaGlucanaseTime = PROFILE_RED_BETAGLUCANASE_TIME;
debranchingTime = PROFILE_RED_DEBRANCHING_TIME;
proteolyticTime = PROFILE_RED_PROTEOLYTIC_TIME;
betaAmylaseTime = PROFILE_RED_BETAAMYLASE_TIME;
alphaAmylaseTime = PROFILE_RED_ALPHAAMYLASE_TIME;
mashoutTime = PROFILE_RED_MASHOUT_TIME;
recirculationTime = PROFILE_RED_RECIRCULATION_TIME;
spargeTime = PROFILE_RED_SPARGE_TIME;
boilTime = PROFILE_RED_BOIL_TIME;
coolingTime = PROFILE_RED_COOLING_TIME;
startpointTemperature = PROFILE_RED_STARTPOINT_TEMPERATURE;
betaGlucanaseTemperature = PROFILE_RED_BETAGLUCANASE_TEMPERATURE;
debranchingTemperature = PROFILE_RED_DEBRANCHING_TEMPERATURE;
proteolyticTemperature = PROFILE_RED_PROTEOLYTIC_TEMPERATURE;
betaAmylaseTemperature = PROFILE_RED_BETAAMYLASE_TEMPERATURE;
alphaAmylaseTemperature = PROFILE_RED_ALPHAAMYLASE_TEMPERATURE;
mashoutTemperature = PROFILE_RED_MASHOUT_TEMPERATURE;
recirculationTemperature = PROFILE_RED_RECIRCULATION_TEMPERATURE;
spargeTemperature = PROFILE_RED_SPARGE_TEMPERATURE;
boilTemperature = PROFILE_RED_BOIL_TEMPERATURE;
coolingTemperature = PROFILE_RED_COOLING_TEMPERATURE;
backToStatus();
break;
}
case eBeerProfileMenu_APA: {
beerProfile = eBeerProfile_APA;
startpointTime = PROFILE_APA_STARTPOINT_TIME;
betaGlucanaseTime = PROFILE_APA_BETAGLUCANASE_TIME;
debranchingTime = PROFILE_APA_DEBRANCHING_TIME;
proteolyticTime = PROFILE_APA_PROTEOLYTIC_TIME;
betaAmylaseTime = PROFILE_APA_BETAAMYLASE_TIME;
alphaAmylaseTime = PROFILE_APA_ALPHAAMYLASE_TIME;
mashoutTime = PROFILE_APA_MASHOUT_TIME;
recirculationTime = PROFILE_APA_RECIRCULATION_TIME;
spargeTime = PROFILE_APA_SPARGE_TIME;
boilTime = PROFILE_APA_BOIL_TIME;
coolingTime = PROFILE_APA_COOLING_TIME;
startpointTemperature = PROFILE_APA_STARTPOINT_TEMPERATURE;
betaGlucanaseTemperature = PROFILE_APA_BETAGLUCANASE_TEMPERATURE;
debranchingTemperature = PROFILE_APA_DEBRANCHING_TEMPERATURE;
proteolyticTemperature = PROFILE_APA_PROTEOLYTIC_TEMPERATURE;
betaAmylaseTemperature = PROFILE_APA_BETAAMYLASE_TEMPERATURE;
alphaAmylaseTemperature = PROFILE_APA_ALPHAAMYLASE_TEMPERATURE;
mashoutTemperature = PROFILE_APA_MASHOUT_TEMPERATURE;
recirculationTemperature = PROFILE_APA_RECIRCULATION_TEMPERATURE;
spargeTemperature = PROFILE_APA_SPARGE_TEMPERATURE;
boilTemperature = PROFILE_APA_BOIL_TEMPERATURE;
coolingTemperature = PROFILE_APA_COOLING_TEMPERATURE;
backToStatus();
break;
}
case eBeerProfileMenu_Custom: {
beerProfile = eBeerProfile_Custom;
startpointTime = PROFILE_CUSTOM_STARTPOINT_TIME;
betaGlucanaseTime = PROFILE_CUSTOM_BETAGLUCANASE_TIME;
debranchingTime = PROFILE_CUSTOM_DEBRANCHING_TIME;
proteolyticTime = PROFILE_CUSTOM_PROTEOLYTIC_TIME;
betaAmylaseTime = PROFILE_CUSTOM_BETAAMYLASE_TIME;
alphaAmylaseTime = PROFILE_CUSTOM_ALPHAAMYLASE_TIME;
mashoutTime = PROFILE_CUSTOM_MASHOUT_TIME;
recirculationTime = PROFILE_CUSTOM_RECIRCULATION_TIME;
spargeTime = PROFILE_CUSTOM_SPARGE_TIME;
boilTime = PROFILE_CUSTOM_BOIL_TIME;
coolingTime = PROFILE_CUSTOM_COOLING_TIME;
startpointTemperature = PROFILE_CUSTOM_STARTPOINT_TEMPERATURE;
betaGlucanaseTemperature = PROFILE_CUSTOM_BETAGLUCANASE_TEMPERATURE;
debranchingTemperature = PROFILE_CUSTOM_DEBRANCHING_TEMPERATURE;
proteolyticTemperature = PROFILE_CUSTOM_PROTEOLYTIC_TEMPERATURE;
betaAmylaseTemperature = PROFILE_CUSTOM_BETAAMYLASE_TEMPERATURE;
alphaAmylaseTemperature = PROFILE_CUSTOM_ALPHAAMYLASE_TEMPERATURE;
mashoutTemperature = PROFILE_CUSTOM_MASHOUT_TEMPERATURE;
recirculationTemperature = PROFILE_CUSTOM_RECIRCULATION_TEMPERATURE;
spargeTemperature = PROFILE_CUSTOM_SPARGE_TEMPERATURE;
boilTemperature = PROFILE_CUSTOM_BOIL_TEMPERATURE;
coolingTemperature = PROFILE_CUSTOM_COOLING_TEMPERATURE;
backToStatus();
break; // Do flow control
} xRegulatePumpSpeed();
case eBeerProfileMenu_Back: {
eMenuType = eMenuType_Main;
repaint = true;
// reset operation state | INPUT : eRotaryEncoderMode newMode, int newPosition, int newMaxPosition, int newMinPosition, int newSingleStep, int newMultiStep } else {
//xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eMainMenuPosition, MENU_SIZE_MAIN_MENU - 1, 1, 1, 0 ); #ifdef DEBUG_OFF
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, mdMainMenu._position, MENU_SIZE_MAIN_MENU - 1, 1, 1, 0 ); debugPrintFunction("xBasicStageOperation");
debugPrintVar("clockCounter", clockCounter);
#endif
break; // Continue to the next stage, there is nothing to do, in this stage
} xTransitionIntoStage( nextStage );
default: { return;
}
} }
eBeerProfileMenuSelection = eBeerProfileMenu_NULL; return;
} }
void xStartStage( unsigned long *stageTime, int *stageTemperature, eCookingStages nextStage, bool bPurgePump, bool bSetFinalYield, bool bSetTime, bool bSetTemperature ) { void xManageMachineSystems() {
xSafeHardwarePowerOff(); // Stop anything that might be still going on
if (bSetFinalYield) { #ifdef DEBUG
finalYield = xSetFinalYield( finalYield ); Serial.print(millis());
Serial.print(",");
if (cooking) {
Serial.print("1");
} }
if (bSetTime) { else {
(*stageTime) = getTimer( clockCounter / 1000, (*stageTime) ); Serial.print("0");
} }
if (bSetTemperature) { Serial.print(",");
(*stageTemperature) = xSetTemperature( (*stageTemperature) ); Serial.print(cookTemperature);
Serial.print(",");
if (bStatusElement) {
Serial.print("1");
} }
if (bPurgePump) { else {
xPurgePump(); Serial.print("0");
} }
Serial.print(",");
#endif
startBrewing(); // Measure temperature, for effect
xSetupStage( nextStage ); basePT100.measure(false);
backToStatus(); upPT100.measure(false);
} downPT100.measure(true);
void xStartStageHeadless( eCookingStages nextStage, bool bPurgePump ) {
xStartStage( NULL, NULL, nextStage, bPurgePump, false, false, false );
}
void xStartStageInteractive( unsigned long *stageTime, int *stageTemperature, eCookingStages nextStage ) { // If cooking is done, return (this is a nice place to double check safety and ensure the cooking parts aren't on.
xStartStage( stageTime, stageTemperature, nextStage, true, true, true, true ); if (!cooking) {
} xSafeHardwarePowerOff();
void runStartFromStageSelection() { return;
switch (eStartFromStageMenuSelection) {
case eStageMenu_Startpoint: {
xStartStageInteractive( &startpointTime, &startpointTemperature, eCookingStage_Startpoint );
break;
}
case eStageMenu_BetaGlucanase: {
xStartStageInteractive( &betaGlucanaseTime, &betaGlucanaseTemperature, eCookingStage_BetaGlucanase );
break;
}
case eStageMenu_Debranching: {
xStartStageInteractive( &debranchingTime, &debranchingTemperature, eCookingStage_Debranching );
break;
}
case eStageMenu_Proteolytic: {
xStartStageInteractive( &proteolyticTime, &proteolyticTemperature, eCookingStage_Proteolytic );
break;
}
case eStageMenu_BetaAmylase: {
xStartStageInteractive( &betaAmylaseTime, &betaAmylaseTemperature, eCookingStage_BetaAmylase );
break;
}
case eStageMenu_AlphaAmylase: {
xStartStageInteractive( &alphaAmylaseTime, &alphaAmylaseTemperature, eCookingStage_AlphaAmylase );
break;
}
case eStageMenu_Mashout: {
xStartStageInteractive( &mashoutTime, &mashoutTemperature, eCookingStage_Mashout );
break;
}
case eStageMenu_Recirculation: {
xStartStageInteractive( &recirculationTime, &recirculationTemperature, eCookingStage_Recirculation );
break;
}
case eStageMenu_Sparge: {
xStartStageInteractive( &spargeTime, &spargeTemperature, eCookingStage_Sparge );
break;
}
case eStageMenu_Boil: {
xStartStageInteractive( &boilTime, &boilTemperature, eCookingStage_Boil );
break;
}
case eStageMenu_Cooling: {
xStartStageInteractive( &coolingTime, &coolingTemperature, eCookingStage_Cooling );
break;
}
case eStageMenu_Back: {
resetMenu( true );
break;
}
default: {
}
} }
eStartFromStageMenuSelection = eStageMenu_NULL;
}
void runMainMenuSelection() { // Operate the machine according to the current mode
switch (mdMainMenu._selection) { switch (cookingStage) {
//switch (eMainMenuSelection) { case eCookingStage_Startpoint: {
case eMainMenu_GO: { xBasicStageOperation( startpointTime, startpointTemperature, 0, eCookingStage_BetaGlucanase, false);
xStartStage( NULL, NULL, eCookingStage_Startpoint, true, true, false, false );
break;
}
case eMainMenu_GO_FROM_STAGE: {
eMenuType = eMenuType_StartFromStage;
repaint = true;
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eBeerProfileMenuPosition, MENU_SIZE_PROFILES_MENU - 1, 1, 1, 0 );
break;
}
case eMainMenu_STOP: {
stopBrewing();
backToStatus();
break;
}
case eMainMenu_SKIP: {
cookTime = 0;
backToStatus();
break;
}
case eMainMenu_BeerProfile: {
eMenuType = eMenuType_BeerProfile;
repaint = true;
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eBeerProfileMenuPosition, MENU_SIZE_PROFILES_MENU - 1, 1, 1, 0 );
break;
}
case eMainMenu_Stage: {
eMenuType = eMenuType_Stage;
repaint = true;
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eStageMenuPosition, MENU_SIZE_STAGE_MENU - 1, 1, 1, 0 );
break;
}
case eMainMenu_Malt: {
eMenuType = eMenuType_Malt;
repaint = true;
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eMaltMenuPosition, MENU_SIZE_MALT_MENU - 1, 1, 1, 0 );
break; break;
} }
case eMainMenu_Hops: { case eCookingStage_BetaGlucanase: {
backToStatus(); xBasicStageOperation( betaGlucanaseTime, betaGlucanaseTemperature, 3, eCookingStage_Debranching, true );
break; break;
} }
case eMainMenu_Clean: { case eCookingStage_Debranching: {
xStartStageHeadless( eCookingStage_Clean, true ); xBasicStageOperation( debranchingTime, debranchingTemperature, 3, eCookingStage_Proteolytic, true );
break; break;
} }
case eMainMenu_Purge: { case eCookingStage_Proteolytic: {
xStartStageHeadless( eCookingStage_Purge, true ); xBasicStageOperation( proteolyticTime, proteolyticTemperature, 3, eCookingStage_BetaAmylase, true );
break; break;
} }
case eMainMenu_Settings: { case eCookingStage_BetaAmylase: {
eMenuType = eMenuType_Settings; xBasicStageOperation( betaAmylaseTime, betaAmylaseTemperature, 4, eCookingStage_AlphaAmylase, true );
repaint = true;
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eSettingsMenuPosition, MENU_SIZE_SETTINGS_MENU - 1, 1, 1, 0 );
break; break;
} }
case eMainMenu_Back: { case eCookingStage_AlphaAmylase: {
backToStatus(); xBasicStageOperation( alphaAmylaseTime, alphaAmylaseTemperature, 2, eCookingStage_Mashout, true );
break; break;
} }
default: { case eCookingStage_Mashout: {
} xBasicStageOperation( mashoutTime, mashoutTemperature, 1, eCookingStage_Recirculation, true );
} break;
mdMainMenu._selection = eMainMenu_NULL;
//eMainMenuSelection = eMainMenu_NULL;
}
void xCountTheTime( int temperatureMarginRange, boolean bMaximumOfUpDown ) {
unsigned long now = millis();
// Get current maximum sensed temperaure
double temperatureCount = 0;
if ( bMaximumOfUpDown ) {
float tup = upPT100.getCurrentTemperature();
float tdown = downPT100.getCurrentTemperature();
if (tup > tdown) {
temperatureCount = tdown;
}
else {
temperatureCount = tup;
}
} else {
temperatureCount = basePT100.getCurrentTemperature();
}
// Ignote time ticks if temperature is not within the acceptable margin for this stage
unsigned long elapsedTime = now - clockLastUpdate;
if ( temperatureCount < (cookTemperature - temperatureMarginRange) ) {
clockIgnore += elapsedTime;
}
// Calculate the remaining time on the clock
clockCounter = cookTime * 1000 - (elapsedTime - clockIgnore);
// Don't let clock get bellow 0
if ( clockCounter < 0 ) {
clockCounter = 0;
}
clockLastUpdate = now;
#ifdef DEBUG_OFF
debugPrintFunction("xCountTheTime");
debugPrintVar("millis()", now);
debugPrintVar("cookTime", cookTime);
debugPrintVar("clockStartTime", clockStartTime);
debugPrintVar("clockIgnore", clockIgnore);
debugPrintVar("clockCounter", clockCounter);
#endif
}
bool isTimeLeft() {
if ( clockCounter > 0 ) {
return true;
}
return false;
}
//HEATING_ELEMENT_MAX_WATTAGE / HEATING_ELEMENT_AC_FREQUENCY_HZ
double ulWattToWindowTime( double ulAppliedWatts ) {
double ulPulsesRequired = ulAppliedWatts / dWattPerPulse;
return (double)iWindowSize / 1000.0 * ulPulsesRequired * 1000.0 / HEATING_ELEMENT_AC_FREQUENCY_HZ;
}
bool xRegulateTemperature( boolean bMaximumOfUpDown ) {
double difference = 0;
bool overTemperature = false;
double wattage = 0.0;
float tup = upPT100.getCurrentTemperature();
float tdown = downPT100.getCurrentTemperature();
float tbase = basePT100.getCurrentTemperature();
if ( bMaximumOfUpDown ) {
if (tup > tdown) {
difference = cookTemperature - tup;
}
else {
difference = cookTemperature - tdown;
}
if (tbase > cookTemperature && (tbase >= (PUMP_TEMPERATURE_MAX_OPERATION - 2.0) || difference >= 5.0)) {
difference = cookTemperature - tbase;
}
if ( (tbase < cookTemperature) && (difference < (cookTemperature - tbase)) ) {
difference = cookTemperature - tbase;
}
} else {
difference = cookTemperature - tbase;
}
// Deviation between the cook temperature set and the cook temperature measured
if ( difference < 0.0 ) {
difference = difference * (-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(difference <= 0.1) {
// turn it off
// wattage = 0.0;
//} else {
if (difference <= 0.5) {
// pulse lightly at 500 watt
if (cookTemperature > 99.0) {
wattage = 2000.0;
}
else {
if (cookTemperature > 70.0) {
wattage = 1000.0;
}
else {
wattage = 500.0;
} }
case eCookingStage_Recirculation: {
xBasicStageOperation( recirculationTime, recirculationTemperature, 1, eCookingStage_Sparge, true );
break;
} }
} else { case eCookingStage_Sparge: {
if (difference <= 1.0) { xBasicStageOperation( spargeTime, spargeTemperature, 3, eCookingStage_Boil, false );
// pulse moderately at 1000 watt break;
if (cookTemperature > 99.0) {
wattage = 2000.0;
} }
else { case eCookingStage_Boil: {
wattage = 1000.0; xBasicStageOperation( boilTime, boilTemperature, 2, eCookingStage_Cooling, false );
break;
} }
case eCookingStage_Cooling: {
} else { xBasicStageOperation( coolingTime, coolingTemperature, 0, eCookingStage_Done, false );
if (difference <= 3.0) { break;
// pulse hardly at 2000 watt
wattage = 2000.0;
} else {
//pulse constantly at HEATING_ELEMENT_MAX_WATTAGE watt
wattage = HEATING_ELEMENT_MAX_WATTAGE;
} }
case eCookingStage_Clean: {
xBasicStageOperation( cleaningTime, cleaningTemperature, 0, eCookingStage_Done, false );
break;
} }
case eCookingStage_Purge: {
iPumpSpeed = PUMP_SPEED_MAX_MOSFET;
xRegulatePumpSpeed();
break;
} }
//} case eCookingStage_Done: {
stopBrewing(); // Update cooking state
repaint = true; // Ask for screen refresh
xWarnCookEnded(); // Warn the user that the cooking is done
break;
} }
// Update the recorded time for the begining of the window, if the previous window has passed
while ((millis() - windowStartTime) > iWindowSize) { // Check if it's time to vary the pulse width modulation and if so do it by shifting the "Relay in ON" Window
windowStartTime += iWindowSize;
} }
}
// Apply wattage to the element at the right time // ##################################################### Menus ###################################################################
if ( ulWattToWindowTime( wattage ) > (millis() - windowStartTime) ) {
digitalWrite(HEATING_ELEMENT_OUTPUT_PIN, HIGH);
bStatusElement = true;
} else {
digitalWrite(HEATING_ELEMENT_OUTPUT_PIN, LOW);
bStatusElement = false;
}
// *************************** MENU BASE *********************************
void runMenu() {
#ifdef DEBUG_OFF #ifdef DEBUG_OFF
//debugPrintFunction("xRegulateTemperature"); boolean debug_go = repaint;
debugPrintVar("difference", difference); if (debug_go) {
//debugPrintVar("overTemperature", overTemperature); debugPrintFunction("runMenu");
debugPrintVar("wattage", wattage); debugPrintVar("repaint", repaint);
//debugPrintVar("ulWattToWindowTime( wattage )", ulWattToWindowTime( wattage ) ); debugPrintVar("eMenuType", eMenuType);
//debugPrintVar("millis()", millis()); debugPrintVar("rotaryEncoderVirtualPosition", rotaryEncoderVirtualPosition);
//debugPrintVar("windowStartTime", windowStartTime); }
//debugPrintVar("test", ulWattToWindowTime( wattage ) > (millis() - windowStartTime) );
#endif #endif
}
void xPurgePump() { switch (eMenuType) {
for (int i = 0; i < 2; i++) { case eMenuType_Main: {
analogWrite(PUMP_PIN, PUMP_SPEED_MAX_MOSFET); // analogWrite values from 0 to 255 runMenuProcessor( &mdMainMenu );
delay(1000); break;
analogWrite(PUMP_PIN, PUMP_SPEED_STOP_MOSFET); // analogWrite values from 0 to 255
delay(1500);
} }
} case eMenuType_BeerProfile: {
runMenuProcessor( &mdBeerProfileMenu );
bool xRegulatePumpSpeed() { break;
// analogWrite(PUMP_PIN, iPumpSpeed); // analogWrite values from 0 to 255 }
case eMenuType_Stage: {
if (basePT100.getCurrentTemperature() > PUMP_TEMPERATURE_MAX_OPERATION) { runMenuProcessor( &mdStageMenu );
analogWrite(PUMP_PIN, PUMP_SPEED_STOP_MOSFET); // analogWrite values from 0 to 255 break;
}
basePT100.setPumpStatus( false ); case eMenuType_Malt: {
upPT100.setPumpStatus( false ); runMenuProcessor( &mdMaltMenu );
downPT100.setPumpStatus( false ); break;
}
case eMenuType_Settings: {
runMenuProcessor( &mdSettingsMenu );
break;
}
case eMenuType_StartFromStage: {
runMenuProcessor( &mdStartFromStageMenu );
break;
} }
else {
analogWrite(PUMP_PIN, iPumpSpeed); // analogWrite values from 0 to 255
basePT100.setPumpStatus( true );
upPT100.setPumpStatus( true );
downPT100.setPumpStatus( true );
} }
}
void xWarnClockEnded() {
sing(MELODY_SUPER_MARIO_START, PIEZO_PIN);
}
void xWarnCookEnded() {
sing(MELODY_UNDERWORLD_SHORT, PIEZO_PIN);
}
void xPrepareForStage( int stageTime, int stageTemperature, int stagePumpSpeed, eCookingStages stage ) {
#ifdef DEBUG_OFF #ifdef DEBUG_OFF
debugPrintFunction("xPrepareForStage"); if (debug_go) {
debugPrintVar("cookingStage", stage); debugPrintVar("repaint", repaint);
}
#endif #endif
// Reset the clock
unsigned long now = millis();
clockStartTime = now;
clockLastUpdate = now;
clockIgnore = 0;
iPumpSpeed = stagePumpSpeed; // Set the pump speed
cookingStage = stage; // Set Stage
cookTime = stageTime; // Set the clock
cookTemperature = stageTemperature; // Set the target temperature
} }
void xSetupStage(eCookingStages nextStage) { // ************************ MENU SELECTIONS ******************************
#ifdef DEBUG_OFF void runMainMenuSelection() {
debugPrintFunction("xSetupStage"); switch (mdMainMenu._selection) {
debugPrintVar("cookingStage", nextStage); //switch (eMainMenuSelection) {
#endif case eMainMenu_GO: {
xStartStage( NULL, NULL, eCookingStage_Startpoint, true, true, false, false );
// Operate the machine according to the current mode
switch (nextStage) {
case eCookingStage_Startpoint: {
switch (beerProfile) {
case eBeerProfile_Trigo: {
float wheatAmount = 0.05 * ((float) finalYield);
float pilsnerAmount = 0.2 * ((float) finalYield);
String say = "Cruch ";
say += String(wheatAmount);
say += String("Kg of Wheat and ");
say += String(pilsnerAmount);
say += String("Kg of Pilsner Malt into a pot.");
xWaitForAction("Malt", say);
repaint = true;
break; break;
} }
case eBeerProfile_IPA: { case eMainMenu_GO_FROM_STAGE: {
float caramelAmount = 0.013157895 * ((float) finalYield); eMenuType = eMenuType_StartFromStage;
float wheatAmount = 0.060526316 * ((float) finalYield);
float pilsnerAmount = 0.115789474 * ((float) finalYield);
float munichAmount = 0.028947368 * ((float) finalYield);
String say = "Cruch ";
say += String(caramelAmount);
say += String("Kg of Caramel 120, ");
say += String(wheatAmount);
say += String("Kg of Wheat, ");
say += String(pilsnerAmount);
say += String("Kg of Pilsner, ");
say += String(munichAmount);
say += String("Kg of Munich into a pot.");
xWaitForAction("Malt", say);
repaint = true; repaint = true;
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, mdBeerProfileMenu._position, MENU_SIZE_PROFILES_MENU - 1, 1, 1, 0 );
break; break;
} }
default: { case eMainMenu_STOP: {
stopBrewing();
backToStatus();
break;
} }
case eMainMenu_SKIP: {
cookTime = 0;
backToStatus();
break;
} }
case eMainMenu_BeerProfile: {
// Make sure there is water eMenuType = eMenuType_BeerProfile;
xWaitForAction("Water", "Make sure there is water in the machine before start cooking.");
repaint = true; repaint = true;
xPrepareForStage( startpointTime, startpointTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_Startpoint ); xSetupRotaryEncoder( eRotaryEncoderMode_Menu, mdBeerProfileMenu._position, MENU_SIZE_PROFILES_MENU - 1, 1, 1, 0 );
break; break;
} }
case eCookingStage_BetaGlucanase: { case eMainMenu_Stage: {
switch (beerProfile) { eMenuType = eMenuType_Stage;
case eBeerProfile_Trigo: {
float wheatAmount = 0.05 * ((float) finalYield);
float pilsnerAmount = 0.2 * ((float) finalYield);
String say = "Put ";
say += String(wheatAmount);
say += String("Kg of Wheat and ");
say += String(pilsnerAmount);
say += String("Kg of Pilsner Malt in.");
xWaitForAction("Malt", say);
repaint = true; repaint = true;
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, mdStageMenu._position, MENU_SIZE_STAGE_MENU - 1, 1, 1, 0 );
break; break;
} }
case eBeerProfile_IPA: { case eMainMenu_Malt: {
float caramelAmount = 0.013157895 * ((float) finalYield); eMenuType = eMenuType_Malt;
float wheatAmount = 0.060526316 * ((float) finalYield); repaint = true;
float pilsnerAmount = 0.115789474 * ((float) finalYield); xSetupRotaryEncoder( eRotaryEncoderMode_Menu, mdMaltMenu._position, MENU_SIZE_MALT_MENU - 1, 1, 1, 0 );
float munichAmount = 0.028947368 * ((float) finalYield); break;
String say = "Cruch "; }
say += String(caramelAmount); case eMainMenu_Hops: {
say += String("Kg of Caramel 120, "); backToStatus();
say += String(wheatAmount); break;
say += String("Kg of Wheat, "); }
say += String(pilsnerAmount); case eMainMenu_Clean: {
say += String("Kg of Pilsner, "); xStartStageHeadless( eCookingStage_Clean, true );
say += String(munichAmount); break;
say += String("Kg of Munich into a pot."); }
case eMainMenu_Purge: {
xWaitForAction("Malt", say); xStartStageHeadless( eCookingStage_Purge, true );
break;
}
case eMainMenu_Settings: {
eMenuType = eMenuType_Settings;
repaint = true; repaint = true;
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, mdSettingsMenu._position, MENU_SIZE_SETTINGS_MENU - 1, 1, 1, 0 );
break;
}
case eMainMenu_Back: {
backToStatus();
break;
}
default: {
}
}
mdMainMenu._selection = eMainMenu_NULL;
}
void runStartFromStageSelection() {
switch (mdStartFromStageMenu._selection) {
case eStageMenu_Startpoint: {
xStartStageInteractive( &startpointTime, &startpointTemperature, eCookingStage_Startpoint );
break; break;
} }
default: {} case eStageMenu_BetaGlucanase: {
xStartStageInteractive( &betaGlucanaseTime, &betaGlucanaseTemperature, eCookingStage_BetaGlucanase );
break;
} }
xPrepareForStage( betaGlucanaseTime, betaGlucanaseTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_BetaGlucanase ); case eStageMenu_Debranching: {
xStartStageInteractive( &debranchingTime, &debranchingTemperature, eCookingStage_Debranching );
break; break;
} }
case eCookingStage_Debranching: { case eStageMenu_Proteolytic: {
xPrepareForStage( debranchingTime, debranchingTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_Debranching ); xStartStageInteractive( &proteolyticTime, &proteolyticTemperature, eCookingStage_Proteolytic );
break; break;
} }
case eCookingStage_Proteolytic: { case eStageMenu_BetaAmylase: {
xPrepareForStage( proteolyticTime, proteolyticTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_Proteolytic ); xStartStageInteractive( &betaAmylaseTime, &betaAmylaseTemperature, eCookingStage_BetaAmylase );
break; break;
} }
case eCookingStage_BetaAmylase: { case eStageMenu_AlphaAmylase: {
xPrepareForStage( betaAmylaseTime, betaAmylaseTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_BetaAmylase ); xStartStageInteractive( &alphaAmylaseTime, &alphaAmylaseTemperature, eCookingStage_AlphaAmylase );
break; break;
} }
case eCookingStage_AlphaAmylase: { case eStageMenu_Mashout: {
xPrepareForStage( alphaAmylaseTime, alphaAmylaseTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_AlphaAmylase ); xStartStageInteractive( &mashoutTime, &mashoutTemperature, eCookingStage_Mashout );
break; break;
} }
case eCookingStage_Mashout: { case eStageMenu_Recirculation: {
xPrepareForStage( mashoutTime, mashoutTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_Mashout ); xStartStageInteractive( &recirculationTime, &recirculationTemperature, eCookingStage_Recirculation );
break; break;
} }
case eCookingStage_Recirculation: { case eStageMenu_Sparge: {
xWaitForAction("Sparge Water", "Start heating your sparge water."); xStartStageInteractive( &spargeTime, &spargeTemperature, eCookingStage_Sparge );
repaint = true;
xPrepareForStage( recirculationTime, recirculationTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_Recirculation );
break; break;
} }
case eCookingStage_Sparge: { case eStageMenu_Boil: {
xWaitForAction("Sparge Water", "Start pouring the sparge water."); xStartStageInteractive( &boilTime, &boilTemperature, eCookingStage_Boil );
repaint = true;
xPrepareForStage( spargeTime, spargeTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_Sparge );
break; break;
} }
case eCookingStage_Boil: { case eStageMenu_Cooling: {
switch (beerProfile) { xStartStageInteractive( &coolingTime, &coolingTemperature, eCookingStage_Cooling );
case eBeerProfile_Trigo: { break;
String say = "Get "; }
case eStageMenu_Back: {
resetMenu( true );
break;
}
default: {
}
}
mdStartFromStageMenu._selection = eStageMenu_NULL;
}
float hopAmount = 0.8 * ((float) finalYield); void runBeerProfileSelection() {
say += String(hopAmount); switch (mdBeerProfileMenu._selection) {
case eBeerProfileMenu_Basic: {
beerProfile = eBeerProfile_Basic;
startpointTime = PROFILE_BASIC_STARTPOINT_TIME;
betaGlucanaseTime = PROFILE_BASIC_BETAGLUCANASE_TIME;
debranchingTime = PROFILE_BASIC_DEBRANCHING_TIME;
proteolyticTime = PROFILE_BASIC_PROTEOLYTIC_TIME;
betaAmylaseTime = PROFILE_BASIC_BETAAMYLASE_TIME;
alphaAmylaseTime = PROFILE_BASIC_ALPHAAMYLASE_TIME;
mashoutTime = PROFILE_BASIC_MASHOUT_TIME;
recirculationTime = PROFILE_BASIC_RECIRCULATION_TIME;
spargeTime = PROFILE_BASIC_SPARGE_TIME;
boilTime = PROFILE_BASIC_BOIL_TIME;
coolingTime = PROFILE_BASIC_COOLING_TIME;
startpointTemperature = PROFILE_BASIC_STARTPOINT_TEMPERATURE;
betaGlucanaseTemperature = PROFILE_BASIC_BETAGLUCANASE_TEMPERATURE;
debranchingTemperature = PROFILE_BASIC_DEBRANCHING_TEMPERATURE;
proteolyticTemperature = PROFILE_BASIC_PROTEOLYTIC_TEMPERATURE;
betaAmylaseTemperature = PROFILE_BASIC_BETAAMYLASE_TEMPERATURE;
alphaAmylaseTemperature = PROFILE_BASIC_ALPHAAMYLASE_TEMPERATURE;
mashoutTemperature = PROFILE_BASIC_MASHOUT_TEMPERATURE;
recirculationTemperature = PROFILE_BASIC_RECIRCULATION_TEMPERATURE;
spargeTemperature = PROFILE_BASIC_SPARGE_TEMPERATURE;
boilTemperature = PROFILE_BASIC_BOIL_TEMPERATURE;
coolingTemperature = PROFILE_BASIC_COOLING_TEMPERATURE;
say += String("g of Magnum 9.4\% and Styrian Golding 5\% ready."); backToStatus();
break;
}
case eBeerProfileMenu_Trigo: {
beerProfile = eBeerProfile_Trigo;
startpointTime = PROFILE_TRIGO_STARTPOINT_TIME;
betaGlucanaseTime = PROFILE_TRIGO_BETAGLUCANASE_TIME;
debranchingTime = PROFILE_TRIGO_DEBRANCHING_TIME;
proteolyticTime = PROFILE_TRIGO_PROTEOLYTIC_TIME;
betaAmylaseTime = PROFILE_TRIGO_BETAAMYLASE_TIME;
alphaAmylaseTime = PROFILE_TRIGO_ALPHAAMYLASE_TIME;
mashoutTime = PROFILE_TRIGO_MASHOUT_TIME;
recirculationTime = PROFILE_TRIGO_RECIRCULATION_TIME;
spargeTime = PROFILE_TRIGO_SPARGE_TIME;
boilTime = PROFILE_TRIGO_BOIL_TIME;
coolingTime = PROFILE_TRIGO_COOLING_TIME;
startpointTemperature = PROFILE_TRIGO_STARTPOINT_TEMPERATURE;
betaGlucanaseTemperature = PROFILE_TRIGO_BETAGLUCANASE_TEMPERATURE;
debranchingTemperature = PROFILE_TRIGO_DEBRANCHING_TEMPERATURE;
proteolyticTemperature = PROFILE_TRIGO_PROTEOLYTIC_TEMPERATURE;
betaAmylaseTemperature = PROFILE_TRIGO_BETAAMYLASE_TEMPERATURE;
alphaAmylaseTemperature = PROFILE_TRIGO_ALPHAAMYLASE_TEMPERATURE;
mashoutTemperature = PROFILE_TRIGO_MASHOUT_TEMPERATURE;
recirculationTemperature = PROFILE_TRIGO_RECIRCULATION_TEMPERATURE;
spargeTemperature = PROFILE_TRIGO_SPARGE_TEMPERATURE;
boilTemperature = PROFILE_TRIGO_BOIL_TEMPERATURE;
coolingTemperature = PROFILE_TRIGO_COOLING_TEMPERATURE;
xWaitForAction("Hops", say); backToStatus();
break;
}
case eBeerProfileMenu_IPA: {
beerProfile = eBeerProfile_IPA;
startpointTime = PROFILE_IPA_STARTPOINT_TIME;
betaGlucanaseTime = PROFILE_IPA_BETAGLUCANASE_TIME;
debranchingTime = PROFILE_IPA_DEBRANCHING_TIME;
proteolyticTime = PROFILE_IPA_PROTEOLYTIC_TIME;
betaAmylaseTime = PROFILE_IPA_BETAAMYLASE_TIME;
alphaAmylaseTime = PROFILE_IPA_ALPHAAMYLASE_TIME;
mashoutTime = PROFILE_IPA_MASHOUT_TIME;
recirculationTime = PROFILE_IPA_RECIRCULATION_TIME;
spargeTime = PROFILE_IPA_SPARGE_TIME;
boilTime = PROFILE_IPA_BOIL_TIME;
coolingTime = PROFILE_IPA_COOLING_TIME;
startpointTemperature = PROFILE_IPA_STARTPOINT_TEMPERATURE;
betaGlucanaseTemperature = PROFILE_IPA_BETAGLUCANASE_TEMPERATURE;
debranchingTemperature = PROFILE_IPA_DEBRANCHING_TEMPERATURE;
proteolyticTemperature = PROFILE_IPA_PROTEOLYTIC_TEMPERATURE;
betaAmylaseTemperature = PROFILE_IPA_BETAAMYLASE_TEMPERATURE;
alphaAmylaseTemperature = PROFILE_IPA_ALPHAAMYLASE_TEMPERATURE;
mashoutTemperature = PROFILE_IPA_MASHOUT_TEMPERATURE;
recirculationTemperature = PROFILE_IPA_RECIRCULATION_TEMPERATURE;
spargeTemperature = PROFILE_IPA_SPARGE_TEMPERATURE;
boilTemperature = PROFILE_IPA_BOIL_TEMPERATURE;
coolingTemperature = PROFILE_IPA_COOLING_TEMPERATURE;
backToStatus();
break; break;
} }
case eBeerProfile_IPA: { case eBeerProfileMenu_Belga: {
String say = "Get "; beerProfile = eBeerProfile_Belga;
startpointTime = PROFILE_BELGA_STARTPOINT_TIME;
betaGlucanaseTime = PROFILE_BELGA_BETAGLUCANASE_TIME;
debranchingTime = PROFILE_BELGA_DEBRANCHING_TIME;
proteolyticTime = PROFILE_BELGA_PROTEOLYTIC_TIME;
betaAmylaseTime = PROFILE_BELGA_BETAAMYLASE_TIME;
alphaAmylaseTime = PROFILE_BELGA_ALPHAAMYLASE_TIME;
mashoutTime = PROFILE_BELGA_MASHOUT_TIME;
recirculationTime = PROFILE_BELGA_RECIRCULATION_TIME;
spargeTime = PROFILE_BELGA_SPARGE_TIME;
boilTime = PROFILE_BELGA_BOIL_TIME;
coolingTime = PROFILE_BELGA_COOLING_TIME;
startpointTemperature = PROFILE_BELGA_STARTPOINT_TEMPERATURE;
betaGlucanaseTemperature = PROFILE_BELGA_BETAGLUCANASE_TEMPERATURE;
debranchingTemperature = PROFILE_BELGA_DEBRANCHING_TEMPERATURE;
proteolyticTemperature = PROFILE_BELGA_PROTEOLYTIC_TEMPERATURE;
betaAmylaseTemperature = PROFILE_BELGA_BETAAMYLASE_TEMPERATURE;
alphaAmylaseTemperature = PROFILE_BELGA_ALPHAAMYLASE_TEMPERATURE;
mashoutTemperature = PROFILE_BELGA_MASHOUT_TEMPERATURE;
recirculationTemperature = PROFILE_BELGA_RECIRCULATION_TEMPERATURE;
spargeTemperature = PROFILE_BELGA_SPARGE_TEMPERATURE;
boilTemperature = PROFILE_BELGA_BOIL_TEMPERATURE;
coolingTemperature = PROFILE_BELGA_COOLING_TEMPERATURE;
float hopAmount = 0.8 * ((float) finalYield); backToStatus();
say += String(hopAmount); break;
}
case eBeerProfileMenu_Red: {
beerProfile = eBeerProfile_Red;
startpointTime = PROFILE_RED_STARTPOINT_TIME;
betaGlucanaseTime = PROFILE_RED_BETAGLUCANASE_TIME;
debranchingTime = PROFILE_RED_DEBRANCHING_TIME;
proteolyticTime = PROFILE_RED_PROTEOLYTIC_TIME;
betaAmylaseTime = PROFILE_RED_BETAAMYLASE_TIME;
alphaAmylaseTime = PROFILE_RED_ALPHAAMYLASE_TIME;
mashoutTime = PROFILE_RED_MASHOUT_TIME;
recirculationTime = PROFILE_RED_RECIRCULATION_TIME;
spargeTime = PROFILE_RED_SPARGE_TIME;
boilTime = PROFILE_RED_BOIL_TIME;
coolingTime = PROFILE_RED_COOLING_TIME;
startpointTemperature = PROFILE_RED_STARTPOINT_TEMPERATURE;
betaGlucanaseTemperature = PROFILE_RED_BETAGLUCANASE_TEMPERATURE;
debranchingTemperature = PROFILE_RED_DEBRANCHING_TEMPERATURE;
proteolyticTemperature = PROFILE_RED_PROTEOLYTIC_TEMPERATURE;
betaAmylaseTemperature = PROFILE_RED_BETAAMYLASE_TEMPERATURE;
alphaAmylaseTemperature = PROFILE_RED_ALPHAAMYLASE_TEMPERATURE;
mashoutTemperature = PROFILE_RED_MASHOUT_TEMPERATURE;
recirculationTemperature = PROFILE_RED_RECIRCULATION_TEMPERATURE;
spargeTemperature = PROFILE_RED_SPARGE_TEMPERATURE;
boilTemperature = PROFILE_RED_BOIL_TEMPERATURE;
coolingTemperature = PROFILE_RED_COOLING_TEMPERATURE;
say += String("g of Chinook, Cascade and Styrian Golding ready."); backToStatus();
break;
}
case eBeerProfileMenu_APA: {
beerProfile = eBeerProfile_APA;
startpointTime = PROFILE_APA_STARTPOINT_TIME;
betaGlucanaseTime = PROFILE_APA_BETAGLUCANASE_TIME;
debranchingTime = PROFILE_APA_DEBRANCHING_TIME;
proteolyticTime = PROFILE_APA_PROTEOLYTIC_TIME;
betaAmylaseTime = PROFILE_APA_BETAAMYLASE_TIME;
alphaAmylaseTime = PROFILE_APA_ALPHAAMYLASE_TIME;
mashoutTime = PROFILE_APA_MASHOUT_TIME;
recirculationTime = PROFILE_APA_RECIRCULATION_TIME;
spargeTime = PROFILE_APA_SPARGE_TIME;
boilTime = PROFILE_APA_BOIL_TIME;
coolingTime = PROFILE_APA_COOLING_TIME;
startpointTemperature = PROFILE_APA_STARTPOINT_TEMPERATURE;
betaGlucanaseTemperature = PROFILE_APA_BETAGLUCANASE_TEMPERATURE;
debranchingTemperature = PROFILE_APA_DEBRANCHING_TEMPERATURE;
proteolyticTemperature = PROFILE_APA_PROTEOLYTIC_TEMPERATURE;
betaAmylaseTemperature = PROFILE_APA_BETAAMYLASE_TEMPERATURE;
alphaAmylaseTemperature = PROFILE_APA_ALPHAAMYLASE_TEMPERATURE;
mashoutTemperature = PROFILE_APA_MASHOUT_TEMPERATURE;
recirculationTemperature = PROFILE_APA_RECIRCULATION_TEMPERATURE;
spargeTemperature = PROFILE_APA_SPARGE_TEMPERATURE;
boilTemperature = PROFILE_APA_BOIL_TEMPERATURE;
coolingTemperature = PROFILE_APA_COOLING_TEMPERATURE;
xWaitForAction("Hops", say); backToStatus();
break;
}
case eBeerProfileMenu_Custom: {
beerProfile = eBeerProfile_Custom;
startpointTime = PROFILE_CUSTOM_STARTPOINT_TIME;
betaGlucanaseTime = PROFILE_CUSTOM_BETAGLUCANASE_TIME;
debranchingTime = PROFILE_CUSTOM_DEBRANCHING_TIME;
proteolyticTime = PROFILE_CUSTOM_PROTEOLYTIC_TIME;
betaAmylaseTime = PROFILE_CUSTOM_BETAAMYLASE_TIME;
alphaAmylaseTime = PROFILE_CUSTOM_ALPHAAMYLASE_TIME;
mashoutTime = PROFILE_CUSTOM_MASHOUT_TIME;
recirculationTime = PROFILE_CUSTOM_RECIRCULATION_TIME;
spargeTime = PROFILE_CUSTOM_SPARGE_TIME;
boilTime = PROFILE_CUSTOM_BOIL_TIME;
coolingTime = PROFILE_CUSTOM_COOLING_TIME;
startpointTemperature = PROFILE_CUSTOM_STARTPOINT_TEMPERATURE;
betaGlucanaseTemperature = PROFILE_CUSTOM_BETAGLUCANASE_TEMPERATURE;
debranchingTemperature = PROFILE_CUSTOM_DEBRANCHING_TEMPERATURE;
proteolyticTemperature = PROFILE_CUSTOM_PROTEOLYTIC_TEMPERATURE;
betaAmylaseTemperature = PROFILE_CUSTOM_BETAAMYLASE_TEMPERATURE;
alphaAmylaseTemperature = PROFILE_CUSTOM_ALPHAAMYLASE_TEMPERATURE;
mashoutTemperature = PROFILE_CUSTOM_MASHOUT_TEMPERATURE;
recirculationTemperature = PROFILE_CUSTOM_RECIRCULATION_TEMPERATURE;
spargeTemperature = PROFILE_CUSTOM_SPARGE_TEMPERATURE;
boilTemperature = PROFILE_CUSTOM_BOIL_TEMPERATURE;
coolingTemperature = PROFILE_CUSTOM_COOLING_TEMPERATURE;
backToStatus();
break;
}
case eBeerProfileMenu_Back: {
resetMenu( true );
break; break;
} }
default: { default: {}
xWaitForAction("Hops", "Add the hops in the right order, at the right time."); }
mdBeerProfileMenu._selection = eBeerProfileMenu_NULL;
}
void runStageSelection() {
switch (mdStageMenu._selection) {
case eStageMenu_Startpoint: {
runStageSelection_Generic( &startpointTime, &startpointTemperature );
break;
} }
case eStageMenu_BetaGlucanase: {
runStageSelection_Generic( &betaGlucanaseTime, &betaGlucanaseTemperature );
break;
} }
case eStageMenu_Debranching: {
repaint = true; runStageSelection_Generic( &debranchingTime, &debranchingTemperature );
// A basic operation for a basic stage
xPrepareForStage( boilTime, boilTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_Boil );
break; break;
} }
case eCookingStage_Cooling: { case eStageMenu_Proteolytic: {
// Make sure there is water runStageSelection_Generic( &proteolyticTime, &proteolyticTemperature );
xWaitForAction("Coil", "Add the coil and connect it to the main water supply.");
repaint = true;
// A basic operation for a basic stage
xPrepareForStage( coolingTime, coolingTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_Cooling );
break; break;
} }
case eCookingStage_Clean: { case eStageMenu_BetaAmylase: {
// Make sure there is water runStageSelection_Generic( &betaAmylaseTime, &betaAmylaseTemperature );
xWaitForAction("Water", "Add 13 liters.");
// Make sure there is water
xWaitForAction("Star San HB", "Add 0.89oz/26ml.");
repaint = true;
// A basic operation for a basic stage
xPrepareForStage( cleaningTime, cleaningTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_Clean );
break; break;
} }
case eCookingStage_Purge: { case eStageMenu_AlphaAmylase: {
// A basic operation for a basic stage runStageSelection_Generic( &alphaAmylaseTime, &alphaAmylaseTemperature );
xPrepareForStage( 0, 0, PUMP_SPEED_MAX_MOSFET, eCookingStage_Purge );
xRegulatePumpSpeed();
break; break;
} }
case eCookingStage_Done: { case eStageMenu_Mashout: {
// A basic operation for a basic stage runStageSelection_Generic( &mashoutTime, &mashoutTemperature );
xPrepareForStage( 0, 0, PUMP_SPEED_STOP_MOSFET, eCookingStage_Done );
break; break;
} }
case eStageMenu_Recirculation: {
runStageSelection_Generic( &recirculationTime, &recirculationTemperature );
break;
} }
} case eStageMenu_Sparge: {
runStageSelection_Generic( &spargeTime, &spargeTemperature );
void xTransitionIntoStage(eCookingStages nextStage) { break;
// 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
xSetupStage( nextStage );
}
void xBasicStageOperation( int iStageTime, int iStageTemperature, int iStageTemperatureRange, eCookingStages nextStage, boolean bMaximumOfUpDown ) {
// Account for time spent at the target temperature | Input 1: range in ºC within which the target temperature is considered to be reached
#ifdef DEBUG_OFF
xCountTheTime( iStageTemperatureRange, false );
#else
xCountTheTime( iStageTemperatureRange, bMaximumOfUpDown );
#endif
if ( isTimeLeft() ) {
// Do temperature control
xRegulateTemperature( bMaximumOfUpDown );
// Do flow control
xRegulatePumpSpeed();
} else {
#ifdef DEBUG_OFF
debugPrintFunction("xBasicStageOperation");
debugPrintVar("clockCounter", clockCounter);
#endif
// Continue to the next stage, there is nothing to do, in this stage
xTransitionIntoStage( nextStage );
return;
} }
case eStageMenu_Boil: {
return; runStageSelection_Generic( &boilTime, &boilTemperature );
} break;
void xManageMachineSystems() {
#ifdef DEBUG
Serial.print(millis());
Serial.print(",");
if (cooking) {
Serial.print("1");
} }
else { case eStageMenu_Cooling: {
Serial.print("0"); runStageSelection_Generic( &coolingTime, &coolingTemperature );
break;
} }
Serial.print(","); case eStageMenu_Back: {
Serial.print(cookTemperature); resetMenu( true );
Serial.print(","); break;
if (bStatusElement) {
Serial.print("1");
} }
else { default: {}
Serial.print("0");
} }
Serial.print(","); mdStageMenu._selection = eStageMenu_NULL;
#endif }
// Measure temperature, for effect
basePT100.measure(false);
upPT100.measure(false);
downPT100.measure(true);
// 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; void runSettingsSelection() {
switch (mdSettingsMenu._selection) {
case eSettingsMenu_Pump: {
// Stuff
if ( xSetGenericValue( iPumpSpeed ? 0 : 1, 0, 1, "pump", "bool" ) ) {
iPumpSpeed = PUMP_SPEED_MAX_MOSFET;
} else {
iPumpSpeed = PUMP_SPEED_STOP_MOSFET;
} }
analogWrite(PUMP_PIN, iPumpSpeed);
// Operate the machine according to the current mode backToStatus();
switch (cookingStage) {
case eCookingStage_Startpoint: {
// A basic operation for a basic stage
xBasicStageOperation( startpointTime, startpointTemperature, 0, eCookingStage_BetaGlucanase, false);
break; break;
} }
case eCookingStage_BetaGlucanase: { case eSettingsMenu_PT100_Element: {
// A basic operation for a basic stage backToStatus();
xBasicStageOperation( betaGlucanaseTime, betaGlucanaseTemperature, 3, eCookingStage_Debranching, true );
break; break;
} }
case eCookingStage_Debranching: { case eSettingsMenu_PT100_Up: {
// A basic operation for a basic stage backToStatus();
xBasicStageOperation( debranchingTime, debranchingTemperature, 3, eCookingStage_Proteolytic, true );
break; break;
} }
case eCookingStage_Proteolytic: { case eSettingsMenu_PT100_Down: {
// A basic operation for a basic stage backToStatus();
xBasicStageOperation( proteolyticTime, proteolyticTemperature, 3, eCookingStage_BetaAmylase, true );
break; break;
} }
case eCookingStage_BetaAmylase: { case eSettingsMenu_Back: {
// A basic operation for a basic stage resetMenu( true );
xBasicStageOperation( betaAmylaseTime, betaAmylaseTemperature, 4, eCookingStage_AlphaAmylase, true );
break; break;
} }
case eCookingStage_AlphaAmylase: { default: {}
// A basic operation for a basic stage
xBasicStageOperation( alphaAmylaseTime, alphaAmylaseTemperature, 2, eCookingStage_Mashout, true );
break;
} }
case eCookingStage_Mashout: { mdSettingsMenu._selection = eSettingsMenu_NULL;
// A basic operation for a basic stage }
xBasicStageOperation( mashoutTime, mashoutTemperature, 1, eCookingStage_Recirculation, true );
void runMaltSelection() {
switch (mdMaltMenu._selection) {
case eMaltMenu_CastleMalting_Chteau_Pilsen_2RS: {
backToStatus();
break; break;
} }
case eCookingStage_Recirculation: { case eMaltMenu_CastleMalting_Wheat_Blanc: {
// A basic operation for a basic stage backToStatus();
xBasicStageOperation( recirculationTime, recirculationTemperature, 1, eCookingStage_Sparge, true );
break; break;
} }
case eCookingStage_Sparge: { case eMaltMenu_Back: {
// A basic operation for a basic stage resetMenu( true );
xBasicStageOperation( spargeTime, spargeTemperature, 3, eCookingStage_Boil, false );
break; break;
} }
case eCookingStage_Boil: { default: {}
// A basic operation for a basic stage
xBasicStageOperation( boilTime, boilTemperature, 2, eCookingStage_Cooling, false );
break;
} }
case eCookingStage_Cooling: { mdMaltMenu._selection = eMaltMenu_NULL;
// A basic operation for a basic stage }
xBasicStageOperation( coolingTime, coolingTemperature, 0, eCookingStage_Done, false );
break; // ************************ MENU HELPERS ******************************
} void runMenuProcessor( MenuData *data ) {
case eCookingStage_Clean: { data->_position = rotaryEncoderVirtualPosition; // Read position
// A basic operation for a basic stage
xBasicStageOperation( cleaningTime, cleaningTemperature, 0, eCookingStage_Done, false );
break; data->_repaint = repaint; // Request repaint
repaint = displayGenericMenu( &lcd, data ); // Display menu
if ( gotButtonPress( ROTARY_ENCODER_SW_PIN ) ) { // Read selection
data->_selection = data->_position;
} }
case eCookingStage_Purge: {
// A basic operation for a basic stage
//xBasicStageOperation( coolingTime, coolingTemperature, 1, eCookingStage_Done );
iPumpSpeed = PUMP_SPEED_MAX_MOSFET;
xRegulatePumpSpeed(); (data->_selectionFunction)(); // Run selection function
}
break; void runStageSelection_Generic( unsigned long * selectedStageTime, int *selectedStageTemperature) {
} (*selectedStageTime) = getTimer( (*selectedStageTime) );
case eCookingStage_Done: { (*selectedStageTemperature) = xSetGenericValue( (*selectedStageTemperature), TEMPERATURE_MIN_VALUE, TEMPERATURE_MAX_VALUE, MENU_GLOBAL_STR_TEMPERATURE, MENU_GLOBAL_STR_CELSIUS );
// Update cooking state backToStatus();
stopBrewing(); }
// Ask for screen refresh void xStartStageHeadless( eCookingStages nextStage, bool bPurgePump ) {
repaint = true; xStartStage( NULL, NULL, nextStage, bPurgePump, false, false, false );
}
// Warn the user that the cooking is done void xStartStageInteractive( unsigned long *stageTime, int *stageTemperature, eCookingStages nextStage ) {
xWarnCookEnded(); xStartStage( stageTime, stageTemperature, nextStage, true, true, true, true );
}
break; void xStartStage( unsigned long *stageTime, int *stageTemperature, eCookingStages nextStage, bool bPurgePump, bool bSetFinalYield, bool bSetTime, bool bSetTemperature ) {
xSafeHardwarePowerOff(); // Stop anything that might be still going on
if (bSetFinalYield) {
finalYield = xSetFinalYield( finalYield );
}
if (bSetTime) {
(*stageTime) = getTimer( clockCounter / 1000, (*stageTime) );
}
if (bSetTemperature) {
(*stageTemperature) = xSetTemperature( (*stageTemperature) );
} }
if (bPurgePump) {
xPurgePump();
} }
startBrewing();
xSetupStage( nextStage );
backToStatus();
} }
// ##################################################### Menus ###################################################################
// #################################################### Helpers ################################################################## // #################################################### Helpers ##################################################################
...@@ -1708,7 +1495,6 @@ void resetMenu( boolean requestRepaintPaint ) { ...@@ -1708,7 +1495,6 @@ void resetMenu( boolean requestRepaintPaint ) {
} }
// reset operation state | INPUT : eRotaryEncoderMode newMode, int newPosition, int newMaxPosition, int newMinPosition, int newSingleStep, int newMultiStep // reset operation state | INPUT : eRotaryEncoderMode newMode, int newPosition, int newMaxPosition, int newMinPosition, int newSingleStep, int newMultiStep
//xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eMainMenuPosition, MENU_SIZE_MAIN_MENU - 1, 1, 1, 0 );
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, mdMainMenu._position, MENU_SIZE_MAIN_MENU - 1, 1, 1, 0 ); xSetupRotaryEncoder( eRotaryEncoderMode_Menu, mdMainMenu._position, MENU_SIZE_MAIN_MENU - 1, 1, 1, 0 );
} }
......
...@@ -95,36 +95,45 @@ ...@@ -95,36 +95,45 @@
#define MENU_MAIN_INIT_POSITION eMainMenu_GO #define MENU_MAIN_INIT_POSITION eMainMenu_GO
#define MENU_MAIN_INIT_SELECTION eMainMenu_NULL #define MENU_MAIN_INIT_SELECTION eMainMenu_NULL
#define MENU_MAIN_INIT_REPAINT false #define MENU_MAIN_INIT_REPAINT false
#define MENU_MAIN_FUNCTION &runMainMenuSelection
#define MENU_PROFILE_TITLE "Profile Menu" #define MENU_PROFILE_TITLE "Profile Menu"
#define MENU_PROFILE_DIALOG {"", "-> Basic ", "-> Trigo ", "-> IPA ", "-> Belga ", "-> Red ", "-> APA ", "-> Custom ", "-> Back " } #define MENU_PROFILE_DIALOG {"", "-> Basic ", "-> Trigo ", "-> IPA ", "-> Belga ", "-> Red ", "-> APA ", "-> Custom ", "-> Back " }
#define MENU_PROFILE_INIT_POSITION eBeerProfileMenu_Basic #define MENU_PROFILE_INIT_POSITION eBeerProfileMenu_Basic
#define MENU_PROFILE_INIT_SELECTION eBeerProfileMenu_NULL #define MENU_PROFILE_INIT_SELECTION eBeerProfileMenu_NULL
#define MENU_PROFILE_INIT_REPAINT false #define MENU_PROFILE_INIT_REPAINT false
#define MENU_PROFILE_FUNCTION &runBeerProfileSelection
#define MENU_STAGE_TITLE "Stage Menu" #define MENU_STAGE_TITLE "Stage Menu"
#define MENU_STAGE_DIALOG {"", "-> Startpoint ", "-> BetaGlucanase", "-> Debranching ", "-> Proteolytic ", "-> Beta Amylase ", "-> Alpha Amylase", "-> Mashout ", "-> Recirculation", "-> Sparge ", "-> Boil ", "-> Cooling ", "-> Back " } #define MENU_STAGE_DIALOG {"", "-> Startpoint ", "-> BetaGlucanase", "-> Debranching ", "-> Proteolytic ", "-> Beta Amylase ", "-> Alpha Amylase", "-> Mashout ", "-> Recirculation", "-> Sparge ", "-> Boil ", "-> Cooling ", "-> Back " }
#define MENU_STAGE_INIT_POSITION eStageMenu_Startpoint #define MENU_STAGE_INIT_POSITION eStageMenu_Startpoint
#define MENU_STAGE_INIT_SELECTION eStageMenu_NULL #define MENU_STAGE_INIT_SELECTION eStageMenu_NULL
#define MENU_STAGE_INIT_REPAINT false #define MENU_STAGE_INIT_REPAINT false
#define MENU_STAGE_FUNCTION &runStageSelection
#define MENU_MALT_TITLE "Malt Menu" #define MENU_MALT_TITLE "Malt Menu"
#define MENU_MALT_DIALOG {"", "-> CM Ch. Pilsen", "-> CM Wheat Blan", "-> Back " } #define MENU_MALT_DIALOG {"", "-> CM Ch. Pilsen", "-> CM Wheat Blan", "-> Back " }
#define MENU_MALT_INIT_POSITION eMaltMenu_CastleMalting_Chteau_Pilsen_2RS #define MENU_MALT_INIT_POSITION eMaltMenu_CastleMalting_Chteau_Pilsen_2RS
#define MENU_MALT_INIT_SELECTION eMaltMenu_NULL #define MENU_MALT_INIT_SELECTION eMaltMenu_NULL
#define MENU_MALT_INIT_REPAINT false #define MENU_MALT_INIT_REPAINT false
#define MENU_MALT_FUNCTION &runMaltSelection
#define MENU_SETTINGS_TITLE "Settings Menu" #define MENU_SETTINGS_TITLE "Settings Menu"
#define MENU_SETTINGS_DIALOG {"", "-> PT100 Element", "-> PT100 Up ", "-> PT100 Down ", "-> Back " } #define MENU_SETTINGS_DIALOG {"", "-> PT100 Element", "-> PT100 Up ", "-> PT100 Down ", "-> Back " }
#define MENU_SETTINGS_INIT_POSITION eSettingsMenu_PT100_Element #define MENU_SETTINGS_INIT_POSITION eSettingsMenu_PT100_Element
#define MENU_SETTINGS_INIT_SELECTION eSettingsMenu_NULL #define MENU_SETTINGS_INIT_SELECTION eSettingsMenu_NULL
#define MENU_SETTINGS_INIT_REPAINT false #define MENU_SETTINGS_INIT_REPAINT false
#define MENU_SETTINGS_FUNCTION &runSettingsSelection
#define MENU_GLOBAL_STR_TEMPERATURE "temperature"
#define MENU_GLOBAL_STR_CELSIUS "*C"
#define MENU_START_TITLE MENU_STAGE_TITLE #define MENU_START_TITLE MENU_STAGE_TITLE
#define MENU_START_DIALOG MENU_STAGE_DIALOG #define MENU_START_DIALOG MENU_STAGE_DIALOG
#define MENU_START_INIT_POSITION MENU_STAGE_INIT_POSITION #define MENU_START_INIT_POSITION MENU_STAGE_INIT_POSITION
#define MENU_START_INIT_SELECTION MENU_STAGE_INIT_SELECTION #define MENU_START_INIT_SELECTION MENU_STAGE_INIT_SELECTION
#define MENU_START_INIT_REPAINT MENU_STAGE_INIT_REPAINT #define MENU_START_INIT_REPAINT MENU_STAGE_INIT_REPAINT
#define MENU_START_FUNCTION &runStartFromStageSelection
// ++++++++++++++++++++++++ Serial Monotor ++++++++++++++++++++++++ // ++++++++++++++++++++++++ Serial Monotor ++++++++++++++++++++++++
#define SETTING_SERIAL_MONITOR_BAUD_RATE 9600 #define SETTING_SERIAL_MONITOR_BAUD_RATE 9600
......
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