diff --git a/hot_fermentation.ino b/hot_fermentation.ino index 3cea619..d826a0d 100644 --- a/hot_fermentation.ino +++ b/hot_fermentation.ino @@ -49,7 +49,7 @@ Profile profiles[] = { {"Lentils gradual", 10, {{48, 120}, {80, 60}}, 2}, {"Wheat", 3, {{47, 60}, {53, 60}, {65, 20}, {72, 20}, {85, 20}}, 5}, {"Sous Vide 55+120", 1, {{55, 30}, {85, 120}}, 2}, - {"Sous Vide 46", 0, {{46, 60}}, 1}, + {"46 (45)", 0, {{46, 45}}, 1}, {"Test", 1, {{49, 1}, {51, 1}}, 2}, }; @@ -91,6 +91,7 @@ uint32_t timer = 0; uint32_t timerSSR = 0; #define T_PERIOD_SSR 500 // period of heater handling +#define PARTS 10 void setup() { pinMode(ssrPin, OUTPUT); @@ -113,13 +114,12 @@ void loop() { handleEncoder(); } handleExecution(); - handleHeater(); + handleHeaterAdv(); } -void handleHeater() { +void handleHeaterSimple() { long time = millis(); static int currentPart = 0; - #define PARTS 4 if (time - timerSSR < T_PERIOD_SSR) { return; @@ -150,6 +150,50 @@ void handleHeater() { } } +void handleHeaterAdv() { + long time = millis(); + static int currentPart = 0; + static bool states[PARTS]; + + if (time - timerSSR < T_PERIOD_SSR) { + return; + } + if (inSelectionMode) { + digitalWrite(ssrPin, LOW); + return; + } + timerSSR = time; + + int current = Output * PARTS; + + int last = 0; + for (int i = 1; i < PARTS; i++) { + last += states[i] ? 1 : 0; + if (i) { + states[i-1] = states[i]; + } + } + bool next = current > last ? true : false; + states[PARTS-1] = next; + + oled.setCursor(128-6*PARTS, 7); + sprintf(timeBuffer, "%3d", (int)(Output*100)); + char symbol; + for (int i = 0; i < PARTS; i++) { + int index = i - (PARTS - 3); + symbol = index < 0 ? ' ' : timeBuffer[index]; + oled.invertText(states[i]); + oled.print(symbol); + oled.invertText(false); + } + + digitalWrite(ssrPin, next); + currentPart++; + if (currentPart >= PARTS) { + currentPart = 0; + } +} + void handleEncoder() { if (inSelectionMode) { handleProfileSelection(); @@ -203,6 +247,22 @@ void handleExecution() { printPhases(); } +void startExecution() { + activeProfile = profiles[activeProfileIndex]; + inSelectionMode = false; // Switch to execution mode + phaseStartTime = totalStartTime = millis(); // Start the timer + totalElapsedTime = 0; + myPID.SetMode(AUTOMATIC); + myPID.SetOutputLimits(0, 1); // SSR is either ON or OFF + // digitalWrite(ssrPin, HIGH); // Start with heater on + ssrLastSwitchTime = millis(); + calculateTotalTime(); + getPhaseAndTemperature(); + writeEEPROM(); + oled.clear(); + isComplete = false; +} + void handleProfileSelection() { if (!isClick && !isLeft && !isRight) { return; @@ -220,18 +280,7 @@ void handleProfileSelection() { // Start the selected profile on button press if (isClick) { activeProfileIndex = selectedProfileIndex; - activeProfile = profiles[activeProfileIndex]; - inSelectionMode = false; // Switch to execution mode - phaseStartTime = totalStartTime = millis(); // Start the timer - totalElapsedTime = 0; - myPID.SetMode(AUTOMATIC); - myPID.SetOutputLimits(0, 1); // SSR is either ON or OFF - // digitalWrite(ssrPin, HIGH); // Start with heater on - ssrLastSwitchTime = millis(); - calculateTotalTime(); - getPhaseAndTemperature(); - writeEEPROM(); - oled.clear(); + startExecution(); } }