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_ {
int _position;
int _selection;
bool _repaint;
void (*_selectionFunction)(void);
} MenuData;
#endif
......@@ -17,6 +17,14 @@
#include "CustomDataStructures.h"
#include "debug.h"
// ++++++++++++++++++++++++ FUNCTIONS (used in configuration) +++++++++++++++++++++++++++++++++
void runMainMenuSelection();
void runStartFromStageSelection();
void runBeerProfileSelection();
void runStageSelection();
void runMaltSelection();
void runSettingsSelection();
#include "config.h"
#include "Melody.h"
......@@ -38,13 +46,9 @@ void xWelcomeUser();
void runMenu();
void runSettingsSelection();
void runMenuProcessor( MenuData *data );
void runMaltSelection();
void runStageSelection();
void runBeerProfileSelection();
void runStageSelection_Generic( unsigned long * selectedStageTime, int *selectedStageTemperature);
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 );
void xStartStageInteractive( unsigned long *stageTime, int *stageTemperature, eCookingStages nextStage );
void runStartFromStageSelection();
void runMainMenuSelection();
void xCountTheTime( int temperatureRange, boolean bAverageUpDown );
bool isTimeLeft();
......
......@@ -18,25 +18,12 @@ eBeerProfile beerProfile;
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 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 };
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 };
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 };
//eMainMenuOptions eMainMenuPosition;
//eMainMenuOptions eMainMenuSelection;
eStageMenuOptions eStartFromStageMenuPosition;
eStageMenuOptions eStartFromStageMenuSelection;
eBeerProfileMenuOptions eBeerProfileMenuPosition;
eBeerProfileMenuOptions eBeerProfileMenuSelection;
eStageMenuOptions eStageMenuPosition;
eStageMenuOptions eStageMenuSelection;
eMaltMenuOptions eMaltMenuPosition;
eMaltMenuOptions eMaltMenuSelection;
eSettingsMenuOptions eSettingsMenuPosition;
eSettingsMenuOptions eSettingsMenuSelection;
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 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 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 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 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 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 };
// ++++++++++++++++++++++++ Global Variables ++++++++++++++++++++++++
boolean cooking;
......@@ -147,10 +134,10 @@ void isr () { // Interrupt service routine is executed when a HIGH to LOW tr
rotaryEncoderVirtualPosition = rotaryEncoderVirtualPosition - rotaryEncoderSingleStep;
}
if (rotaryEncoderVirtualPosition > rotaryEncoderMaxPosition) {
rotaryEncoderVirtualPosition = rotaryEncoderMinPosition;
rotaryEncoderVirtualPosition = rotaryEncoderMaxPosition;
}
if (rotaryEncoderVirtualPosition < rotaryEncoderMinPosition) {
rotaryEncoderVirtualPosition = rotaryEncoderMaxPosition;
rotaryEncoderVirtualPosition = rotaryEncoderMinPosition;
}
break;
......@@ -301,17 +288,6 @@ void setup() {
// ++++++++++++++++++++++++ State Machine ++++++++++++++++++++++++
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;
beerProfile = eBeerProfile_Basic;
// ++++++++++++++++++++++++ Global Variables ++++++++++++++++++++++++
......@@ -394,634 +370,620 @@ void loop() {
// ######################### 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;
}
case eMenuType_StartFromStage: {
eStartFromStageMenuPosition = static_cast<eStageMenuOptions>(rotaryEncoderVirtualPosition);
// 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();
}
repaint = displayStageMenu( &lcd, eStartFromStageMenuPosition, repaint );
// 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;
}
if ( gotButtonPress( ROTARY_ENCODER_SW_PIN ) ) {
eStartFromStageMenuSelection = eStartFromStageMenuPosition;
}
// Calculate the remaining time on the clock
clockCounter = cookTime * 1000 - (elapsedTime - clockIgnore);
runStartFromStageSelection();
// Don't let clock get bellow 0
if ( clockCounter < 0 ) {
clockCounter = 0;
}
break;
}
case eMenuType_BeerProfile: {
eBeerProfileMenuPosition = static_cast<eBeerProfileMenuOptions>(rotaryEncoderVirtualPosition);
clockLastUpdate = now;
repaint = displayBeerProfileMenu( &lcd, eBeerProfileMenuPosition, repaint );
#ifdef DEBUG_OFF
debugPrintFunction("xCountTheTime");
debugPrintVar("millis()", now);
debugPrintVar("cookTime", cookTime);
debugPrintVar("clockStartTime", clockStartTime);
debugPrintVar("clockIgnore", clockIgnore);
debugPrintVar("clockCounter", clockCounter);
#endif
}
if ( gotButtonPress( ROTARY_ENCODER_SW_PIN ) ) {
eBeerProfileMenuSelection = eBeerProfileMenuPosition;
}
bool isTimeLeft() {
if ( clockCounter > 0 ) {
return true;
}
return false;
}
runBeerProfileSelection();
//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;
}
break;
}
case eMenuType_Stage: {
eStageMenuPosition = static_cast<eStageMenuOptions>(rotaryEncoderVirtualPosition);
bool xRegulateTemperature( boolean bMaximumOfUpDown ) {
double difference = 0;
bool overTemperature = false;
double wattage = 0.0;
repaint = displayStageMenu( &lcd, eStageMenuPosition, repaint );
float tup = upPT100.getCurrentTemperature();
float tdown = downPT100.getCurrentTemperature();
float tbase = basePT100.getCurrentTemperature();
if ( gotButtonPress( ROTARY_ENCODER_SW_PIN ) ) {
eStageMenuSelection = eStageMenuPosition;
}
if ( bMaximumOfUpDown ) {
if (tup > tdown) {
difference = cookTemperature - tup;
}
else {
difference = cookTemperature - tdown;
}
runStageSelection();
if (tbase > cookTemperature && (tbase >= (PUMP_TEMPERATURE_MAX_OPERATION - 2.0) || difference >= 5.0)) {
difference = cookTemperature - tbase;
}
break;
}
case eMenuType_Malt: {
eMaltMenuPosition = static_cast<eMaltMenuOptions>(rotaryEncoderVirtualPosition);
if ( (tbase < cookTemperature) && (difference < (cookTemperature - tbase)) ) {
difference = cookTemperature - tbase;
}
} else {
difference = cookTemperature - tbase;
}
repaint = displayMaltMenu( &lcd, eMaltMenuPosition, repaint );
// Deviation between the cook temperature set and the cook temperature measured
if ( difference < 0.0 ) {
difference = difference * (-1.0);
overTemperature = true;
}
if ( gotButtonPress( ROTARY_ENCODER_SW_PIN ) ) {
eMaltMenuSelection = eMaltMenuPosition;
// 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;
}
runMaltSelection();
break;
}
case eMenuType_Settings: {
eSettingsMenuPosition = static_cast<eSettingsMenuOptions>(rotaryEncoderVirtualPosition);
repaint = displaySettingsMenu( &lcd, eSettingsMenuPosition, repaint );
} else {
if (difference <= 1.0) {
// pulse moderately at 1000 watt
if (cookTemperature > 99.0) {
wattage = 2000.0;
}
else {
wattage = 1000.0;
}
if ( gotButtonPress( ROTARY_ENCODER_SW_PIN ) ) {
eSettingsMenuSelection = eSettingsMenuPosition;
} 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;
}
}
}
//}
}
runSettingsSelection();
// 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;
}
break;
}
// Apply wattage to the element at the right time
if ( ulWattToWindowTime( wattage ) > (millis() - windowStartTime) ) {
digitalWrite(HEATING_ELEMENT_OUTPUT_PIN, HIGH);
bStatusElement = true;
} else {
digitalWrite(HEATING_ELEMENT_OUTPUT_PIN, LOW);
bStatusElement = false;
}
#ifdef DEBUG_OFF
if (debug_go) {
debugPrintVar("repaint", repaint);
}
//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 runSettingsSelection() {
switch (eSettingsMenuSelection) {
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);
backToStatus();
break;
}
case eSettingsMenu_PT100_Element: {
// Stuff
backToStatus();
break;
}
case eSettingsMenu_PT100_Up: {
// Stuff
backToStatus();
break;
}
case eSettingsMenu_PT100_Down: {
// Stuff
void xPurgePump() {
for (int i = 0; i < 2; i++) {
analogWrite(PUMP_PIN, PUMP_SPEED_MAX_MOSFET); // analogWrite values from 0 to 255
delay(1000);
analogWrite(PUMP_PIN, PUMP_SPEED_STOP_MOSFET); // analogWrite values from 0 to 255
delay(1500);
}
}
backToStatus();
bool xRegulatePumpSpeed() {
// analogWrite(PUMP_PIN, iPumpSpeed); // analogWrite values from 0 to 255
break;
}
case eSettingsMenu_Back: {
eMenuType = eMenuType_Main;
repaint = true;
if (basePT100.getCurrentTemperature() > PUMP_TEMPERATURE_MAX_OPERATION) {
analogWrite(PUMP_PIN, PUMP_SPEED_STOP_MOSFET); // analogWrite values from 0 to 255
// 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 );
basePT100.setPumpStatus( false );
upPT100.setPumpStatus( false );
downPT100.setPumpStatus( false );
}
else {
analogWrite(PUMP_PIN, iPumpSpeed); // analogWrite values from 0 to 255
break;
}
default: {
}
basePT100.setPumpStatus( true );
upPT100.setPumpStatus( true );
downPT100.setPumpStatus( true );
}
}
eSettingsMenuSelection = eSettingsMenu_NULL;
void xWarnClockEnded() {
sing(MELODY_SUPER_MARIO_START, PIEZO_PIN);
}
void runMaltSelection() {
switch (eMaltMenuSelection) {
case eMaltMenu_CastleMalting_Chteau_Pilsen_2RS: {
// Stuff
void xWarnCookEnded() {
sing(MELODY_UNDERWORLD_SHORT, PIEZO_PIN);
}
backToStatus();
void xPrepareForStage( int stageTime, int stageTemperature, int stagePumpSpeed, eCookingStages stage ) {
#ifdef DEBUG_OFF
debugPrintFunction("xPrepareForStage");
debugPrintVar("cookingStage", stage);
#endif
break;
}
case eMaltMenu_CastleMalting_Wheat_Blanc: {
// Stuff
backToStatus();
break;
}
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;
}
default: {
}
}
// Reset the clock
unsigned long now = millis();
clockStartTime = now;
clockLastUpdate = now;
clockIgnore = 0;
eMaltMenuSelection = eMaltMenu_NULL;
iPumpSpeed = stagePumpSpeed; // Set the pump speed
cookingStage = stage; // Set Stage
cookTime = stageTime; // Set the clock
cookTemperature = stageTemperature; // Set the target temperature
}
void runStageSelection() {
switch (eStageMenuSelection) {
case eStageMenu_Startpoint: {
startpointTime = getTimer( startpointTime );
void xSetupStage(eCookingStages nextStage) {
#ifdef DEBUG_OFF
debugPrintFunction("xSetupStage");
debugPrintVar("cookingStage", nextStage);
#endif
startpointTemperature = xSetGenericValue( startpointTemperature, TEMPERATURE_MIN_VALUE, TEMPERATURE_MAX_VALUE, "temperature", "*C" );
// 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.");
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.");
break;
}
case eStageMenu_BetaGlucanase: {
betaGlucanaseTime = getTimer( betaGlucanaseTime );
xWaitForAction("Malt", say);
repaint = true;
break;
}
default: {
betaGlucanaseTemperature = xSetGenericValue( betaGlucanaseTemperature, 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;
}
case eStageMenu_Debranching: {
debranchingTime = getTimer( debranchingTime );
debranchingTemperature = xSetGenericValue( debranchingTemperature, TEMPERATURE_MIN_VALUE, TEMPERATURE_MAX_VALUE, "temperature", "*C" );
case eCookingStage_BetaGlucanase: {
switch (beerProfile) {
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.");
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;
}
default: {}
}
xPrepareForStage( betaGlucanaseTime, betaGlucanaseTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_BetaGlucanase );
break;
}
case eStageMenu_Proteolytic: {
proteolyticTime = getTimer( proteolyticTime );
proteolyticTemperature = xSetGenericValue( proteolyticTemperature, TEMPERATURE_MIN_VALUE, TEMPERATURE_MAX_VALUE, "temperature", "*C" );
backToStatus();
case eCookingStage_Debranching: {
xPrepareForStage( debranchingTime, debranchingTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_Debranching );
break;
}
case eStageMenu_BetaAmylase: {
betaAmylaseTime = getTimer( betaAmylaseTime );
betaAmylaseTemperature = xSetGenericValue( betaAmylaseTemperature, TEMPERATURE_MIN_VALUE, TEMPERATURE_MAX_VALUE, "temperature", "*C" );
backToStatus();
case eCookingStage_Proteolytic: {
xPrepareForStage( proteolyticTime, proteolyticTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_Proteolytic );
break;
}
case eStageMenu_AlphaAmylase: {
alphaAmylaseTime = getTimer( alphaAmylaseTime );
alphaAmylaseTemperature = xSetGenericValue( alphaAmylaseTemperature, TEMPERATURE_MIN_VALUE, TEMPERATURE_MAX_VALUE, "temperature", "*C" );
backToStatus();
case eCookingStage_BetaAmylase: {
xPrepareForStage( betaAmylaseTime, betaAmylaseTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_BetaAmylase );
break;
}
case eStageMenu_Mashout: {
mashoutTime = getTimer( mashoutTime );
mashoutTemperature = xSetGenericValue( mashoutTemperature, TEMPERATURE_MIN_VALUE, TEMPERATURE_MAX_VALUE, "temperature", "*C" );
backToStatus();
case eCookingStage_AlphaAmylase: {
xPrepareForStage( alphaAmylaseTime, alphaAmylaseTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_AlphaAmylase );
break;
}
case eStageMenu_Recirculation: {
recirculationTime = getTimer( recirculationTime );
recirculationTemperature = xSetGenericValue( recirculationTemperature, TEMPERATURE_MIN_VALUE, TEMPERATURE_MAX_VALUE, "temperature", "*C" );
backToStatus();
case eCookingStage_Mashout: {
xPrepareForStage( mashoutTime, mashoutTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_Mashout );
break;
}
case eStageMenu_Sparge: {
spargeTime = getTimer( spargeTime );
spargeTemperature = xSetGenericValue( spargeTemperature, TEMPERATURE_MIN_VALUE, TEMPERATURE_MAX_VALUE, "temperature", "*C" );
backToStatus();
case eCookingStage_Recirculation: {
xWaitForAction("Sparge Water", "Start heating your sparge water.");
repaint = true;
xPrepareForStage( recirculationTime, recirculationTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_Recirculation );
break;
}
case eStageMenu_Boil: {
boilTime = getTimer( boilTime );
boilTemperature = xSetGenericValue( boilTemperature, TEMPERATURE_MIN_VALUE, TEMPERATURE_MAX_VALUE, "temperature", "*C" );
backToStatus();
case eCookingStage_Sparge: {
xWaitForAction("Sparge Water", "Start pouring the sparge water.");
repaint = true;
xPrepareForStage( spargeTime, spargeTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_Sparge );
break;
}
case eStageMenu_Cooling: {
coolingTime = getTimer( coolingTime );
coolingTemperature = xSetGenericValue( coolingTemperature, TEMPERATURE_MIN_VALUE, TEMPERATURE_MAX_VALUE, "temperature", "*C" );
case eCookingStage_Boil: {
switch (beerProfile) {
case eBeerProfile_Trigo: {
String say = "Get ";
backToStatus();
float hopAmount = 0.8 * ((float) finalYield);
say += String(hopAmount);
break;
}
case eStageMenu_Back: {
eMenuType = eMenuType_Main;
repaint = true;
say += String("g of Magnum 9.4\% and Styrian Golding 5\% ready.");
// 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 );
xWaitForAction("Hops", say);
break;
}
default: {
}
}
break;
}
case eBeerProfile_IPA: {
String say = "Get ";
eStageMenuSelection = eStageMenu_NULL;
}
float hopAmount = 0.8 * ((float) finalYield);
say += String(hopAmount);
void runBeerProfileSelection() {
switch (eBeerProfileMenuSelection) {
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 Chinook, Cascade and Styrian Golding ready.");
backToStatus();
xWaitForAction("Hops", say);
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;
break;
}
default: {
xWaitForAction("Hops", "Add the hops in the right order, at the right time.");
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;
repaint = true;
backToStatus();
// A basic operation for a basic stage
xPrepareForStage( boilTime, boilTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_Boil );
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;
case eCookingStage_Cooling: {
// Make sure there is water
xWaitForAction("Coil", "Add the coil and connect it to the main water supply.");
backToStatus();
repaint = true;
// A basic operation for a basic stage
xPrepareForStage( coolingTime, coolingTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_Cooling );
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;
case eCookingStage_Clean: {
// Make sure there is water
xWaitForAction("Water", "Add 13 liters.");
backToStatus();
// Make sure there is water
xWaitForAction("Star San HB", "Add 0.89oz/26ml.");
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;
repaint = true;
backToStatus();
// A basic operation for a basic stage
xPrepareForStage( cleaningTime, cleaningTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_Clean );
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;
case eCookingStage_Purge: {
// A basic operation for a basic stage
xPrepareForStage( 0, 0, PUMP_SPEED_MAX_MOSFET, eCookingStage_Purge );
backToStatus();
xRegulatePumpSpeed();
break;
}
case eBeerProfileMenu_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 );
case eCookingStage_Done: {
// A basic operation for a basic stage
xPrepareForStage( 0, 0, PUMP_SPEED_STOP_MOSFET, eCookingStage_Done );
break;
}
default: {
}
}
eBeerProfileMenuSelection = eBeerProfileMenu_NULL;
}
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
void xTransitionIntoStage(eCookingStages nextStage) {
// Turn off all hardware that can damage itself if the machine is not cooking
xSafeHardwarePowerOff();
if (bSetFinalYield) {
finalYield = xSetFinalYield( finalYield );
// 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;
}
if (bSetTime) {
(*stageTime) = getTimer( clockCounter / 1000, (*stageTime) );
return;
}
void xManageMachineSystems() {
#ifdef DEBUG
Serial.print(millis());
Serial.print(",");
if (cooking) {
Serial.print("1");
}
if (bSetTemperature) {
(*stageTemperature) = xSetTemperature( (*stageTemperature) );
else {
Serial.print("0");
}
if (bPurgePump) {
xPurgePump();
Serial.print(",");
Serial.print(cookTemperature);
Serial.print(",");
if (bStatusElement) {
Serial.print("1");
}
else {
Serial.print("0");
}
Serial.print(",");
#endif
startBrewing();
xSetupStage( nextStage );
backToStatus();
}
// Measure temperature, for effect
basePT100.measure(false);
upPT100.measure(false);
downPT100.measure(true);
void xStartStageHeadless( eCookingStages nextStage, bool bPurgePump ) {
xStartStage( NULL, NULL, nextStage, bPurgePump, false, false, false );
}
// 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();
void xStartStageInteractive( unsigned long *stageTime, int *stageTemperature, eCookingStages nextStage ) {
xStartStage( stageTime, stageTemperature, nextStage, true, true, true, true );
}
return;
}
void runStartFromStageSelection() {
switch (eStartFromStageMenuSelection) {
case eStageMenu_Startpoint: {
xStartStageInteractive( &startpointTime, &startpointTemperature, eCookingStage_Startpoint );
// Operate the machine according to the current mode
switch (cookingStage) {
case eCookingStage_Startpoint: {
xBasicStageOperation( startpointTime, startpointTemperature, 0, eCookingStage_BetaGlucanase, false);
break;
}
case eStageMenu_BetaGlucanase: {
xStartStageInteractive( &betaGlucanaseTime, &betaGlucanaseTemperature, eCookingStage_BetaGlucanase );
case eCookingStage_BetaGlucanase: {
xBasicStageOperation( betaGlucanaseTime, betaGlucanaseTemperature, 3, eCookingStage_Debranching, true );
break;
}
case eStageMenu_Debranching: {
xStartStageInteractive( &debranchingTime, &debranchingTemperature, eCookingStage_Debranching );
case eCookingStage_Debranching: {
xBasicStageOperation( debranchingTime, debranchingTemperature, 3, eCookingStage_Proteolytic, true );
break;
}
case eStageMenu_Proteolytic: {
xStartStageInteractive( &proteolyticTime, &proteolyticTemperature, eCookingStage_Proteolytic );
case eCookingStage_Proteolytic: {
xBasicStageOperation( proteolyticTime, proteolyticTemperature, 3, eCookingStage_BetaAmylase, true );
break;
}
case eStageMenu_BetaAmylase: {
xStartStageInteractive( &betaAmylaseTime, &betaAmylaseTemperature, eCookingStage_BetaAmylase );
case eCookingStage_BetaAmylase: {
xBasicStageOperation( betaAmylaseTime, betaAmylaseTemperature, 4, eCookingStage_AlphaAmylase, true );
break;
}
case eStageMenu_AlphaAmylase: {
xStartStageInteractive( &alphaAmylaseTime, &alphaAmylaseTemperature, eCookingStage_AlphaAmylase );
case eCookingStage_AlphaAmylase: {
xBasicStageOperation( alphaAmylaseTime, alphaAmylaseTemperature, 2, eCookingStage_Mashout, true );
break;
}
case eStageMenu_Mashout: {
xStartStageInteractive( &mashoutTime, &mashoutTemperature, eCookingStage_Mashout );
case eCookingStage_Mashout: {
xBasicStageOperation( mashoutTime, mashoutTemperature, 1, eCookingStage_Recirculation, true );
break;
}
case eStageMenu_Recirculation: {
xStartStageInteractive( &recirculationTime, &recirculationTemperature, eCookingStage_Recirculation );
case eCookingStage_Recirculation: {
xBasicStageOperation( recirculationTime, recirculationTemperature, 1, eCookingStage_Sparge, true );
break;
}
case eStageMenu_Sparge: {
xStartStageInteractive( &spargeTime, &spargeTemperature, eCookingStage_Sparge );
case eCookingStage_Sparge: {
xBasicStageOperation( spargeTime, spargeTemperature, 3, eCookingStage_Boil, false );
break;
}
case eStageMenu_Boil: {
xStartStageInteractive( &boilTime, &boilTemperature, eCookingStage_Boil );
case eCookingStage_Boil: {
xBasicStageOperation( boilTime, boilTemperature, 2, eCookingStage_Cooling, false );
break;
}
case eStageMenu_Cooling: {
xStartStageInteractive( &coolingTime, &coolingTemperature, eCookingStage_Cooling );
case eCookingStage_Cooling: {
xBasicStageOperation( coolingTime, coolingTemperature, 0, eCookingStage_Done, false );
break;
}
case eStageMenu_Back: {
resetMenu( true );
case eCookingStage_Clean: {
xBasicStageOperation( cleaningTime, cleaningTemperature, 0, eCookingStage_Done, false );
break;
}
default: {
}
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;
}
}
}
// ##################################################### Menus ###################################################################
// *************************** MENU BASE *********************************
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: {
runMenuProcessor( &mdMainMenu );
break;
}
case eMenuType_BeerProfile: {
runMenuProcessor( &mdBeerProfileMenu );
break;
}
case eMenuType_Stage: {
runMenuProcessor( &mdStageMenu );
break;
}
case eMenuType_Malt: {
runMenuProcessor( &mdMaltMenu );
break;
}
case eMenuType_Settings: {
runMenuProcessor( &mdSettingsMenu );
break;
}
case eMenuType_StartFromStage: {
runMenuProcessor( &mdStartFromStageMenu );
break;
}
}
#ifdef DEBUG_OFF
if (debug_go) {
debugPrintVar("repaint", repaint);
}
eStartFromStageMenuSelection = eStageMenu_NULL;
#endif
}
// ************************ MENU SELECTIONS ******************************
void runMainMenuSelection() {
switch (mdMainMenu._selection) {
//switch (eMainMenuSelection) {
......@@ -1032,7 +994,7 @@ void runMainMenuSelection() {
case eMainMenu_GO_FROM_STAGE: {
eMenuType = eMenuType_StartFromStage;
repaint = true;
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eBeerProfileMenuPosition, MENU_SIZE_PROFILES_MENU - 1, 1, 1, 0 );
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, mdBeerProfileMenu._position, MENU_SIZE_PROFILES_MENU - 1, 1, 1, 0 );
break;
}
case eMainMenu_STOP: {
......@@ -1048,19 +1010,19 @@ void runMainMenuSelection() {
case eMainMenu_BeerProfile: {
eMenuType = eMenuType_BeerProfile;
repaint = true;
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eBeerProfileMenuPosition, MENU_SIZE_PROFILES_MENU - 1, 1, 1, 0 );
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, mdBeerProfileMenu._position, 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 );
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, mdStageMenu._position, 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 );
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, mdMaltMenu._position, MENU_SIZE_MALT_MENU - 1, 1, 1, 0 );
break;
}
case eMainMenu_Hops: {
......@@ -1078,7 +1040,7 @@ void runMainMenuSelection() {
case eMainMenu_Settings: {
eMenuType = eMenuType_Settings;
repaint = true;
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, eSettingsMenuPosition, MENU_SIZE_SETTINGS_MENU - 1, 1, 1, 0 );
xSetupRotaryEncoder( eRotaryEncoderMode_Menu, mdSettingsMenu._position, MENU_SIZE_SETTINGS_MENU - 1, 1, 1, 0 );
break;
}
case eMainMenu_Back: {
......@@ -1089,604 +1051,429 @@ void runMainMenuSelection() {
}
}
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();
void runStartFromStageSelection() {
switch (mdStartFromStageMenu._selection) {
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: {
}
}
mdStartFromStageMenu._selection = eStageMenu_NULL;
}
// 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;
void runBeerProfileSelection() {
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;
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;
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;
}
case eBeerProfileMenu_Back: {
resetMenu( true );
break;
}
default: {}
}
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;
mdBeerProfileMenu._selection = eBeerProfileMenu_NULL;
}
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;
void runStageSelection() {
switch (mdStageMenu._selection) {
case eStageMenu_Startpoint: {
runStageSelection_Generic( &startpointTime, &startpointTemperature );
break;
}
else {
difference = cookTemperature - tdown;
case eStageMenu_BetaGlucanase: {
runStageSelection_Generic( &betaGlucanaseTime, &betaGlucanaseTemperature );
break;
}
if (tbase > cookTemperature && (tbase >= (PUMP_TEMPERATURE_MAX_OPERATION - 2.0) || difference >= 5.0)) {
difference = cookTemperature - tbase;
case eStageMenu_Debranching: {
runStageSelection_Generic( &debranchingTime, &debranchingTemperature );
break;
}
if ( (tbase < cookTemperature) && (difference < (cookTemperature - tbase)) ) {
difference = cookTemperature - tbase;
case eStageMenu_Proteolytic: {
runStageSelection_Generic( &proteolyticTime, &proteolyticTemperature );
break;
}
} 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;
case eStageMenu_BetaAmylase: {
runStageSelection_Generic( &betaAmylaseTime, &betaAmylaseTemperature );
break;
}
case eStageMenu_AlphaAmylase: {
runStageSelection_Generic( &alphaAmylaseTime, &alphaAmylaseTemperature );
break;
}
case eStageMenu_Mashout: {
runStageSelection_Generic( &mashoutTime, &mashoutTemperature );
break;
}
case eStageMenu_Recirculation: {
runStageSelection_Generic( &recirculationTime, &recirculationTemperature );
break;
}
case eStageMenu_Sparge: {
runStageSelection_Generic( &spargeTime, &spargeTemperature );
break;
}
case eStageMenu_Boil: {
runStageSelection_Generic( &boilTime, &boilTemperature );
break;
}
case eStageMenu_Cooling: {
runStageSelection_Generic( &coolingTime, &coolingTemperature );
break;
}
case eStageMenu_Back: {
resetMenu( true );
break;
}
default: {}
}
mdStageMenu._selection = eStageMenu_NULL;
}
// 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;
}
}
} else {
if (difference <= 1.0) {
// pulse moderately at 1000 watt
if (cookTemperature > 99.0) {
wattage = 2000.0;
}
else {
wattage = 1000.0;
}
} else {
if (difference <= 3.0) {
// pulse hardly at 2000 watt
wattage = 2000.0;
void runSettingsSelection() {
switch (mdSettingsMenu._selection) {
case eSettingsMenu_Pump: {
// Stuff
if ( xSetGenericValue( iPumpSpeed ? 0 : 1, 0, 1, "pump", "bool" ) ) {
iPumpSpeed = PUMP_SPEED_MAX_MOSFET;
} else {
//pulse constantly at HEATING_ELEMENT_MAX_WATTAGE watt
wattage = HEATING_ELEMENT_MAX_WATTAGE;
iPumpSpeed = PUMP_SPEED_STOP_MOSFET;
}
analogWrite(PUMP_PIN, iPumpSpeed);
backToStatus();
break;
}
case eSettingsMenu_PT100_Element: {
backToStatus();
break;
}
case eSettingsMenu_PT100_Up: {
backToStatus();
break;
}
case eSettingsMenu_PT100_Down: {
backToStatus();
break;
}
case eSettingsMenu_Back: {
resetMenu( true );
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
if ( ulWattToWindowTime( wattage ) > (millis() - windowStartTime) ) {
digitalWrite(HEATING_ELEMENT_OUTPUT_PIN, HIGH);
bStatusElement = true;
} else {
digitalWrite(HEATING_ELEMENT_OUTPUT_PIN, LOW);
bStatusElement = false;
default: {}
}
#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
mdSettingsMenu._selection = eSettingsMenu_NULL;
}
void xPurgePump() {
for (int i = 0; i < 2; i++) {
analogWrite(PUMP_PIN, PUMP_SPEED_MAX_MOSFET); // analogWrite values from 0 to 255
delay(1000);
analogWrite(PUMP_PIN, PUMP_SPEED_STOP_MOSFET); // analogWrite values from 0 to 255
delay(1500);
void runMaltSelection() {
switch (mdMaltMenu._selection) {
case eMaltMenu_CastleMalting_Chteau_Pilsen_2RS: {
backToStatus();
break;
}
case eMaltMenu_CastleMalting_Wheat_Blanc: {
backToStatus();
break;
}
case eMaltMenu_Back: {
resetMenu( true );
break;
}
default: {}
}
mdMaltMenu._selection = eMaltMenu_NULL;
}
bool xRegulatePumpSpeed() {
// analogWrite(PUMP_PIN, iPumpSpeed); // analogWrite values from 0 to 255
// ************************ MENU HELPERS ******************************
void runMenuProcessor( MenuData *data ) {
data->_position = rotaryEncoderVirtualPosition; // Read position
if (basePT100.getCurrentTemperature() > PUMP_TEMPERATURE_MAX_OPERATION) {
analogWrite(PUMP_PIN, PUMP_SPEED_STOP_MOSFET); // analogWrite values from 0 to 255
data->_repaint = repaint; // Request repaint
repaint = displayGenericMenu( &lcd, data ); // Display menu
basePT100.setPumpStatus( false );
upPT100.setPumpStatus( false );
downPT100.setPumpStatus( false );
if ( gotButtonPress( ROTARY_ENCODER_SW_PIN ) ) { // Read selection
data->_selection = data->_position;
}
else {
analogWrite(PUMP_PIN, iPumpSpeed); // analogWrite values from 0 to 255
(data->_selectionFunction)(); // Run selection function
}
basePT100.setPumpStatus( true );
upPT100.setPumpStatus( true );
downPT100.setPumpStatus( true );
}
void runStageSelection_Generic( unsigned long * selectedStageTime, int *selectedStageTemperature) {
(*selectedStageTime) = getTimer( (*selectedStageTime) );
(*selectedStageTemperature) = xSetGenericValue( (*selectedStageTemperature), TEMPERATURE_MIN_VALUE, TEMPERATURE_MAX_VALUE, MENU_GLOBAL_STR_TEMPERATURE, MENU_GLOBAL_STR_CELSIUS );
backToStatus();
}
void xWarnClockEnded() {
sing(MELODY_SUPER_MARIO_START, PIEZO_PIN);
void xStartStageHeadless( eCookingStages nextStage, bool bPurgePump ) {
xStartStage( NULL, NULL, nextStage, bPurgePump, false, false, false );
}
void xWarnCookEnded() {
sing(MELODY_UNDERWORLD_SHORT, PIEZO_PIN);
void xStartStageInteractive( unsigned long *stageTime, int *stageTemperature, eCookingStages nextStage ) {
xStartStage( stageTime, stageTemperature, nextStage, true, true, true, true );
}
void xPrepareForStage( int stageTime, int stageTemperature, int stagePumpSpeed, eCookingStages stage ) {
#ifdef DEBUG_OFF
debugPrintFunction("xPrepareForStage");
debugPrintVar("cookingStage", stage);
#endif
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
// 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) {
#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;
}
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;
}
default: {
}
}
// 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;
}
case eCookingStage_BetaGlucanase: {
switch (beerProfile) {
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;
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;
}
default: {}
}
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);
say += String("g of Magnum 9.4\% and Styrian Golding 5\% ready.");
xWaitForAction("Hops", say);
break;
}
case eBeerProfile_IPA: {
String say = "Get ";
float hopAmount = 0.8 * ((float) finalYield);
say += String(hopAmount);
say += String("g of Chinook, Cascade and Styrian Golding ready.");
xWaitForAction("Hops", say);
break;
}
default: {
xWaitForAction("Hops", "Add the hops in the right order, at the right time.");
}
}
repaint = true;
// A basic operation for a basic stage
xPrepareForStage( boilTime, boilTemperature, PUMP_SPEED_MAX_MOSFET, eCookingStage_Boil );
break;
}
case eCookingStage_Cooling: {
// Make sure there is water
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;
}
case eCookingStage_Clean: {
// Make sure there is water
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;
}
case eCookingStage_Purge: {
// A basic operation for a basic stage
xPrepareForStage( 0, 0, PUMP_SPEED_MAX_MOSFET, eCookingStage_Purge );
xRegulatePumpSpeed();
break;
}
case eCookingStage_Done: {
// A basic operation for a basic stage
xPrepareForStage( 0, 0, PUMP_SPEED_STOP_MOSFET, eCookingStage_Done );
break;
}
}
}
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
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;
}
return;
}
void xManageMachineSystems() {
#ifdef DEBUG
Serial.print(millis());
Serial.print(",");
if (cooking) {
Serial.print("1");
}
else {
Serial.print("0");
if (bSetFinalYield) {
finalYield = xSetFinalYield( finalYield );
}
Serial.print(",");
Serial.print(cookTemperature);
Serial.print(",");
if (bStatusElement) {
Serial.print("1");
if (bSetTime) {
(*stageTime) = getTimer( clockCounter / 1000, (*stageTime) );
}
else {
Serial.print("0");
if (bSetTemperature) {
(*stageTemperature) = xSetTemperature( (*stageTemperature) );
}
Serial.print(",");
#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;
if (bPurgePump) {
xPurgePump();
}
// Operate the machine according to the current mode
switch (cookingStage) {
case eCookingStage_Startpoint: {
// A basic operation for a basic stage
xBasicStageOperation( startpointTime, startpointTemperature, 0, eCookingStage_BetaGlucanase, false);
break;
}
case eCookingStage_BetaGlucanase: {
// A basic operation for a basic stage
xBasicStageOperation( betaGlucanaseTime, betaGlucanaseTemperature, 3, eCookingStage_Debranching, true );
break;
}
case eCookingStage_Debranching: {
// A basic operation for a basic stage
xBasicStageOperation( debranchingTime, debranchingTemperature, 3, eCookingStage_Proteolytic, true );
break;
}
case eCookingStage_Proteolytic: {
// A basic operation for a basic stage
xBasicStageOperation( proteolyticTime, proteolyticTemperature, 3, eCookingStage_BetaAmylase, true );
break;
}
case eCookingStage_BetaAmylase: {
// A basic operation for a basic stage
xBasicStageOperation( betaAmylaseTime, betaAmylaseTemperature, 4, eCookingStage_AlphaAmylase, true );
break;
}
case eCookingStage_AlphaAmylase: {
// A basic operation for a basic stage
xBasicStageOperation( alphaAmylaseTime, alphaAmylaseTemperature, 2, eCookingStage_Mashout, true );
break;
}
case eCookingStage_Mashout: {
// A basic operation for a basic stage
xBasicStageOperation( mashoutTime, mashoutTemperature, 1, eCookingStage_Recirculation, true );
break;
}
case eCookingStage_Recirculation: {
// A basic operation for a basic stage
xBasicStageOperation( recirculationTime, recirculationTemperature, 1, eCookingStage_Sparge, true );
break;
}
case eCookingStage_Sparge: {
// A basic operation for a basic stage
xBasicStageOperation( spargeTime, spargeTemperature, 3, eCookingStage_Boil, false );
break;
}
case eCookingStage_Boil: {
// A basic operation for a basic stage
xBasicStageOperation( boilTime, boilTemperature, 2, eCookingStage_Cooling, false );
break;
}
case eCookingStage_Cooling: {
// A basic operation for a basic stage
xBasicStageOperation( coolingTime, coolingTemperature, 0, eCookingStage_Done, false );
break;
}
case eCookingStage_Clean: {
// A basic operation for a basic stage
xBasicStageOperation( cleaningTime, cleaningTemperature, 0, eCookingStage_Done, false );
break;
}
case eCookingStage_Purge: {
// A basic operation for a basic stage
//xBasicStageOperation( coolingTime, coolingTemperature, 1, eCookingStage_Done );
iPumpSpeed = PUMP_SPEED_MAX_MOSFET;
xRegulatePumpSpeed();
break;
}
case eCookingStage_Done: {
// Update cooking state
stopBrewing();
// Ask for screen refresh
repaint = true;
// Warn the user that the cooking is done
xWarnCookEnded();
break;
}
}
startBrewing();
xSetupStage( nextStage );
backToStatus();
}
// ##################################################### Menus ###################################################################
// #################################################### Helpers ##################################################################
......@@ -1708,7 +1495,6 @@ void resetMenu( boolean requestRepaintPaint ) {
}
// 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 );
}
......
......@@ -95,36 +95,45 @@
#define MENU_MAIN_INIT_POSITION eMainMenu_GO
#define MENU_MAIN_INIT_SELECTION eMainMenu_NULL
#define MENU_MAIN_INIT_REPAINT false
#define MENU_MAIN_FUNCTION &runMainMenuSelection
#define MENU_PROFILE_TITLE "Profile Menu"
#define MENU_PROFILE_DIALOG {"", "-> Basic ", "-> Trigo ", "-> IPA ", "-> Belga ", "-> Red ", "-> APA ", "-> Custom ", "-> Back " }
#define MENU_PROFILE_INIT_POSITION eBeerProfileMenu_Basic
#define MENU_PROFILE_INIT_SELECTION eBeerProfileMenu_NULL
#define MENU_PROFILE_INIT_REPAINT false
#define MENU_PROFILE_FUNCTION &runBeerProfileSelection
#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_INIT_POSITION eStageMenu_Startpoint
#define MENU_STAGE_INIT_SELECTION eStageMenu_NULL
#define MENU_STAGE_INIT_REPAINT false
#define MENU_STAGE_FUNCTION &runStageSelection
#define MENU_MALT_TITLE "Malt Menu"
#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_SELECTION eMaltMenu_NULL
#define MENU_MALT_INIT_REPAINT false
#define MENU_MALT_FUNCTION &runMaltSelection
#define MENU_SETTINGS_TITLE "Settings Menu"
#define MENU_SETTINGS_DIALOG {"", "-> PT100 Element", "-> PT100 Up ", "-> PT100 Down ", "-> Back " }
#define MENU_SETTINGS_INIT_POSITION eSettingsMenu_PT100_Element
#define MENU_SETTINGS_INIT_SELECTION eSettingsMenu_NULL
#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_DIALOG MENU_STAGE_DIALOG
#define MENU_START_INIT_POSITION MENU_STAGE_INIT_POSITION
#define MENU_START_INIT_SELECTION MENU_STAGE_INIT_SELECTION
#define MENU_START_INIT_REPAINT MENU_STAGE_INIT_REPAINT
#define MENU_START_FUNCTION &runStartFromStageSelection
// ++++++++++++++++++++++++ Serial Monotor ++++++++++++++++++++++++
#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