diff --git a/hot_fermentation.ino b/hot_fermentation.ino index 1097351..f0c93b9 100644 --- a/hot_fermentation.ino +++ b/hot_fermentation.ino @@ -59,13 +59,13 @@ double Kp = 2, Ki = 0.5, Kd = 0.25; PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT); // Timing variables -unsigned long phaseStartTime; -unsigned long totalStartTime; -unsigned long ssrLastSwitchTime; -unsigned long totalElapsedTime; -unsigned long totalProcessTime; -unsigned long finishTime = 0; -unsigned long currentTime = 0; +long phaseStartTime; +long totalStartTime; +long ssrLastSwitchTime; +long totalElapsedTime; +long totalProcessTime; +long finishTime = 0; +long currentTime = 0; bool isComplete = false; const int ssrSwitchInterval = 1000; // SSR switching interval in milliseconds @@ -81,41 +81,45 @@ void setup() { } void loop() { - enc1.tick(); // Mandatory encoder update function + enc1.tick(); if (inSelectionMode) { - handleProfileSelection(); // Handle profile selection mode + handleProfileSelection(); } else { - currentTime = millis(); - totalElapsedTime = (currentTime - totalStartTime) / 1000; // Total elapsed time in seconds - - getPhaseAndTemperature(totalElapsedTime); - - Input = thermocouple.readCelsius(); - if (isnan(Input)) { - Input = 0; - } - myPID.Compute(); - - // Switch SSR based on PID output and interval control - if (currentTime - ssrLastSwitchTime > ssrSwitchInterval) { - digitalWrite(ssrPin, Output > 0.5 ? HIGH : LOW); - ssrLastSwitchTime = currentTime; - } - - if (isComplete && currentPhase >= activeProfile.numPhases && !finishTime) { - finishTime = currentTime; - } - - // Display all phases and highlight the current one - printPhases(); - - oled.update(); - - delay(1000); // Update every second + handleExecution(); } } +void handleExecution() { + currentTime = millis(); + totalElapsedTime = (currentTime - totalStartTime) / 1000; // Total elapsed time in seconds + + getPhaseAndTemperature(); + + Input = thermocouple.readCelsius(); + if (isnan(Input)) { + Input = 0; + } + myPID.Compute(); + + // Switch SSR based on PID output and interval control + if (currentTime - ssrLastSwitchTime > ssrSwitchInterval) { + digitalWrite(ssrPin, Output > 0.5 ? HIGH : LOW); + ssrLastSwitchTime = currentTime; + } + + if (isComplete && currentPhase >= activeProfile.numPhases && !finishTime) { + finishTime = currentTime; + } + + // Display all phases and highlight the current one + printPhases(); + + oled.update(); + + delay(1000); // Update every second +} + void handleProfileSelection() { bool click = enc1.isClick(); @@ -175,8 +179,8 @@ void calculateTotalTime() { } } -void getPhaseAndTemperature(unsigned long elapsedSeconds) { - unsigned long accumulatedTime = 0; +void getPhaseAndTemperature() { + long accumulatedTime = 0; for (int i = 0; i < activeProfile.numPhases; i++) { int phaseDuration = activeProfile.phases[i].duration * 60; @@ -188,11 +192,12 @@ void getPhaseAndTemperature(unsigned long elapsedSeconds) { int tempDiff = abs(targetTemp - previousTemp); int transitionDuration = tempDiff * 60 * activeProfile.transitionMinutesPerDegree; - if (elapsedSeconds < accumulatedTime + transitionDuration) { + if (totalElapsedTime < accumulatedTime + transitionDuration) { isInTransition = true; currentPhase = i - 1; // Keep currentPhase as the previous phase - int timeInTransition = elapsedSeconds - accumulatedTime; + int timeInTransition = totalElapsedTime - accumulatedTime; Setpoint = previousTemp + (double)timeInTransition / (60 * activeProfile.transitionMinutesPerDegree) * (targetTemp > previousTemp ? 1 : -1); + phaseStartTime = totalStartTime + accumulatedTime * 1000; // Set phase start time return; } @@ -200,10 +205,11 @@ void getPhaseAndTemperature(unsigned long elapsedSeconds) { } // Check if we're within the current phase - if (elapsedSeconds < accumulatedTime + phaseDuration) { + if (totalElapsedTime < accumulatedTime + phaseDuration) { isInTransition = false; currentPhase = i; Setpoint = activeProfile.phases[i].temperature; + phaseStartTime = totalStartTime + accumulatedTime * 1000; // Set phase start time return; } @@ -215,8 +221,10 @@ void getPhaseAndTemperature(unsigned long elapsedSeconds) { Setpoint = 45; // Default to 45°C after completion isInTransition = false; isComplete = true; // Mark the process as complete + phaseStartTime = totalStartTime + accumulatedTime * 1000; // Set phase start time to the end } + void printPhases() { oled.clear(); @@ -251,7 +259,7 @@ void printPhases() { oled.invertText(true); // Invert text for the current phase oled.setCursor(0, i + 2); // Set cursor to the row corresponding to the phase - unsigned long timeRemaining = (activeProfile.phases[i].duration * 60) - ((currentTime - phaseStartTime) / 1000); + long timeRemaining = (activeProfile.phases[i].duration * 60) - ((currentTime - phaseStartTime) / 1000); formatTime(timeRemaining, timeBuffer); oled.print(i + 1); oled.print(". ");