initial
This commit is contained in:
commit
d52e559ef4
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
*.swp
|
||||||
127
hot_fermentation.ino
Normal file
127
hot_fermentation.ino
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
#include <LiquidCrystal_I2C.h>
|
||||||
|
#include <max6675.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <PID_v1.h>
|
||||||
|
|
||||||
|
// MAX6675 configuration
|
||||||
|
int max_SO = 12;
|
||||||
|
int max_CS = 10;
|
||||||
|
int max_SCK = 13;
|
||||||
|
MAX6675 thermocouple(max_SCK, max_CS, max_SO);
|
||||||
|
|
||||||
|
// LCD configuration via I2C
|
||||||
|
LiquidCrystal_I2C lcd(0x27, 16, 2); // Set the LCD I2C address
|
||||||
|
|
||||||
|
// SSR pin configuration
|
||||||
|
const int ssrPin = 7;
|
||||||
|
|
||||||
|
// Process phases (temperatures in Celsius and duration in minutes)
|
||||||
|
|
||||||
|
// const int temperatures[] = {49, 51, 55, 45};
|
||||||
|
// const int phaseDurations[] = {30, 30, 30, 30}; // Individual durations for each phase in minutes
|
||||||
|
// const int numPhases = 3;
|
||||||
|
|
||||||
|
|
||||||
|
// const int temperatures[] = {47, 55, 65, 72, 85, 0};
|
||||||
|
// const int phaseDurations[] = {20, 20, 20, 20, 20, 5}; // Individual durations for each phase in minutes
|
||||||
|
// const int numPhases = 5;
|
||||||
|
|
||||||
|
// const int temperatures[] = {85, 50};
|
||||||
|
// const int phaseDurations[] = {120, 120}; // Individual durations for each phase in minutes
|
||||||
|
// const int numPhases = 1;
|
||||||
|
|
||||||
|
const int temperatures[] = {47, 53, 65, 72, 90, 50};
|
||||||
|
const int phaseDurations[] = {120, 120, 150, 60, 105, 60}; // Individual durations for each phase in minutes
|
||||||
|
const int numPhases = 5;
|
||||||
|
|
||||||
|
// const int temperatures[] = {55, 65, 72, 80, 90, 10};
|
||||||
|
// const int phaseDurations[] = {60, 120, 120, 120, 30, 100}; // Individual durations for each phase in minutes
|
||||||
|
// const int numPhases = 5;
|
||||||
|
|
||||||
|
|
||||||
|
// PID Control variables
|
||||||
|
double Setpoint, Input, Output;
|
||||||
|
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;
|
||||||
|
const int ssrSwitchInterval = 1000; // SSR switching interval in milliseconds
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
pinMode(ssrPin, OUTPUT);
|
||||||
|
Serial.begin(9600);
|
||||||
|
lcd.init();
|
||||||
|
lcd.backlight();
|
||||||
|
lcd.print("Starting...");
|
||||||
|
delay(2000);
|
||||||
|
|
||||||
|
// Begin the first phase
|
||||||
|
phaseStartTime = totalStartTime = millis();
|
||||||
|
Setpoint = temperatures[0];
|
||||||
|
myPID.SetMode(AUTOMATIC);
|
||||||
|
myPID.SetOutputLimits(0, 1); // SSR is either ON or OFF
|
||||||
|
digitalWrite(ssrPin, HIGH); // Start with heater on
|
||||||
|
ssrLastSwitchTime = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
static int currentPhase = 0;
|
||||||
|
Input = (int) thermocouple.readCelsius(); // Cast to integer for display and control
|
||||||
|
unsigned long currentTime = millis();
|
||||||
|
|
||||||
|
myPID.Compute();
|
||||||
|
|
||||||
|
// Switch SSR based on PID output and interval control
|
||||||
|
if (currentTime - ssrLastSwitchTime > ssrSwitchInterval) {
|
||||||
|
digitalWrite(ssrPin, Output > 0.5 ? HIGH : LOW);
|
||||||
|
ssrLastSwitchTime = currentTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display time calculations
|
||||||
|
unsigned long totalElapsedTime = (currentTime - totalStartTime) / 1000; // Total elapsed time in seconds
|
||||||
|
unsigned long totalProcessTime = 0;
|
||||||
|
for (int i = 0; i < numPhases; i++) {
|
||||||
|
totalProcessTime += phaseDurations[i] * 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the phase duration is complete
|
||||||
|
if ((currentTime - phaseStartTime) / 1000 >= phaseDurations[currentPhase] * 60) {
|
||||||
|
currentPhase++;
|
||||||
|
if (currentPhase >= numPhases) {
|
||||||
|
lcd.clear();
|
||||||
|
lcd.print("Complete");
|
||||||
|
digitalWrite(ssrPin, LOW); // Turn off the heater
|
||||||
|
return; // Stop further execution
|
||||||
|
}
|
||||||
|
phaseStartTime = currentTime; // Reset the start time for the new phase
|
||||||
|
Setpoint = temperatures[currentPhase];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display data on the LCD
|
||||||
|
lcd.clear();
|
||||||
|
lcd.setCursor(0, 0);
|
||||||
|
lcd.print(formatTime(totalElapsedTime));
|
||||||
|
lcd.print(" (");
|
||||||
|
lcd.print(formatTime(totalProcessTime));
|
||||||
|
lcd.print(")");
|
||||||
|
|
||||||
|
lcd.setCursor(0, 1);
|
||||||
|
lcd.print(currentPhase + 1);
|
||||||
|
lcd.print(". ");
|
||||||
|
lcd.print((int)Input);
|
||||||
|
lcd.print("C ");
|
||||||
|
lcd.print((int)Setpoint);
|
||||||
|
lcd.print("C ");
|
||||||
|
lcd.print(formatTime((phaseDurations[currentPhase] * 60) - ((currentTime - phaseStartTime) / 1000)));
|
||||||
|
|
||||||
|
delay(1000); // Update every second
|
||||||
|
}
|
||||||
|
|
||||||
|
String formatTime(long seconds) {
|
||||||
|
long mins = seconds / 60;
|
||||||
|
int secs = seconds % 60;
|
||||||
|
return (mins < 10 ? "0" : "") + String(mins) + ":" + (secs < 10 ? "0" : "") + String(secs);
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user