/* Copyright (c) 2025 Rodrigo Arias Mallo * SPDX-License-Identifier: GPL-3.0-or-later */ #include "thermostat.h" #define TEMP_MIN 35.0 /* °C */ #define DELTA_LOW 1.0 #define DELTA_HIGH 1.0 #define T_ERR_MIN 35.0 /* °C */ void thermostat_set(struct thermostat *th, float temp_target) { if (th->st == THERMOSTAT_ON && th->temp_target == temp_target) return; th->st = THERMOSTAT_ON; th->temp_target = temp_target; th->temp_min = temp_target - DELTA_LOW; th->temp_max = temp_target + DELTA_HIGH; th->on = 1; } void thermostat_off(struct thermostat *th) { th->st = THERMOSTAT_OFF; th->on = 0; } static float pid(float T0, float T, float dT_dt) { float err_min = 2.0; /* The rate of change of error is the same as the temperature, as they * are only offset by a mostly constant value */ float derr_dt = dT_dt; if ((T0 - T) < err_min) return 0.0; float Kp = 1.0 / 20.0; float Kd = - 1.0 / 3.0; float u = Kp * (T0 - T) + Kd * dT_dt; if (u < 0.0) u = 0.0; else if (u > 1.0) u = 1.0; return u; } /* Return a value in [0, 1] to set the heater duty cycle */ float thermostat_state(struct thermostat *th, float T, float dT_dt) { if (th->st == THERMOSTAT_OFF) return 0.0; return pid(th->temp_target, T, dT_dt); }