Made a much more involved kettle control class.
All the input/output tracking is handled with class members instead of passing pointers to global variables.
This commit is contained in:
parent
c7857c1b03
commit
8b72a16203
@ -3,28 +3,21 @@
|
|||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
#include <Ethernet.h>
|
#include <Ethernet.h>
|
||||||
#include <EEPROM.h>
|
#include <EEPROM.h>
|
||||||
|
#include <PubSubClient.h>
|
||||||
|
#include <cJSON.h>
|
||||||
|
|
||||||
// Additoinal Libraries
|
// Additoinal Libraries
|
||||||
#include <cJSON.h>
|
|
||||||
#include <PubSubClient.h>
|
|
||||||
#include <LiquidCrystal_I2C.h>
|
#include <LiquidCrystal_I2C.h>
|
||||||
#include <LiquidMenu.h> // LiquidMenu_config.h needs to be modified to use I2C.
|
#include <LiquidMenu.h> // LiquidMenu_config.h needs to be modified to use I2C.
|
||||||
#include <MD_REncoder.h>
|
#include <MD_REncoder.h>
|
||||||
#include <Adafruit_MAX31865.h>
|
|
||||||
|
|
||||||
// My Includes
|
// My Includes
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "globals.h"
|
||||||
#include "button.h"
|
#include "button.h"
|
||||||
#include "slowPWM.h"
|
#include "slowPWM.h"
|
||||||
#include "thermoControl.h"
|
#include "thermoControl.h"
|
||||||
|
|
||||||
// Global variables.
|
|
||||||
uint8_t KettleDuty = 0;
|
|
||||||
uint8_t KettleTemp;
|
|
||||||
uint8_t KettleSetpoint;
|
|
||||||
modes KettleMode = OFF;
|
|
||||||
const int UpdateInterval = 5000;
|
|
||||||
|
|
||||||
/* Defined in config.h for now */
|
/* Defined in config.h for now */
|
||||||
// uint8_t ThreshPWR = 5;
|
// uint8_t ThreshPWR = 5;
|
||||||
// double Hysteresis = 1;
|
// double Hysteresis = 1;
|
||||||
@ -34,24 +27,20 @@ Button Enter;
|
|||||||
MD_REncoder rotary = MD_REncoder(I_DT, I_CLK);
|
MD_REncoder rotary = MD_REncoder(I_DT, I_CLK);
|
||||||
LiquidCrystal_I2C lcd(0x27,20,4);
|
LiquidCrystal_I2C lcd(0x27,20,4);
|
||||||
|
|
||||||
// Internal I/O
|
// Internal I/O objects.
|
||||||
Adafruit_MAX31865 KettleThermo = Adafruit_MAX31865(kettleRTDCS);
|
|
||||||
slowPWM boilPWM;
|
slowPWM boilPWM;
|
||||||
thermoControl KettleController;
|
thermoControl KettleController;
|
||||||
|
|
||||||
void MessageReceived(char*, byte*, unsigned int);
|
// Network objects.
|
||||||
|
|
||||||
EthernetClient net;
|
EthernetClient net;
|
||||||
PubSubClient mqtt_client;
|
PubSubClient mqtt_client;
|
||||||
|
|
||||||
unsigned long lastRun = 0;
|
|
||||||
|
|
||||||
// Return a character array to represent the
|
// Return a character array to represent the
|
||||||
// On/Off state of the kettle.
|
// state of the kettle.
|
||||||
char* ShowKettleState() {
|
char* ShowKettleState() {
|
||||||
if (KettleMode == MANUAL) {
|
if (KettleController.Mode() == MANUAL) {
|
||||||
return (char*)F("Kettle: Manual");
|
return (char*)F("Kettle: Manual");
|
||||||
} else if (KettleMode == AUTOMATIC) {
|
} else if (KettleController.Mode() == AUTOMATIC) {
|
||||||
return (char*)F("Kettle: Auto");
|
return (char*)F("Kettle: Auto");
|
||||||
} else {
|
} else {
|
||||||
return (char*)F("Kettle: Off");
|
return (char*)F("Kettle: Off");
|
||||||
@ -61,18 +50,18 @@ char* ShowKettleState() {
|
|||||||
char* ShowKettleSetting() {
|
char* ShowKettleSetting() {
|
||||||
static char LCD_Line[21];
|
static char LCD_Line[21];
|
||||||
char setting[4];
|
char setting[4];
|
||||||
if (KettleMode == MANUAL) {
|
if (KettleController.Mode() == MANUAL) {
|
||||||
strcpy(LCD_Line, (char*)F("Kettle Power: "));
|
strcpy(LCD_Line, (char*)F("Kettle Power: "));
|
||||||
itoa(KettleDuty / 10, setting, 10);
|
itoa(KettleController.Power(), setting, 10);
|
||||||
strcat(LCD_Line, setting);
|
strcat(LCD_Line, setting);
|
||||||
strcat(LCD_Line, "%");
|
strcat(LCD_Line, (char*)F("%"));
|
||||||
|
|
||||||
return LCD_Line;
|
return LCD_Line;
|
||||||
} else if (KettleMode == AUTOMATIC) {
|
} else if (KettleController.Mode() == AUTOMATIC) {
|
||||||
strcpy(LCD_Line, (char*)F("Kettle Temp: "));
|
strcpy(LCD_Line, (char*)F("Kettle Temp: "));
|
||||||
itoa(KettleSetpoint / 10, setting, 10);
|
itoa(KettleController.Setpoint(), setting, 10);
|
||||||
strcat(LCD_Line, setting);
|
strcat(LCD_Line, setting);
|
||||||
strcat(LCD_Line, "F");
|
strcat(LCD_Line, (char*)F("F"));
|
||||||
return LCD_Line;
|
return LCD_Line;
|
||||||
} else {
|
} else {
|
||||||
return (char*)"";
|
return (char*)"";
|
||||||
@ -87,18 +76,20 @@ void doEncoder()
|
|||||||
{
|
{
|
||||||
uint8_t result = rotary.read();
|
uint8_t result = rotary.read();
|
||||||
uint8_t inc;
|
uint8_t inc;
|
||||||
|
uint8_t KettleDuty = (uint8_t)KettleController.Power();
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
uint8_t speed = rotary.speed();
|
uint8_t speed = rotary.speed();
|
||||||
speed >= 10 ? inc = 50 : inc = 10;
|
speed >= 10 ? inc = 5 : inc = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == DIR_CW && KettleDuty < 1000) {
|
if (result == DIR_CW && KettleDuty < 100) {
|
||||||
KettleDuty = (KettleDuty / inc) * inc + inc;
|
KettleDuty = (KettleDuty / inc) * inc + inc;
|
||||||
} else if (result == DIR_CCW && KettleDuty > 0) {
|
} else if (result == DIR_CCW && KettleDuty > 0) {
|
||||||
KettleDuty = (KettleDuty / inc) * inc - inc;
|
KettleDuty = (KettleDuty / inc) * inc - inc;
|
||||||
}
|
}
|
||||||
|
KettleController.Power((double)KettleDuty);
|
||||||
|
SettingChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// LCD menu setup.
|
// LCD menu setup.
|
||||||
@ -146,23 +137,16 @@ void setup() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void UpdateBoilKettle(){
|
void UpdateBoilKettle(){
|
||||||
static uint8_t last_KettleDuty = 0;
|
|
||||||
static uint8_t last_KettleTemp = 0;
|
|
||||||
|
|
||||||
if (Enter.pressed()) {
|
if (Enter.pressed()) {
|
||||||
|
KettleController.CycleMode();
|
||||||
KettleMode = (modes)(KettleMode + 1);
|
SettingChanged = true;
|
||||||
menu.update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (last_KettleDuty != KettleDuty) {
|
if (SettingChanged) {
|
||||||
last_KettleDuty = KettleDuty;
|
|
||||||
menu.update();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (last_KettleTemp != KettleTemp) {
|
|
||||||
last_KettleTemp = KettleTemp;
|
|
||||||
menu.update();
|
menu.update();
|
||||||
|
SettingChanged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (KettleController.Mode() != OFF) {
|
if (KettleController.Mode() != OFF) {
|
||||||
@ -174,7 +158,6 @@ void UpdateBoilKettle(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
KettleTemp = (uint8_t)(KettleThermo.readRTD() * 10);
|
|
||||||
UpdateBoilKettle();
|
UpdateBoilKettle();
|
||||||
|
|
||||||
unsigned long elapsedTime = (millis() - lastRun);
|
unsigned long elapsedTime = (millis() - lastRun);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
void ConnectMQTT() {
|
void ConnectMQTT() {
|
||||||
ConfigData config;
|
ConfigData config;
|
||||||
EEPROM.get(ConfAddress, config);
|
EEPROM.get(ConfAddress, config);
|
||||||
|
@ -17,7 +17,6 @@ class slowPWM {
|
|||||||
lastSwitchTime = 0;
|
lastSwitchTime = 0;
|
||||||
outputState = LOW;
|
outputState = LOW;
|
||||||
pinMode(pin, OUTPUT);
|
pinMode(pin, OUTPUT);
|
||||||
Serial.println("Setup PWM");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
byte compute(uint8_t duty) {
|
byte compute(uint8_t duty) {
|
||||||
|
@ -3,14 +3,25 @@
|
|||||||
#include <EEPROM.h>
|
#include <EEPROM.h>
|
||||||
#include "thermoControl.h"
|
#include "thermoControl.h"
|
||||||
|
|
||||||
void thermoControl::begin(uint8_t* input_temp, uint8_t* setpoint_temp, uint8_t* output_pwm, uint8_t max_threshold, uint8_t hysteresis) {
|
|
||||||
|
void thermoControl::begin(int8_t pinRTD) {
|
||||||
|
RTD = new Adafruit_MAX31865(pinRTD);
|
||||||
|
outMax = 100;
|
||||||
|
outMin = 10;
|
||||||
|
OpMode = OFF;
|
||||||
|
SampleTime = 100;
|
||||||
|
lastTime = millis()-SampleTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
void thermoControl::begin(int8_t pinRTD, double temp, double output_pwm, double max_pwr_threshold, double hysteresis) {
|
||||||
output_pwm = output_pwm;
|
output_pwm = output_pwm;
|
||||||
input_temp = input_temp;
|
|
||||||
setpoint_temp = setpoint_temp;
|
RTD = new Adafruit_MAX31865(pinRTD);
|
||||||
|
control_temp = temp;
|
||||||
outMax = 1000;
|
|
||||||
outMin = 100;
|
outMax = 100;
|
||||||
|
outMin = 10;
|
||||||
|
|
||||||
OpMode = OFF;
|
OpMode = OFF;
|
||||||
SampleTime = 100;
|
SampleTime = 100;
|
||||||
lastTime = millis()-SampleTime;
|
lastTime = millis()-SampleTime;
|
||||||
@ -20,20 +31,22 @@ bool thermoControl::Compute() {
|
|||||||
unsigned long now = millis();
|
unsigned long now = millis();
|
||||||
unsigned long timeChange = (now - lastTime);
|
unsigned long timeChange = (now - lastTime);
|
||||||
|
|
||||||
if(timeChange>=SampleTime && OpMode == AUTOMATIC) {
|
double temp = RTD->readRTD();
|
||||||
uint8_t output;
|
|
||||||
uint8_t error = *setpoint_temp - *input_temp;
|
|
||||||
|
|
||||||
if (error >= *max_threshold) {
|
if(timeChange>=SampleTime && OpMode == AUTOMATIC) {
|
||||||
|
double output;
|
||||||
|
double error = control_temp - temp;
|
||||||
|
|
||||||
|
if (error >= max_pwr_threshold) {
|
||||||
output = outMax;
|
output = outMax;
|
||||||
} else if (error > *hysteresis) {
|
} else if (error > hysteresis) {
|
||||||
output = 100 * error / *max_threshold;
|
output = 100 * error / max_pwr_threshold;
|
||||||
output = max(output, outMin);
|
output = max(output, outMin);
|
||||||
output = min(output, outMax);
|
output = min(output, outMax);
|
||||||
} else {
|
} else {
|
||||||
output = 0;
|
output = 0;
|
||||||
}
|
}
|
||||||
*output_pwm = output;
|
output_pwm = output;
|
||||||
lastTime = now;
|
lastTime = now;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -42,28 +55,48 @@ bool thermoControl::Compute() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double thermoControl::Power() {
|
||||||
|
return output_pwm;
|
||||||
|
}
|
||||||
|
|
||||||
|
void thermoControl::Power(double pwr) {
|
||||||
|
output_pwm = pwr;
|
||||||
|
}
|
||||||
|
|
||||||
|
double thermoControl::Setpoint() {
|
||||||
|
return control_temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void thermoControl::Setpoint(double temp) {
|
||||||
|
control_temp = temp;
|
||||||
|
}
|
||||||
|
|
||||||
void thermoControl::SetSampleTime(int NewSampleTime) {
|
void thermoControl::SetSampleTime(int NewSampleTime) {
|
||||||
if (NewSampleTime > 0) {
|
if (NewSampleTime > 0) {
|
||||||
SampleTime = (unsigned long)NewSampleTime;
|
SampleTime = (unsigned long)NewSampleTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void thermoControl::SetPowerLimits(uint8_t Max, uint8_t Min) {
|
void thermoControl::SetPowerLimits(double Max, double Min) {
|
||||||
if(Min >= Max) return;
|
if(Min >= Max) return;
|
||||||
outMax = Max;
|
outMax = Max;
|
||||||
outMin = Min;
|
outMin = Min;
|
||||||
}
|
}
|
||||||
|
|
||||||
void thermoControl::SetMode(modes newMode) {
|
void thermoControl::Mode(modes newMode) {
|
||||||
OpMode = newMode;
|
OpMode = newMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
modes thermoControl::GetMode() {
|
modes thermoControl::Mode() {
|
||||||
return OpMode;
|
return OpMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
modes thermoControl::CycleMode() {
|
modes thermoControl::CycleMode() {
|
||||||
OpMode = (modes)(OpMode + 1);
|
if (OpMode + 1 == OVERFLOW) {
|
||||||
|
OpMode = (modes)(0);
|
||||||
|
} else {
|
||||||
|
OpMode = (modes)(OpMode + 1);
|
||||||
|
}
|
||||||
return OpMode;
|
return OpMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,32 +1,39 @@
|
|||||||
#ifndef THERMOCONTROL_h
|
#ifndef THERMOCONTROL_h
|
||||||
#define THERMOCONTROL_h
|
#define THERMOCONTROL_h
|
||||||
|
|
||||||
enum modes : uint8_t {OFF, AUTOMATIC, MANUAL};
|
#include <Adafruit_MAX31865.h>
|
||||||
|
|
||||||
|
enum modes : uint8_t {OFF, AUTOMATIC, MANUAL, OVERFLOW};
|
||||||
|
|
||||||
class thermoControl {
|
class thermoControl {
|
||||||
private:
|
private:
|
||||||
double *input_temp;
|
Adafruit_MAX31865* RTD;
|
||||||
double *output_pwm;
|
double output_pwm;
|
||||||
double *setpoint_temp;
|
double control_temp;
|
||||||
double *hysteresis;
|
double hysteresis;
|
||||||
double *max_threshold;
|
double max_pwr_threshold;
|
||||||
double outMax;
|
int outMax;
|
||||||
double outMin;
|
int outMin;
|
||||||
|
|
||||||
modes OpMode;
|
modes OpMode;
|
||||||
|
|
||||||
unsigned long SampleTime;
|
unsigned long SampleTime;
|
||||||
unsigned long lastTime;
|
unsigned long lastTime;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void begin(uint8_t*, uint8_t*, uint8_t*, uint8_t, uint8_t);
|
void begin(int8_t, double, double, double, double);
|
||||||
|
void begin(int8_t);
|
||||||
bool Compute();
|
bool Compute();
|
||||||
|
double Power();
|
||||||
|
void Power(double);
|
||||||
|
double Setpoint();
|
||||||
|
void Setpoint(double);
|
||||||
void SetSampleTime(int);
|
void SetSampleTime(int);
|
||||||
void SetPowerLimits(uint8_t, uint8_t);
|
void SetPowerLimits(double, double);
|
||||||
void SetHysteresis(uint8_t);
|
void SetHysteresis(double);
|
||||||
void SetThreshPWR(uint8_t);
|
void SetThreshPWR(double);
|
||||||
void SetMode(modes);
|
void Mode(modes);
|
||||||
modes GetMode();
|
modes Mode();
|
||||||
modes CycleMode();
|
modes CycleMode();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user