Fermenter restructure + huge code clean
This commit is contained in:
parent
0cc485577c
commit
1bde26489b
@ -79,6 +79,20 @@ void configPutUint64_t(const char *name, uint64_t value) {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t configGetUint8_t(const char *name, uint8_t fallback) {
|
||||
if (!config.containsKey(name)) {
|
||||
return fallback;
|
||||
}
|
||||
return config[name];
|
||||
}
|
||||
|
||||
void configPutUint8_t(const char *name, uint8_t value) {
|
||||
if (config[name] != value) {
|
||||
config[name] = value;
|
||||
lastChangeMillis = millis();
|
||||
}
|
||||
}
|
||||
|
||||
void configPrint() {
|
||||
info("Config (%s):", lastChangeMillis == 0 ? "PERSISTED" : "TRANSIENT");
|
||||
for (JsonPair pair: config.as<JsonObject>()) {
|
||||
|
||||
@ -9,20 +9,27 @@ void configLoop();
|
||||
|
||||
void configReset();
|
||||
|
||||
void configLoaded();
|
||||
|
||||
String configGetString(const char *name, const char *fallback, bool allowEmpty);
|
||||
|
||||
void configPutString(const char *name, const char *value);
|
||||
|
||||
|
||||
double configGetDouble(const char *name, double fallback);
|
||||
|
||||
void configPutDouble(const char *name, double value);
|
||||
|
||||
|
||||
uint64_t configGetUint64_t(const char *name, uint64_t fallback);
|
||||
|
||||
void configPutUint64_t(const char *name, uint64_t value);
|
||||
|
||||
|
||||
uint8_t configGetUint8_t(const char *name, uint8_t fallback);
|
||||
|
||||
void configPutUint8_t(const char *name, uint8_t value);
|
||||
|
||||
|
||||
void configPrint();
|
||||
|
||||
#endif
|
||||
|
||||
@ -84,7 +84,7 @@ void consoleHandle(char *cmd) {
|
||||
_debug();
|
||||
} else if (strcmp(first, "config_reset") == 0) {
|
||||
configReset();
|
||||
} else if (!patrix_command((char *) cmd)) {
|
||||
} else if (!patrixCommand((char *) cmd)) {
|
||||
info("Unknown command: %s", cmd);
|
||||
}
|
||||
}
|
||||
@ -249,7 +249,7 @@ const char *getFlashChipMode() {
|
||||
}
|
||||
}
|
||||
|
||||
bool setDouble(const char *name, double *destinationPtr, double min, double max) {
|
||||
bool cmdReadDouble(const char *name, double *destinationPtr, double min, double max) {
|
||||
const char *valueStr = strtok(nullptr, "");
|
||||
if (valueStr == nullptr) {
|
||||
consolePrintUsage();
|
||||
@ -274,7 +274,7 @@ bool setDouble(const char *name, double *destinationPtr, double min, double max)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool setUint64_T(const char *name, uint64_t *destinationPtr, uint64_t min, uint64_t max) {
|
||||
bool cmdReadU64(const char *name, uint64_t *destinationPtr, uint64_t min, uint64_t max) {
|
||||
const char *valueStr = strtok(nullptr, "");
|
||||
if (valueStr == nullptr) {
|
||||
consolePrintUsage();
|
||||
|
||||
@ -9,12 +9,12 @@ void consoleLoop();
|
||||
|
||||
void consoleHandle(char *cmd);
|
||||
|
||||
bool patrix_command(char *cmd);
|
||||
bool patrixCommand(char *cmd);
|
||||
|
||||
void consolePrintUsage();
|
||||
|
||||
bool setDouble(const char *name, double *destinationPtr, double min, double max);
|
||||
bool cmdReadDouble(const char *name, double *destinationPtr, double min, double max);
|
||||
|
||||
bool setUint64_T(const char *name, uint64_t *destinationPtr, uint64_t min, uint64_t max);
|
||||
bool cmdReadU64(const char *name, uint64_t *destinationPtr, uint64_t min, uint64_t max);
|
||||
|
||||
#endif
|
||||
|
||||
@ -8,6 +8,12 @@
|
||||
|
||||
struct IData {
|
||||
|
||||
time_t time;
|
||||
|
||||
explicit IData(time_t time) : time(time) {
|
||||
// -
|
||||
}
|
||||
|
||||
virtual void toJson(JsonObject &json) const = 0;
|
||||
|
||||
};
|
||||
@ -20,16 +26,13 @@ class Cache {
|
||||
|
||||
private:
|
||||
|
||||
struct Entry {
|
||||
time_t timestamp = 0;
|
||||
T data;
|
||||
};
|
||||
T buffer[size];
|
||||
|
||||
Entry buffer[size];
|
||||
T *bufferRead = buffer;
|
||||
|
||||
Entry *bufferRead = buffer;
|
||||
T *bufferWrite = buffer;
|
||||
|
||||
Entry *bufferWrite = buffer;
|
||||
T last{};
|
||||
|
||||
size_t usage = 0;
|
||||
|
||||
@ -40,15 +43,15 @@ public:
|
||||
// -
|
||||
}
|
||||
|
||||
bool add(const time_t timestamp, const T &data) {
|
||||
if (usage >= size) {
|
||||
return false;
|
||||
bool add(T data) {
|
||||
if (usage < size && data.needsPublish(last)) {
|
||||
last = data;
|
||||
*bufferWrite = data;
|
||||
bufferWrite = (bufferWrite - buffer + 1) % size + buffer;
|
||||
usage++;
|
||||
return true;
|
||||
}
|
||||
bufferWrite->timestamp = timestamp;
|
||||
bufferWrite->data = data;
|
||||
bufferWrite = (bufferWrite - buffer + 1) % size + buffer;
|
||||
usage++;
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
@ -57,8 +60,9 @@ public:
|
||||
}
|
||||
JsonDocument doc;
|
||||
JsonObject json = doc.to<JsonObject>();
|
||||
json["timestamp"] = correctTime(bufferRead->timestamp);
|
||||
bufferRead->data.toJson(json);
|
||||
correctTime(bufferRead->time);
|
||||
json["timestamp"] = bufferRead->time;
|
||||
bufferRead->toJson(json);
|
||||
if (mqttPublishData(json)) {
|
||||
bufferRead = (bufferRead - buffer + 1) % size + buffer;
|
||||
usage--;
|
||||
|
||||
@ -15,36 +15,22 @@ private:
|
||||
|
||||
uint64_t address;
|
||||
|
||||
const double valueThreshold;
|
||||
|
||||
const time_t timeoutSec;
|
||||
|
||||
const time_t minIntervalMillis;
|
||||
|
||||
double lastSentValue = NAN;
|
||||
|
||||
unsigned long lastSentMillis = 0;
|
||||
|
||||
double lastValue = NAN;
|
||||
|
||||
time_t lastTimestamp = 0;
|
||||
|
||||
double lastValidValue = NAN;
|
||||
|
||||
time_t lastValidTimestamp = 0;
|
||||
|
||||
public:
|
||||
|
||||
DallasSensor(Dallas &sensors, const uint64_t address, const double valueThreshold, const time_t timeoutSec, const time_t minIntervalMillis) :
|
||||
DallasSensor(Dallas &sensors, const uint64_t address, const time_t timeoutSec) :
|
||||
sensors(sensors),
|
||||
address(address),
|
||||
valueThreshold(valueThreshold),
|
||||
timeoutSec(timeoutSec),
|
||||
minIntervalMillis(minIntervalMillis) {
|
||||
timeoutSec(timeoutSec) {
|
||||
// -
|
||||
}
|
||||
|
||||
bool loop() {
|
||||
void loop() {
|
||||
const time_t now = getTime();
|
||||
if (now - lastTimestamp > timeoutSec) {
|
||||
lastTimestamp = 0;
|
||||
@ -53,21 +39,9 @@ public:
|
||||
if (sensors.isConverted()) {
|
||||
const double value = sensors.read(address);
|
||||
const time_t timestamp = sensors.getTimestamp();
|
||||
const unsigned long millisNow = millis();
|
||||
const bool doPublish = !isnan(value) && (isnan(lastSentValue) || abs(lastSentValue - value) >= valueThreshold || millisNow - lastSentMillis >= minIntervalMillis);
|
||||
if (doPublish) {
|
||||
lastSentValue = value;
|
||||
lastSentMillis = millisNow;
|
||||
}
|
||||
lastValue = value;
|
||||
lastTimestamp = timestamp;
|
||||
if (!isnan(value)) {
|
||||
lastValidValue = value;
|
||||
lastValidTimestamp = timestamp;
|
||||
}
|
||||
return doPublish;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
[[nodiscard]] double getLastValue() const {
|
||||
@ -78,14 +52,6 @@ public:
|
||||
return lastTimestamp;
|
||||
}
|
||||
|
||||
[[nodiscard]] double getLastValidValue() const {
|
||||
return lastValidValue;
|
||||
}
|
||||
|
||||
[[nodiscard]] time_t getLastValidTimestamp() const {
|
||||
return lastValidTimestamp;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -195,18 +195,10 @@ time_t getTime() {
|
||||
return epochSeconds;
|
||||
}
|
||||
|
||||
time_t correctTime(const time_t value) {
|
||||
if (!timeSet) {
|
||||
return value;
|
||||
void correctTime(time_t &value) {
|
||||
if (timeSet && value < MIN_EPOCH_SECONDS) {
|
||||
value = getTime() - preTimeOffset + value;
|
||||
}
|
||||
if (value < MIN_EPOCH_SECONDS) {
|
||||
return getTime() - preTimeOffset + value;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
bool isOlderThan(time_t time, time_t seconds) {
|
||||
return getTime() > correctTime(time) + seconds;
|
||||
}
|
||||
|
||||
void getDateTime(char *buffer, size_t size) {
|
||||
|
||||
@ -15,9 +15,7 @@ bool isTimeSet();
|
||||
|
||||
time_t getTime();
|
||||
|
||||
time_t correctTime(time_t value);
|
||||
|
||||
bool isOlderThan(time_t time, time_t seconds);
|
||||
void correctTime(time_t &value);
|
||||
|
||||
void getDateTime(char *buffer, size_t size);
|
||||
|
||||
|
||||
@ -16,6 +16,7 @@ lib_deps = https://github.com/milesburton/Arduino-Temperature-Control-Library
|
||||
Wire
|
||||
https://github.com/phassel/ArduPID/
|
||||
https://github.com/wayoda/LedControl
|
||||
https://github.com/me-no-dev/ESPAsyncWebServer
|
||||
|
||||
[env:TEST32]
|
||||
upload_port = 10.42.0.66
|
||||
|
||||
29
src/Fermenter/FementerDisplay.cpp
Normal file
29
src/Fermenter/FementerDisplay.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
#include "FementerDisplay.h"
|
||||
|
||||
#include "LedControl.h"
|
||||
|
||||
LedControl lc = LedControl(13, 14, 15, 1);
|
||||
|
||||
void writeDecimal(int *digit, double value) {
|
||||
const int integer = (int) value;
|
||||
const int decimal = (int) ((value - integer) * 10) % 10;
|
||||
lc.setDigit(0, (*digit)++, decimal, false);
|
||||
lc.setDigit(0, (*digit)++, integer % 10, true);
|
||||
lc.setDigit(0, (*digit)++, integer / 10 % 10, false);
|
||||
}
|
||||
|
||||
void displayLoop(double temperature, double target) {
|
||||
static unsigned long lastDisplayInit = 0;
|
||||
if (lastDisplayInit == 0 || millis() - lastDisplayInit > 60 * 60 * 1000) {
|
||||
lastDisplayInit = millis();
|
||||
lc.shutdown(0, true);
|
||||
lc.shutdown(0, false);
|
||||
lc.setIntensity(0, 4);
|
||||
lc.clearDisplay(0);
|
||||
}
|
||||
int digit = 0;
|
||||
writeDecimal(&digit, temperature);
|
||||
digit++;
|
||||
digit++;
|
||||
writeDecimal(&digit, target);
|
||||
}
|
||||
6
src/Fermenter/FementerDisplay.h
Normal file
6
src/Fermenter/FementerDisplay.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef SENSOR3_FEMENTERDISPLAY_H
|
||||
#define SENSOR3_FEMENTERDISPLAY_H
|
||||
|
||||
void displayLoop(double temperature, double target);
|
||||
|
||||
#endif
|
||||
@ -1,170 +1,38 @@
|
||||
#if defined(FERMENTER) || defined(TEST8266)
|
||||
|
||||
#include <Patrix.h>
|
||||
#include "sensors/Dallas.h"
|
||||
#include "sensors/DallasSensor.h"
|
||||
#include "ArduPID.h"
|
||||
#include "LedControl.h"
|
||||
#include "FermenterData.h"
|
||||
|
||||
#define SENSOR_GPIO D4
|
||||
#define CONTROL_GPIO D2
|
||||
#define CONTROL_PWM_BITS 10
|
||||
#define CONTROL_PWM_MAX (pow(2, CONTROL_PWM_BITS) - 1)
|
||||
|
||||
#define PID_DEFAULT_P 1500
|
||||
#define PID_DEFAULT_I 0
|
||||
#define PID_DEFAULT_D 0
|
||||
#define PID_DEFAULT_TARGET 31
|
||||
#define PID_DEFAULT_OVER 5
|
||||
|
||||
Dallas dallas(SENSOR_GPIO);
|
||||
|
||||
DallasSensor sensor(dallas, 0x3D0417C1D740FF28, 0.1, 5, 60 * 1000);
|
||||
|
||||
LedControl lc = LedControl(13, 14, 15, 1);
|
||||
|
||||
ArduPID pid;
|
||||
|
||||
double proportional = PID_DEFAULT_P;
|
||||
|
||||
double integral = PID_DEFAULT_I;
|
||||
|
||||
double derivative = PID_DEFAULT_D;
|
||||
|
||||
double temperatureTarget = PID_DEFAULT_TARGET;
|
||||
|
||||
double temperatureOver = PID_DEFAULT_OVER;
|
||||
|
||||
double temperature = NAN;
|
||||
|
||||
double heaterPWM = 0;
|
||||
|
||||
uint8_t heaterPercent = 0;
|
||||
#include "FementerDisplay.h"
|
||||
#include "FermenterPID.h"
|
||||
#include "FermenterSensor.h"
|
||||
|
||||
Cache<FermenterData, 800> cache;
|
||||
|
||||
void writeDecimal(int *digit, double value);
|
||||
|
||||
void displayLoop();
|
||||
|
||||
void pidLoop();
|
||||
|
||||
void patrixSetup() {
|
||||
dallas.begin();
|
||||
analogWriteResolution(CONTROL_PWM_BITS);
|
||||
|
||||
configLoaded();
|
||||
|
||||
pid.begin(&temperature, &heaterPWM, &temperatureTarget, proportional, integral, derivative);
|
||||
pid.setOutputLimits(0, CONTROL_PWM_MAX);
|
||||
pid.start();
|
||||
sensorSetup();
|
||||
pidSetup(&temperature);
|
||||
}
|
||||
|
||||
void patrixLoop() {
|
||||
dallas.loop();
|
||||
bool doPublish = sensor.loop();
|
||||
displayLoop();
|
||||
sensorLoop();
|
||||
pidLoop();
|
||||
if (doPublish) {
|
||||
const FermenterData data = {(float) sensor.getLastValue(), (float) temperatureTarget, heaterPercent, (float) proportional, (float) integral, (float) derivative};
|
||||
cache.add(sensor.getLastTimestamp(), data);
|
||||
}
|
||||
displayLoop(temperature, target);
|
||||
cache.add({getTime(), (float) temperature, (float) target, getHeaterPercent(), (float) proportional, (float) integral, (float) derivative});
|
||||
cache.loop();
|
||||
}
|
||||
|
||||
void pidLoop() {
|
||||
temperature = sensor.getLastValue();
|
||||
if (!isnan(temperature)) {
|
||||
pid.compute();
|
||||
} else {
|
||||
heaterPWM = 0;
|
||||
}
|
||||
|
||||
const char *emergencyStr = "";
|
||||
if (heaterPWM > 0 && temperature > temperatureTarget + temperatureOver) {
|
||||
heaterPWM = 0;
|
||||
emergencyStr = "[EMERGENCY CUTOFF]";
|
||||
}
|
||||
|
||||
analogWrite(CONTROL_GPIO, (int) round(heaterPWM));
|
||||
heaterPercent = (int) round(100.0 * heaterPWM / CONTROL_PWM_MAX);
|
||||
|
||||
static unsigned long lastDebug = 0;
|
||||
unsigned long now = millis();
|
||||
if (now - lastDebug >= 1000) {
|
||||
lastDebug = now;
|
||||
debug(
|
||||
"cache: %3d/%d | p: %f | i: %.12f | d: %.12f | target: %4.1f | heater: %3d%% | temperature: %5.2f %s",
|
||||
cache.getUsage(),
|
||||
cache.getSize(),
|
||||
|
||||
proportional == 0 ? NAN : proportional,
|
||||
integral == 0 ? NAN : integral,
|
||||
derivative == 0 ? NAN : derivative,
|
||||
|
||||
temperatureTarget,
|
||||
heaterPercent,
|
||||
temperature,
|
||||
|
||||
emergencyStr
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void displayLoop() {
|
||||
static unsigned long lastDisplayInit = 0;
|
||||
if (lastDisplayInit == 0 || millis() - lastDisplayInit > 60 * 60 * 1000) {
|
||||
lastDisplayInit = millis();
|
||||
lc.shutdown(0, true);
|
||||
lc.shutdown(0, false);
|
||||
lc.setIntensity(0, 4);
|
||||
lc.clearDisplay(0);
|
||||
}
|
||||
int digit = 0;
|
||||
writeDecimal(&digit, temperature);
|
||||
digit++;
|
||||
digit++;
|
||||
writeDecimal(&digit, temperatureTarget);
|
||||
}
|
||||
|
||||
void writeDecimal(int *digit, double value) {
|
||||
const int integer = (int) value;
|
||||
const int decimal = (int) ((value - integer) * 10) % 10;
|
||||
lc.setDigit(0, (*digit)++, decimal, false);
|
||||
lc.setDigit(0, (*digit)++, integer % 10, true);
|
||||
lc.setDigit(0, (*digit)++, integer / 10 % 10, false);
|
||||
}
|
||||
|
||||
bool patrix_command(char *first) {
|
||||
bool patrixCommand(char *first) {
|
||||
bool result = false;
|
||||
if (strcmp(first, "over") == 0 || strcmp(first, "o") == 0) {
|
||||
result = setDouble("over", &temperatureOver, 0, 20);
|
||||
} else if (strcmp(first, "target") == 0 || strcmp(first, "t") == 0) {
|
||||
result = setDouble("target", &temperatureTarget, -10, 60);
|
||||
} else if (strcmp(first, "proportional") == 0 || strcmp(first, "p") == 0) {
|
||||
result = setDouble("p", &proportional, NAN, NAN);
|
||||
} else if (strcmp(first, "integral") == 0 || strcmp(first, "i") == 0) {
|
||||
result = setDouble("i", &integral, NAN, NAN);
|
||||
} else if (strcmp(first, "derivative") == 0 || strcmp(first, "d") == 0) {
|
||||
result = setDouble("d", &derivative, NAN, NAN);
|
||||
} else if (strcmp(first, "pid_reset") == 0) {
|
||||
pid.reset();
|
||||
result = true;
|
||||
}
|
||||
if (result) {
|
||||
pid.setCoefficients(proportional, integral, derivative);
|
||||
if (strcmp(first, "p") == 0) {
|
||||
result = cmdReadDouble("p", &proportional, 0, NAN);
|
||||
} else if (strcmp(first, "i") == 0) {
|
||||
result = cmdReadDouble("i", &integral, 0, NAN);
|
||||
} else if (strcmp(first, "d") == 0) {
|
||||
result = cmdReadDouble("d", &derivative, 0, NAN);
|
||||
} else if (strcmp(first, "t") == 0) {
|
||||
result = cmdReadDouble("t", &target, -10, 60);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void configLoaded() {
|
||||
proportional = configGetDouble("p", PID_DEFAULT_P);
|
||||
integral = configGetDouble("i", PID_DEFAULT_I);
|
||||
derivative = configGetDouble("d", PID_DEFAULT_D);
|
||||
temperatureTarget = configGetDouble("target", PID_DEFAULT_TARGET);
|
||||
temperatureOver = configGetDouble("over", PID_DEFAULT_OVER);
|
||||
pid.setCoefficients(proportional, integral, derivative);
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -11,7 +11,7 @@ struct FermenterData : IData {
|
||||
float i;
|
||||
float d;
|
||||
|
||||
FermenterData() {
|
||||
FermenterData() : IData(0) {
|
||||
currentCelsius = NAN;
|
||||
targetCelsius = NAN;
|
||||
heaterPercent = 0;
|
||||
@ -21,6 +21,7 @@ struct FermenterData : IData {
|
||||
}
|
||||
|
||||
FermenterData(
|
||||
time_t time,
|
||||
float currentCelsius,
|
||||
float targetCelsius,
|
||||
uint8_t heaterPercent,
|
||||
@ -28,6 +29,7 @@ struct FermenterData : IData {
|
||||
float i,
|
||||
float d
|
||||
) :
|
||||
IData(time),
|
||||
currentCelsius(currentCelsius),
|
||||
targetCelsius(targetCelsius),
|
||||
heaterPercent(heaterPercent),
|
||||
@ -46,6 +48,18 @@ struct FermenterData : IData {
|
||||
json["d"] = d;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool needsPublish(FermenterData &last) {
|
||||
correctTime(time);
|
||||
correctTime(last.time);
|
||||
return time - last.time >= 60
|
||||
|| this->p != last.p
|
||||
|| this->i != last.i
|
||||
|| this->d != last.d
|
||||
|| abs(this->currentCelsius - last.currentCelsius) >= 0.1
|
||||
|| this->targetCelsius != last.targetCelsius
|
||||
|| this->heaterPercent != last.heaterPercent;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
62
src/Fermenter/FermenterPID.cpp
Normal file
62
src/Fermenter/FermenterPID.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
#include "FermenterPID.h"
|
||||
|
||||
#include "log.h"
|
||||
#include "config.h"
|
||||
|
||||
#define CONTROL_GPIO D2
|
||||
#define CONTROL_PWM_BITS 10
|
||||
#define CONTROL_PWM_MAX (pow(2, CONTROL_PWM_BITS) - 1)
|
||||
|
||||
ArduPID pid;
|
||||
|
||||
double proportional = 0;
|
||||
|
||||
double integral = 0;
|
||||
|
||||
double derivative = 0;
|
||||
|
||||
double target = 0;
|
||||
|
||||
double heater = 0;
|
||||
|
||||
void pidSetup(double *temperature) {
|
||||
analogWriteResolution(CONTROL_PWM_BITS);
|
||||
|
||||
proportional = configGetDouble("p", 0);
|
||||
integral = configGetDouble("i", 0);
|
||||
derivative = configGetDouble("d", 0);
|
||||
target = configGetDouble("t", 0);
|
||||
pid.begin(temperature, &heater, &target, proportional, integral, derivative);
|
||||
pid.setOutputLimits(0, CONTROL_PWM_MAX);
|
||||
}
|
||||
|
||||
void pidLoop() {
|
||||
if (!isnan(*pid.input)) {
|
||||
pid.setCoefficients(proportional, integral, derivative);
|
||||
pid.compute();
|
||||
} else {
|
||||
heater = 0;
|
||||
}
|
||||
|
||||
analogWrite(CONTROL_GPIO, (int) round(heater));
|
||||
|
||||
static unsigned long lastDebug = 0;
|
||||
unsigned long now = millis();
|
||||
if (now - lastDebug >= 1000) {
|
||||
lastDebug = now;
|
||||
debug(
|
||||
"p: %f | i: %.12f | d: %.12f | target: %4.1f | heater: %3d%% | temperature: %5.2f",
|
||||
proportional == 0 ? NAN : proportional,
|
||||
integral == 0 ? NAN : integral,
|
||||
derivative == 0 ? NAN : derivative,
|
||||
|
||||
*pid.setpoint,
|
||||
getHeaterPercent(),
|
||||
*pid.input
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t getHeaterPercent() {
|
||||
return (int) round(100.0 * heater / CONTROL_PWM_MAX);
|
||||
}
|
||||
22
src/Fermenter/FermenterPID.h
Normal file
22
src/Fermenter/FermenterPID.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef SENSOR3_FERMENTERPID_H
|
||||
#define SENSOR3_FERMENTERPID_H
|
||||
|
||||
#include "ArduPID.h"
|
||||
|
||||
extern ArduPID pid;
|
||||
|
||||
extern double proportional;
|
||||
|
||||
extern double integral;
|
||||
|
||||
extern double derivative;
|
||||
|
||||
extern double target;
|
||||
|
||||
void pidSetup(double *temperature);
|
||||
|
||||
void pidLoop();
|
||||
|
||||
uint8_t getHeaterPercent();
|
||||
|
||||
#endif
|
||||
22
src/Fermenter/FermenterSensor.cpp
Normal file
22
src/Fermenter/FermenterSensor.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
#include "FermenterSensor.h"
|
||||
|
||||
#include "sensors/Dallas.h"
|
||||
#include "sensors/DallasSensor.h"
|
||||
|
||||
#define SENSOR_GPIO D4
|
||||
|
||||
Dallas dallas(SENSOR_GPIO);
|
||||
|
||||
DallasSensor sensor(dallas, 0x3D0417C1D740FF28, 5);
|
||||
|
||||
double temperature = NAN;
|
||||
|
||||
void sensorSetup() {
|
||||
dallas.begin();
|
||||
}
|
||||
|
||||
void sensorLoop() {
|
||||
dallas.loop();
|
||||
sensor.loop();
|
||||
temperature = sensor.getLastValue();
|
||||
}
|
||||
10
src/Fermenter/FermenterSensor.h
Normal file
10
src/Fermenter/FermenterSensor.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef SENSOR3_FERMENTERSENSOR_H
|
||||
#define SENSOR3_FERMENTERSENSOR_H
|
||||
|
||||
extern double temperature;
|
||||
|
||||
void sensorSetup();
|
||||
|
||||
void sensorLoop();
|
||||
|
||||
#endif
|
||||
@ -156,20 +156,20 @@ void moistureLoop() {
|
||||
}
|
||||
}
|
||||
|
||||
bool patrix_command(char *first) {
|
||||
bool patrixCommand(char *first) {
|
||||
bool result = false;
|
||||
if (strcmp(first, "tempHigh") == 0 || strcmp(first, "th") == 0) {
|
||||
result = setDouble("tempHigh", &tempHigh, NAN, NAN);
|
||||
result = cmdReadDouble("tempHigh", &tempHigh, NAN, NAN);
|
||||
} else if (strcmp(first, "tempLow") == 0 || strcmp(first, "tl") == 0) {
|
||||
result = setDouble("tempLow", &tempLow, NAN, NAN);
|
||||
result = cmdReadDouble("tempLow", &tempLow, NAN, NAN);
|
||||
} else if (strcmp(first, "tempMillis") == 0 || strcmp(first, "tm") == 0) {
|
||||
result = setUint64_T("tempMillis", &tempMillis, NAN, NAN);
|
||||
result = cmdReadU64("tempMillis", &tempMillis, NAN, NAN);
|
||||
} else if (strcmp(first, "moistHigh") == 0 || strcmp(first, "mh") == 0) {
|
||||
result = setDouble("moistHigh", &moistHigh, NAN, NAN);
|
||||
result = cmdReadDouble("moistHigh", &moistHigh, NAN, NAN);
|
||||
} else if (strcmp(first, "moistLow") == 0 || strcmp(first, "ml") == 0) {
|
||||
result = setDouble("moistLow", &moistLow, NAN, NAN);
|
||||
result = cmdReadDouble("moistLow", &moistLow, NAN, NAN);
|
||||
} else if (strcmp(first, "moistMillis") == 0 || strcmp(first, "mm") == 0) {
|
||||
result = setUint64_T("moistMillis", &moistMillis, NAN, NAN);
|
||||
result = cmdReadU64("moistMillis", &moistMillis, NAN, NAN);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user