Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor brew detection and brew handling #512

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions data/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const vueApp = Vue.createApp({
// post parameter array the same as if it was posted from a form (the values are already updated
// from the v-model bindings)
var formBody = [];

this.parameters.forEach(param => {
var encodedKey = encodeURIComponent(param.name);
var encodedValue = encodeURIComponent(param.value);
Expand All @@ -41,7 +41,7 @@ const vueApp = Vue.createApp({
cache: 'no-cache',
body: formBody
};

this.isPostingForm = true

fetch("/parameters", requestOptions)
Expand Down Expand Up @@ -74,13 +74,14 @@ const vueApp = Vue.createApp({
sectionName(sectionId) {
const sectionNames = {
0: 'PID Parameters',
1: 'Temperature and Preinfusion',
2: 'Brew Detection and Brew PID Parameters',
1: 'Temperature',
2: 'Brew PID Parameters',
3: 'Brew Control',
4: 'Scale Parameters',
5: 'Power Settings'
5: 'Display Settings',
6: 'Power Settings'
}

return sectionNames[sectionId]
},

Expand Down
517 changes: 288 additions & 229 deletions src/brewHandler.h

Large diffs are not rendered by default.

103 changes: 51 additions & 52 deletions src/defaults.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,7 @@ int writeSysParamsToStorage(void);
#define AGGBTN 0 // PID Tn (brew detection phase)
#define AGGBTV 20 // PID Tv (brew detection phase)
#define BREW_TIME 25 // brew time in seconds (only used if pump is being controlled)
#define BREW_SW_TIME 25 // keep brew PID params for this many seconds after detection (only for software BD)
#define BREW_PID_DELAY 10 // delay until enabling PID controller during brew (no heating during this time)
#define BD_SENSITIVITY 120 // brew detection sensitivity, be careful: if too low, then there is the risk of wrong brew detection and rising temperature
#define PRE_INFUSION_TIME 2 // pre-infusion time in seconds
#define PRE_INFUSION_PAUSE_TIME 5 // pre-infusion pause time in seconds
#define SCALE_WEIGHTSETPOINT 30 // Target weight in grams
Expand All @@ -49,54 +47,55 @@ int writeSysParamsToStorage(void);
#define BACKFLUSH_CYCLES 5 // number of cycles the backflush should run
#define BACKFLUSH_FILL_TIME 5 // time in seconds the pump is running during backflush
#define BACKFLUSH_FLUSH_TIME 10 // time in seconds the 3-way valve is open during backflush
#define FEATURE_BREW_CONTROL 0 // enables function to control pump and solenoid valve
#define FEATURE_SHOT_TIMER 0 // enables full screen shot timer
#define SHOT_TIMER_DISPLAY_DELAY 3 // time in seconds that shot timer will be shown after brew finished
#define FEATURE_HEATING_LOGO 1 // enables full screen logo if mashine is heating
#define FEATURE_PID_OFF_LOGO 1 // enables full screen logo if pid is switched off

#define PID_KP_START_MIN 0
#define PID_KP_START_MAX 999
#define PID_TN_START_MIN 0
#define PID_TN_START_MAX 999
#define PID_KP_REGULAR_MIN 0
#define PID_KP_REGULAR_MAX 999
#define PID_TN_REGULAR_MIN 0
#define PID_TN_REGULAR_MAX 999
#define PID_TV_REGULAR_MIN 0
#define PID_TV_REGULAR_MAX 999
#define PID_I_MAX_REGULAR_MIN 0
#define PID_I_MAX_REGULAR_MAX 999
#define PID_KP_BD_MIN 0
#define PID_KP_BD_MAX 999
#define PID_TN_BD_MIN 0
#define PID_TN_BD_MAX 999
#define PID_TV_BD_MIN 0
#define PID_TV_BD_MAX 999
#define BREW_SETPOINT_MIN 20
#define BREW_SETPOINT_MAX 110
#define STEAM_SETPOINT_MIN 100
#define STEAM_SETPOINT_MAX 140
#define BREW_TEMP_OFFSET_MIN 0
#define BREW_TEMP_OFFSET_MAX 20
#define BREW_TEMP_TIME_MIN 1
#define BREW_TEMP_TIME_MAX 180
#define BREW_TIME_MIN 0
#define BREW_TIME_MAX 180
#define BREW_PID_DELAY_MIN 0
#define BREW_PID_DELAY_MAX 60
#define BREW_SW_TIME_MIN 1
#define BREW_SW_TIME_MAX 180
#define BD_THRESHOLD_MIN 0
#define BD_THRESHOLD_MAX 999
#define PRE_INFUSION_TIME_MIN 0
#define PRE_INFUSION_TIME_MAX 60
#define PRE_INFUSION_PAUSE_MIN 0
#define PRE_INFUSION_PAUSE_MAX 60
#define WEIGHTSETPOINT_MIN 0
#define WEIGHTSETPOINT_MAX 500
#define PID_KP_STEAM_MIN 0
#define PID_KP_STEAM_MAX 500
#define STANDBY_MODE_TIME_MIN 30
#define STANDBY_MODE_TIME_MAX 120
#define BACKFLUSH_CYCLES_MIN 2
#define BACKFLUSH_CYCLES_MAX 20
#define BACKFLUSH_FILL_TIME_MIN 5
#define BACKFLUSH_FILL_TIME_MAX 20
#define BACKFLUSH_FLUSH_TIME_MIN 5
#define BACKFLUSH_FLUSH_TIME_MAX 20
#define PID_KP_START_MIN 0
#define PID_KP_START_MAX 999
#define PID_TN_START_MIN 0
#define PID_TN_START_MAX 999
#define PID_KP_REGULAR_MIN 0
#define PID_KP_REGULAR_MAX 999
#define PID_TN_REGULAR_MIN 0
#define PID_TN_REGULAR_MAX 999
#define PID_TV_REGULAR_MIN 0
#define PID_TV_REGULAR_MAX 999
#define PID_I_MAX_REGULAR_MIN 0
#define PID_I_MAX_REGULAR_MAX 999
#define PID_KP_BD_MIN 0
#define PID_KP_BD_MAX 999
#define PID_TN_BD_MIN 0
#define PID_TN_BD_MAX 999
#define PID_TV_BD_MIN 0
#define PID_TV_BD_MAX 999
#define BREW_SETPOINT_MIN 20
#define BREW_SETPOINT_MAX 110
#define STEAM_SETPOINT_MIN 100
#define STEAM_SETPOINT_MAX 140
#define BREW_TEMP_OFFSET_MIN 0
#define BREW_TEMP_OFFSET_MAX 20
#define BREW_TIME_MIN 0
#define BREW_TIME_MAX 180
#define BREW_PID_DELAY_MIN 0
#define BREW_PID_DELAY_MAX 60
#define PRE_INFUSION_TIME_MIN 0
#define PRE_INFUSION_TIME_MAX 60
#define PRE_INFUSION_PAUSE_MIN 0
#define PRE_INFUSION_PAUSE_MAX 60
#define WEIGHTSETPOINT_MIN 0
#define WEIGHTSETPOINT_MAX 500
#define PID_KP_STEAM_MIN 0
#define PID_KP_STEAM_MAX 500
#define STANDBY_MODE_TIME_MIN 30
#define STANDBY_MODE_TIME_MAX 120
#define BACKFLUSH_CYCLES_MIN 2
#define BACKFLUSH_CYCLES_MAX 20
#define BACKFLUSH_FILL_TIME_MIN 5
#define BACKFLUSH_FILL_TIME_MAX 20
#define BACKFLUSH_FLUSH_TIME_MIN 5
#define BACKFLUSH_FLUSH_TIME_MAX 20
#define SHOT_TIMER_DISPLAY_DELAY_MIN 0
#define SHOT_TIMER_DISPLAY_DELAY_MAX 60
77 changes: 26 additions & 51 deletions src/display/displayCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,66 +234,41 @@ void displayLogo(String displaymessagetext, String displaymessagetext2) {
}

/**
* @brief display shot timer
* @brief display shot and flush timer
*/
bool displayShottimer() {
if (FEATURE_SHOTTIMER == 0) {
if (featureShotTimer == 0) {
return false;
}

if (machineState == kBrew || brewSwitchState == kBrewSwitchFlushOff) {
if (machineState == kBrew || (millis() - lastBrewTimeMillis) < (shotTimerDisplayDelay * 1000) || machineState == kManualFlush) {
u8g2.clearBuffer();

if (brewSwitchState != kBrewSwitchFlushOff) {
if (machineState != kManualFlush) {
u8g2.drawXBMP(-1, 11, Brew_Cup_Logo_width, Brew_Cup_Logo_height, Brew_Cup_Logo);
#if (FEATURE_SCALE == 1)
u8g2.setFont(u8g2_font_profont22_tf);
u8g2.setCursor(64, 15);
u8g2.print(timeBrewed / 1000, 1);
u8g2.print("s");
u8g2.setCursor(64, 38);
u8g2.print(weightBrewed, 1);
u8g2.print("g");
u8g2.setFont(u8g2_font_profont11_tf);
#else
displayBrewtime(48, 25, timeBrewed);
#endif
}
else {
u8g2.drawXBMP(0, 12, Manual_Flush_Logo_width, Manual_Flush_Logo_height, Manual_Flush_Logo);
displayBrewtime(48, 25, timeBrewed);
}

#if (FEATURE_SCALE == 1)
u8g2.setFont(u8g2_font_profont22_tf);
u8g2.setCursor(64, 15);
u8g2.print(timeBrewed / 1000, 1);
u8g2.print("s");
u8g2.setCursor(64, 38);
u8g2.print(weightBrew, 1);
u8g2.print("g");
u8g2.setFont(u8g2_font_profont11_tf);
#else
displayBrewtime(48, 25, timeBrewed);
#endif

displayWaterIcon(119, 1);
u8g2.sendBuffer();
return true;
}

/* if the totalBrewTime is reached automatically,
* nothing should be done, otherwise wrong time is displayed
* because the switch is pressed later than totalBrewTime
*/
else if (machineState == kShotTimerAfterBrew && brewSwitchState != kBrewSwitchFlushOff) {
u8g2.clearBuffer();
u8g2.drawXBMP(-1, 11, Brew_Cup_Logo_width, Brew_Cup_Logo_height, Brew_Cup_Logo);

#if (FEATURE_SCALE == 1)
u8g2.setFont(u8g2_font_profont22_tf);
u8g2.setCursor(64, 15);
u8g2.print(lastBrewTime / 1000, 1);
u8g2.print("s");
u8g2.setCursor(64, 38);
u8g2.print(weightBrew, 1);
u8g2.print("g");
u8g2.setFont(u8g2_font_profont11_tf);
#else
displayBrewtime(48, 25, lastBrewTime);
#endif

displayWaterIcon(119, 1);
u8g2.sendBuffer();
return true;
}
return false;
}

Expand All @@ -302,7 +277,7 @@ bool displayShottimer() {
*/
bool displayMachineState() {
// Show the heating logo when we are in regular PID mode and more than 5degC below the set point
if (FEATURE_HEATINGLOGO > 0 && machineState == kPidNormal && (setpoint - temperature) > 5. && brewSwitchState != kBrewSwitchFlushOff) {
if (featureHeatingLogo > 0 && machineState == kPidNormal && (setpoint - temperature) > 5.) {
// For status info
u8g2.clearBuffer();

Expand All @@ -318,7 +293,7 @@ bool displayMachineState() {
return true;
}
// Offline logo
else if (FEATURE_PIDOFF_LOGO == 1 && machineState == kPidDisabled) {
else if (featurePidOffLogo == 1 && machineState == kPidDisabled) {
u8g2.clearBuffer();
u8g2.drawXBMP(38, 0, Off_Logo_width, Off_Logo_height, Off_Logo);
u8g2.setCursor(0, 55);
Expand All @@ -328,7 +303,7 @@ bool displayMachineState() {
u8g2.sendBuffer();
return true;
}
else if (FEATURE_PIDOFF_LOGO == 1 && machineState == kStandby) {
else if (featurePidOffLogo == 1 && machineState == kStandby) {
u8g2.clearBuffer();
u8g2.drawXBMP(38, 0, Off_Logo_width, Off_Logo_height, Off_Logo);
u8g2.setCursor(36, 55);
Expand All @@ -339,7 +314,7 @@ bool displayMachineState() {
return true;
}
// Steam
else if (machineState == kSteam && brewSwitchState != kBrewSwitchFlushOff) {
else if (machineState == kSteam) {
u8g2.clearBuffer();
u8g2.drawXBMP(-1, 12, Steam_Logo_width, Steam_Logo_height, Steam_Logo);

Expand All @@ -350,7 +325,7 @@ bool displayMachineState() {
return true;
}
// Water empty
else if (machineState == kWaterEmpty && brewSwitchState != kBrewSwitchFlushOff) {
else if (machineState == kWaterEmpty) {
u8g2.clearBuffer();
u8g2.drawXBMP(45, 0, Water_Empty_Logo_width, Water_Empty_Logo_height, Water_Empty_Logo);
u8g2.setFont(u8g2_font_profont11_tf);
Expand All @@ -364,16 +339,16 @@ bool displayMachineState() {
u8g2.setCursor(2, 10);
u8g2.print("Backflush");

switch (backflushState) {
case kBackflushWaitBrewswitchOn:
switch (currBackflushState) {
case kBackflushIdle:
u8g2.setFont(u8g2_font_profont12_tf);
u8g2.setCursor(4, 37);
u8g2.print(langstring_backflush_press);
u8g2.setCursor(4, 50);
u8g2.print(langstring_backflush_start);
break;

case kBackflushWaitBrewswitchOff:
case kBackflushFinished:
u8g2.setFont(u8g2_font_profont12_tf);
u8g2.setCursor(4, 37);
u8g2.print(langstring_backflush_press);
Expand All @@ -384,7 +359,7 @@ bool displayMachineState() {
default:
u8g2.setFont(u8g2_font_fub17_tf);
u8g2.setCursor(42, 42);
u8g2.print(currBackflushCycles + 1, 0);
u8g2.print(currBackflushCycles, 0);
u8g2.print("/");
u8g2.print(backflushCycles, 0);
break;
Expand Down
6 changes: 3 additions & 3 deletions src/display/displayRotateUpright.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ void displayEmergencyStop(void) {
* @brief display shot timer
*/
bool displayShottimer() {
if (((timeBrewed > 0 && FEATURE_BREWCONTROL == 0) || (FEATURE_BREWCONTROL > 0 && currBrewState > kBrewIdle && currBrewState <= kBrewFinished)) && FEATURE_SHOTTIMER == 1) {
if (((timeBrewed > 0 && featureBrewControl == 0) || (featureBrewControl > 0 && currBrewState > kBrewIdle && currBrewState <= kBrewFinished)) && featureShotTimer == 1) {
u8g2.clearBuffer();

// draw temp icon
Expand All @@ -100,8 +100,8 @@ bool displayShottimer() {
u8g2.sendBuffer();
return true;
}
else if (FEATURE_SHOTTIMER == 1 && millis() >= lastBrewTimeMillis && // directly after creating lastbrewTimeMillis (happens when turning off the brew switch, case 43 in the code) should be started
lastBrewTimeMillis + SHOTTIMERDISPLAYDELAY >= millis() && // should run until millis() has caught up with SHOTTIMERDISPLAYDELAY, this can be used to control the display duration
else if (featureShotTimer == 1 && millis() >= lastBrewTimeMillis && // directly after creating lastbrewTimeMillis (happens when turning off the brew switch, case 43 in the code) should be started
lastBrewTimeMillis + (shotTimerDisplayDelay * 1000) >= millis() && // should run until millis() has caught up with shotTimerDisplayDelay, this can be used to control the display duration
lastBrewTimeMillis < totalBrewTime) // if the totalBrewTime is reached automatically, nothing should be done, otherwise wrong time will be displayed because switch is pressed later than totalBrewTime
{
u8g2.clearBuffer();
Expand Down
47 changes: 31 additions & 16 deletions src/display/displayTemplateMinimal.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,26 +78,41 @@ void printScreen() {

u8g2.setFont(u8g2_font_profont11_tf);

if (isBrewDetected == 1 && currBrewState == kBrewIdle) {
u8g2.setCursor(38, 44);
u8g2.print("BD: ");
u8g2.print((millis() - timeBrewDetection) / 1000, 1);
u8g2.print("/");
u8g2.print(brewtimesoftware, 0);
}
else {
u8g2.setCursor(34, 44);
u8g2.print(langstring_brew);
u8g2.print(timeBrewed / 1000, 0);
u8g2.print("/");
// Brew time
#if (FEATURE_BREWSWITCH == 1)
if (featureBrewControl) {
// Shown brew time while machine is brewing and after the brewing during shotTimerDisplayDelay
if (machineState == kBrew || (millis() - lastBrewTimeMillis) < (shotTimerDisplayDelay * 1000)) {
u8g2.setCursor(34, 44);
u8g2.print(langstring_brew);
u8g2.print(timeBrewed / 1000, 0);
u8g2.print("/");
u8g2.print(totalBrewTime / 1000, 0);
}

// Flush time

if (FEATURE_BREWCONTROL == 0) {
u8g2.print(brewtimesoftware, 0);
// Shown flush time while machine is flushing
if (machineState == kManualFlush) {
u8g2.setDrawColor(0);
u8g2.drawBox(34, 44, 100, 15);
u8g2.setDrawColor(1);
u8g2.setCursor(34, 44);
u8g2.print(langstring_manual_flush);
u8g2.print(timeBrewed / 1000, 0);
}
else {
u8g2.print(totalBrewTime / 1000, 0);
}

// Brew Timer with optocoupler
else {
// Shown brew time while machine is brewing and after the brewing during shotTimerDisplayDelay
if (machineState == kBrew || (millis() - lastBrewTimeMillis) < (shotTimerDisplayDelay * 1000)) {
u8g2.setCursor(34, 44);
u8g2.print(langstring_brew);
u8g2.print(timeBrewed / 1000, 0);
}
}
#endif

// Show heater output in %
displayProgressbar(pidOutput / 10, 15, 60, 100);
Expand Down
Loading
Loading