From 18c43187cb268c1e527c8245de492bba17b433d4 Mon Sep 17 00:00:00 2001 From: Chris Giacofei Date: Tue, 18 Jan 2022 19:45:05 -0500 Subject: [PATCH] Initial junk to get temp control working. Totally not working yet, just getting it pushed to the remote --- boil_kettle/boil_kettle.ino | 46 ++++++++++++++++++----- boil_kettle/thermoControl.cpp | 71 +++++++++++++++++++++++++++++++++++ boil_kettle/thermoControl.h | 33 ++++++++++++++++ 3 files changed, 141 insertions(+), 9 deletions(-) create mode 100644 boil_kettle/thermoControl.cpp create mode 100644 boil_kettle/thermoControl.h diff --git a/boil_kettle/boil_kettle.ino b/boil_kettle/boil_kettle.ino index 269a964..89c5f19 100644 --- a/boil_kettle/boil_kettle.ino +++ b/boil_kettle/boil_kettle.ino @@ -3,7 +3,7 @@ #include #include -// Additoinal Libraries +// Additional Libraries #include #include #include @@ -15,17 +15,28 @@ #include "config.h" #include "button.h" #include "slowPWM.h" +#include "thermoControl.h" // Global variables. -byte KettleDuty = 0; -bool KettleOn = false; +uint8_t KettleDuty = 0; +double KettleTemp; +uint8_t KettleSetpoint; +modes KettleMode = OFF; + +/* Defined in config.h for now */ +// uint8_t ThreshPWR = 5; +// double Hysteresis = 1; // User I/O objects. Button Enter; -slowPWM boilPWM; MD_REncoder rotary = MD_REncoder(encoderDT, encoderCLK); LiquidCrystal_I2C lcd(0x27,20,4); +// Internal I/O +Adafruit_MAX31865 KettleThermo = Adafruit_MAX31865(10); +slowPWM boilPWM; +thermoControl KettleController = thermoControl(&KettleTemp, &KettleSetpoint, &KettleDuty, &ThreshPWR, &Hysteresis); + EthernetClient net; MQTTClient mqtt_client; @@ -34,13 +45,26 @@ unsigned long lastRun = 0; // Return a character array to represent the // On/Off state of the kettle. char* KettleState() { - if (KettleOn) { - return (char*)"On"; + if (KettleMode == MANUAL) { + return (char*)"Manual"; + } else if (KettleMode == AUTOMATIC) { + return (char*)"Auto"; } else { return (char*)"Off"; } } +char* ShowKettleSetting() { + char* LCD_Line; + if (KettleMode == MANUAL) { + return sprintf(LCD_Line, "Kettle Power: %03d%", KettleDuty); + } else if (KettleMode == AUTOMATIC) { + return sprintf(LCD_Line, "Kettle Temp: %03dF", KettleSetpoint); + } else { + return (char[])" Off "; + } +} + // Interrupt function to run when encoder is turned. // // Increases/decreases the kettle output to a max @@ -65,7 +89,7 @@ void doEncoder() // LCD menu setup. LiquidLine KettleState_line(0, 0, "Boil Kettle ", KettleState); -LiquidLine kettle_power_line(0, 1, "Kettle Power % ", KettleDuty); +LiquidLine kettle_power_line(0, 1, ShowKettleSetting); LiquidScreen home_screen(KettleState_line, kettle_power_line); LiquidMenu menu(lcd); @@ -84,6 +108,7 @@ void setup() { pinMode(encoderDT, INPUT_PULLUP); Enter.begin(encoderBTN); boilPWM.begin(kettlePWM, PeriodPWM); + KettleThermo.begin(MAX31865_3WIRE); // if you get a connection, report back via serial: if (Ethernet.linkStatus() == LinkON) { @@ -106,7 +131,8 @@ void UpdateBoilKettle(){ static byte last_KettleDuty = 0; if (Enter.pressed()) { - KettleOn = !KettleOn; + + KettleMode = !KettleMode; menu.update(); } @@ -115,7 +141,8 @@ void UpdateBoilKettle(){ menu.update(); } - if (KettleOn) { + if (KettleMode) { + KettleController.Compute(); digitalWrite(kettlePWM, boilPWM.compute(KettleDuty)); } else { digitalWrite(kettlePWM, boilPWM.compute(0)); @@ -123,6 +150,7 @@ void UpdateBoilKettle(){ } void loop() { + KettleTemp = KettleThermo.readRTD(); UpdateBoilKettle(); unsigned long elapsedTime = (millis() - lastRun); diff --git a/boil_kettle/thermoControl.cpp b/boil_kettle/thermoControl.cpp new file mode 100644 index 0000000..88d5bea --- /dev/null +++ b/boil_kettle/thermoControl.cpp @@ -0,0 +1,71 @@ + +#include +#include +#include "thermoControl.h" + +thermoControl::thermoControl(double* input_temp, uint8_t* setpoint_temp, uint8_t* output_pwm, uint8_t* max_threshold, uint8_t* hysteresis) { + output_pwm = output_pwm; + input_temp = input_temp; + setpoint_temp = setpoint_temp; + + outMax = 100; + outMin = 10; + + OpMode = OFF; + SampleTime = 100; + lastTime = millis()-SampleTime; + +} + +bool thermoControl::Compute() { + unsigned long now = millis(); + unsigned long timeChange = (now - lastTime); + + if(timeChange>=SampleTime && OpMode == AUTOMATIC) { + double output; + double input = *input_temp; + double error = (double)*setpoint_temp - input; + + if (error >= (double)*max_threshold) { + output = outMax; + } else if (error > *hysteresis) { + output = 100 * error / *max_threshold; + output = max(output, outMin); + output = min(output, outMax); + } else { + output = 0; + } + *output_pwm = output; + lastTime = now; + + return true; + } else { + return false; + } +} + +void thermoControl::SetSampleTime(int NewSampleTime) { + if (NewSampleTime > 0) { + SampleTime = (unsigned long)NewSampleTime; + } +} + +void thermoControl::SetPowerLimits(uint8_t Max, uint8_t Min) { + if(Min >= Max) return; + outMax = Max; + outMin = Min; +} + +void thermoControl::SetMode(modes newMode) { + OpMode = newMode; +} + +modes thermoControl::GetMode() { + return OpMode; +} + +modes thermoControl::CycleMode() { + OpMode = (modes)(OpMode + 1); + return OpMode; +} + diff --git a/boil_kettle/thermoControl.h b/boil_kettle/thermoControl.h new file mode 100644 index 0000000..769fbe7 --- /dev/null +++ b/boil_kettle/thermoControl.h @@ -0,0 +1,33 @@ +#ifndef THERMOCONTROL_h +#define THERMOCONTROL_h + +enum modes : uint8_t {OFF, AUTOMATIC, MANUAL}; + +class thermoControl { + private: + double *input_temp; + double *output_pwm; + double *setpoint_temp; + double *hysteresis; + double *max_threshold; + double outMax; + double outMin; + + modes OpMode; + + unsigned long SampleTime; + unsigned long lastTime; + + public: + thermoControl(double*, uint8_t*, uint8_t*, uint8_t*, uint8_t*); + bool Compute(); + void SetSampleTime(int); + void SetPowerLimits(uint8_t, uint8_t); + void SetHysteresis(double); + void SetThreshPWR(uint8_t); + void SetMode(modes); + modes GetMode(); + modes CycleMode(); +}; + +#endif