Test naive bang-bang control algorithm for temperature
This commit is contained in:
@@ -102,12 +102,6 @@ void PWM_SetValue(int port, int value)
|
|||||||
|
|
||||||
n = CLAMP(value, 100, 0) * PWM_CYCLE_TOP / 100.0f;
|
n = CLAMP(value, 100, 0) * PWM_CYCLE_TOP / 100.0f;
|
||||||
|
|
||||||
Info("Setting duty cycle for %s to %d/%d...",
|
|
||||||
(port == FAN01) ? "FAN01" :
|
|
||||||
(port == FAN02) ? "FAN02" :
|
|
||||||
(port == FAN03) ? "FAN03" :
|
|
||||||
"UNKNOWN", n, PWM_CYCLE_TOP);
|
|
||||||
|
|
||||||
switch (port) {
|
switch (port) {
|
||||||
case PD4: OCR1B = n; break;
|
case PD4: OCR1B = n; break;
|
||||||
case PD5: OCR1A = n; break;
|
case PD5: OCR1A = n; break;
|
||||||
|
|||||||
54
src/main.c
54
src/main.c
@@ -6,6 +6,17 @@
|
|||||||
|
|
||||||
#include <avr/interrupt.h>
|
#include <avr/interrupt.h>
|
||||||
|
|
||||||
|
#define HYSTERESIS 1.0f
|
||||||
|
|
||||||
|
// https://en.wikipedia.org/wiki/Bang%E2%80%93bang_control
|
||||||
|
// https://support.75f.io/hc/en-us/articles/360044956794-Deadband-and-Hysteresis
|
||||||
|
// https://www.elotech.de/fileadmin/user_upload/PID-Regelungsgrundlagen.pdf
|
||||||
|
// https://thomasfermi.github.io/Algorithms-for-Automated-Driving/Control/PID.html
|
||||||
|
// https://www.ni.com/en/shop/labview/pid-theory-explained.html
|
||||||
|
// https://en.wikipedia.org/wiki/Proportional%E2%80%93integral%E2%80%93derivative_controller
|
||||||
|
// https://ctms.engin.umich.edu/CTMS/index.php?example=Introduction§ion=ControlPID
|
||||||
|
// https://www.youtube.com/watch?v=wkfEZmsQqiA&list=PLn8PRpmsu08pQBgjxYFXSsODEF3Jqmm-y
|
||||||
|
|
||||||
enum state_e
|
enum state_e
|
||||||
{
|
{
|
||||||
S_IDLE,
|
S_IDLE,
|
||||||
@@ -121,6 +132,7 @@ static void Update(void)
|
|||||||
{
|
{
|
||||||
char ch;
|
char ch;
|
||||||
cmd_t cmd;
|
cmd_t cmd;
|
||||||
|
float terr;
|
||||||
|
|
||||||
// Parse serial commands
|
// Parse serial commands
|
||||||
while ((ch = UART_Getc()) >= 0) {
|
while ((ch = UART_Getc()) >= 0) {
|
||||||
@@ -137,13 +149,48 @@ static void Update(void)
|
|||||||
// Get latest sensor values
|
// Get latest sensor values
|
||||||
FetchSensorValues();
|
FetchSensorValues();
|
||||||
|
|
||||||
// Handle state
|
// Two-step (bang-bang) controller testing
|
||||||
|
|
||||||
|
// TODO: Sanity check setpoint!
|
||||||
|
// TODO: Check thermistor for overheating!
|
||||||
|
// TODO: PID control for fan pulse-width modulation?
|
||||||
|
|
||||||
|
// The dead band represents the lower and upper limits
|
||||||
|
// of the error between which the controller doesn’t
|
||||||
|
// react.
|
||||||
|
|
||||||
|
state = S_IDLE;
|
||||||
|
terr = temp - temp_target;
|
||||||
|
|
||||||
|
if (terr < -HYSTERESIS) {
|
||||||
|
state = S_HEAT_UP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (terr > HYSTERESIS) {
|
||||||
|
state = S_COOL_DOWN;
|
||||||
|
}
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case S_IDLE:
|
case S_IDLE:
|
||||||
|
MOS_Disable(MOS01);
|
||||||
|
MOS_Disable(MOS02);
|
||||||
|
PWM_SetValue(FAN01, 20);
|
||||||
|
PWM_SetValue(FAN02, 20);
|
||||||
|
PWM_SetValue(FAN03, 20);
|
||||||
break;
|
break;
|
||||||
case S_HEAT_UP:
|
case S_HEAT_UP:
|
||||||
|
MOS_Enable(MOS02);
|
||||||
|
MOS_Disable(MOS01);
|
||||||
|
PWM_SetValue(FAN01, 20);
|
||||||
|
PWM_SetValue(FAN02, 60);
|
||||||
|
PWM_SetValue(FAN03, 60);
|
||||||
break;
|
break;
|
||||||
case S_COOL_DOWN:
|
case S_COOL_DOWN:
|
||||||
|
MOS_Enable(MOS01);
|
||||||
|
MOS_Disable(MOS02);
|
||||||
|
PWM_SetValue(FAN01, 60);
|
||||||
|
PWM_SetValue(FAN02, 60);
|
||||||
|
PWM_SetValue(FAN03, 60);
|
||||||
break;
|
break;
|
||||||
case S_DEHUMIDIFY:
|
case S_DEHUMIDIFY:
|
||||||
break;
|
break;
|
||||||
@@ -213,6 +260,11 @@ static void FetchSensorValues(void)
|
|||||||
Info("T3=%.2fC, TD3=%.2fC, RH3=%.2f%%, NT3=%.2fC", t[2], td[2], rh[2], t[5]);
|
Info("T3=%.2fC, TD3=%.2fC, RH3=%.2f%%, NT3=%.2fC", t[2], td[2], rh[2], t[5]);
|
||||||
Info("T_AVG=%.2fC, TD_AVG=%.2fC, RH_AVG=%.2f%%", temp, dewp, rhum);
|
Info("T_AVG=%.2fC, TD_AVG=%.2fC, RH_AVG=%.2f%%", temp, dewp, rhum);
|
||||||
Info("T_TAR=%.2fC, TD_TAR=%.2fC", temp_target, dewp_target);
|
Info("T_TAR=%.2fC, TD_TAR=%.2fC", temp_target, dewp_target);
|
||||||
|
Info("STATE=%s", (state == S_IDLE) ? "S_IDLE" :
|
||||||
|
(state == S_HEAT_UP) ? "S_HEAT_UP" :
|
||||||
|
(state == S_COOL_DOWN) ? "S_COOL_DOWN" :
|
||||||
|
(state == S_DEHUMIDIFY) ? "S_DEHUMIDIFY" :
|
||||||
|
"UNKNOWN");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
|
|||||||
Reference in New Issue
Block a user