Brewery-Controller/boil_kettle/boil_kettle.ino

191 lines
4.4 KiB
C++

//Built-in
#include <Arduino.h>
#include <SPI.h>
#include <Ethernet.h>
#include <EEPROM.h>
// Additoinal Libraries
#include <cJSON.h>
#include <PubSubClient.h>
#include <LiquidCrystal_I2C.h>
#include <LiquidMenu.h> // LiquidMenu_config.h needs to be modified to use I2C.
#include <MD_REncoder.h>
#include <Adafruit_MAX31865.h>
// My Includes
#include "config.h"
#include "button.h"
#include "slowPWM.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 */
// uint8_t ThreshPWR = 5;
// double Hysteresis = 1;
// User I/O objects.
Button Enter;
MD_REncoder rotary = MD_REncoder(encoderDT, encoderCLK);
LiquidCrystal_I2C lcd(0x27,20,4);
// Internal I/O
Adafruit_MAX31865 KettleThermo = Adafruit_MAX31865(kettleRTDCS);
slowPWM boilPWM;
thermoControl KettleController;
void MessageReceived(char*, byte*, unsigned int);
EthernetClient net;
PubSubClient mqtt_client;
unsigned long lastRun = 0;
// Return a character array to represent the
// On/Off state of the kettle.
char* ShowKettleState() {
if (KettleMode == MANUAL) {
return (char*)F("Kettle: Manual");
} else if (KettleMode == AUTOMATIC) {
return (char*)F("Kettle: Auto");
} else {
return (char*)F("Kettle: Off");
}
}
char* ShowKettleSetting() {
static char LCD_Line[21];
char setting[4];
if (KettleMode == MANUAL) {
strcpy(LCD_Line, (char*)F("Kettle Power: "));
itoa(KettleDuty / 10, setting, 10);
strcat(LCD_Line, setting);
strcat(LCD_Line, "%");
return LCD_Line;
} else if (KettleMode == AUTOMATIC) {
strcpy(LCD_Line, (char*)F("Kettle Temp: "));
itoa(KettleSetpoint / 10, setting, 10);
strcat(LCD_Line, setting);
strcat(LCD_Line, "F");
return LCD_Line;
} else {
return (char*)"";
}
}
// Interrupt function to run when encoder is turned.
//
// Increases/decreases the kettle output to a max
// of 100% and minimum of 0%.
void doEncoder()
{
uint8_t result = rotary.read();
uint8_t inc;
if (result) {
uint8_t speed = rotary.speed();
speed >= 10 ? inc = 50 : inc = 10;
}
if (result == DIR_CW && KettleDuty < 1000) {
KettleDuty = (KettleDuty / inc) * inc + inc;
} else if (result == DIR_CCW && KettleDuty > 0) {
KettleDuty = (KettleDuty / inc) * inc - inc;
}
}
// LCD menu setup.
LiquidLine kettle_state_line(0, 0, ShowKettleState);
LiquidLine kettle_power_line(0, 1, ShowKettleSetting);
LiquidScreen home_screen(kettle_state_line, kettle_power_line);
LiquidMenu menu(lcd);
void setup() {
ConfigData config;
EEPROM.get(ConfAddress, config);
unsigned long lastRun = millis() - UpdateInterval;
Serial.begin(9600);
rotary.begin();
Ethernet.begin(config.mac, config.ip);
attachInterrupt(digitalPinToInterrupt(encoderCLK), doEncoder, CHANGE);
attachInterrupt(digitalPinToInterrupt(encoderDT), doEncoder, CHANGE);
pinMode(encoderCLK, INPUT_PULLUP);
pinMode(encoderDT, INPUT_PULLUP);
Enter.begin(encoderBTN);
boilPWM.begin(kettlePWM, config.period);
KettleThermo.begin(MAX31865_3WIRE);
mqtt_client.setServer(config.mqtt.broker, 1883);
mqtt_client.setClient(net);
mqtt_client.setCallback(MessageReceived);
KettleController.begin(&KettleTemp, &KettleSetpoint, &KettleDuty, config.threshold, config.hysteresis);
// if you get a connection, report back via serial:
if (Ethernet.linkStatus() == LinkON) {
ConnectMQTT();
}
lcd.init();
lcd.backlight();
menu.init();
menu.add_screen(home_screen);
menu.update();
};
void UpdateBoilKettle(){
static uint8_t last_KettleDuty = 0;
static uint8_t last_KettleTemp = 0;
if (Enter.pressed()) {
KettleMode = (modes)(KettleMode + 1);
menu.update();
}
if (last_KettleDuty != KettleDuty) {
last_KettleDuty = KettleDuty;
menu.update();
}
if (last_KettleTemp != KettleTemp) {
last_KettleTemp = KettleTemp;
menu.update();
}
if (KettleMode != OFF) {
KettleController.Compute();
digitalWrite(kettlePWM, boilPWM.compute(KettleDuty));
} else {
digitalWrite(kettlePWM, boilPWM.compute(0));
}
}
void loop() {
KettleTemp = (uint8_t)(KettleThermo.readRTD() * 10);
UpdateBoilKettle();
unsigned long elapsedTime = (millis() - lastRun);
if (Ethernet.linkStatus() == LinkON && elapsedTime >= UpdateInterval) {
mqtt_client.loop();
//if (!mqtt_client.connected()) ConnectMQTT();
SendSensorData();
lastRun = millis();
}
}