From 2b8c250bc7fc94587ced003e7135ec49b57b53c1 Mon Sep 17 00:00:00 2001 From: Markus Kuhn Date: Mon, 27 Jan 2025 22:00:30 +0100 Subject: [PATCH] PID tuning, continued --- ToDo | 3 +++ aquaPi/machineroom/__init__.py | 29 +++++++++++++++++++---------- aquaPi/machineroom/ctrl_nodes.py | 1 + aquaPi/machineroom/out_nodes.py | 6 +++--- 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/ToDo b/ToDo index 185e175..da2d0e6 100644 --- a/ToDo +++ b/ToDo @@ -7,6 +7,9 @@ aquaPi ToDo list # startup behaviour of bus isn't good - let everybody post its data as response to HELLO? # on Raspi driver TC420 finds a device although there's none +- Logging to systemd journal? see https://trstringer.com/systemd-logging-in-python/ + This article also covers systemctl services + - Navigation: / Home, a configurable dashboard /settings Controllers, with foldable groups containing Controllers & their in/out diff --git a/aquaPi/machineroom/__init__.py b/aquaPi/machineroom/__init__.py index 5872d20..618d31b 100644 --- a/aquaPi/machineroom/__init__.py +++ b/aquaPi/machineroom/__init__.py @@ -110,6 +110,7 @@ def create_default_nodes(self) -> None: COMPLEX_TEMP = SIM_TEMP and False if REAL_CONFIG: + # __Lighting__ # # single PWM dimmed LED bar, perceptive correction light_schedule = ScheduleInput('Zeitplan Licht', '* 14-21 * * *') @@ -121,7 +122,7 @@ def create_default_nodes(self) -> None: light_c = SunCtrl('Leuchtbalken', light_schedule.id, xscend=1.0) light_pwm = AnalogDevice('Dimmer', light_c.id, - 'PWM 0', percept=True, maximum=85) + 'PWM 0', percept=True, maximum=75) light_schedule.plugin(self.bus) light_c.plugin(self.bus) light_pwm.plugin(self.bus) @@ -131,22 +132,29 @@ def create_default_nodes(self) -> None: [light_schedule.id, light_c.id]) # , light_pwm.id]) history.plugin(self.bus) - # single water temp sensor, switched relay - wasser_i = AnalogInput('Wasser', 'DS1820 xA2E9C', 25.0, '°C', - avg=1, interval=180) + # __Temperatures__ # + # single water temp sensor + # 2-point switched relay or triac ... + #wasser_i = AnalogInput('Wasser', 'DS1820 xA2E9C', 25.0, '°C', + # avg=1, interval=60) #wasser = MinimumCtrl('Temperatur', wasser_i.id, 25.0) #wasser_o = SwitchDevice('Heizstab', wasser.id, - # 'GPIO 12 out', inverted=True) + # 'GPIO 12 out', inverted=False) + + # ... or PID driven triac (relay has increased wear, not recomm.) + # PID for my 60cm/100W: sensor cycle 300s, PID 1.0/0.05/5, PWM 10s + wasser_i = AnalogInput('Wasser', 'DS1820 xA2E9C', 25.0, '°C', + avg=1, interval=300) wasser = PidCtrl('PID Temperatur', wasser_i.id, 25.0, - p_fact=1.5, i_fact=0.1, d_fact=0.) + p_fact=1.0, i_fact=0.05, d_fact=5.0) wasser_o = SlowPwmDevice('Heizstab', wasser.id, - 'GPIO 12 out', inverted=True, cycle=90) + 'GPIO 12 out', inverted=False, cycle=10) wasser_i.plugin(self.bus) wasser.plugin(self.bus) wasser_o.plugin(self.bus) # air temperature, just for the diagram - wasser_i2 = AnalogInput('Wasser 2', 'DS1820 x7A71E', 25.0, '°C', + wasser_i2 = AnalogInput('Raumluft', 'DS1820 x7A71E', 25.0, '°C', avg=2, interval=60) wasser_i2.plugin(self.bus) @@ -165,6 +173,7 @@ def create_default_nodes(self) -> None: coolspeed.id]) # , cool.id]) t_history.plugin(self.bus) + # __CO2__ # adc_ph = AnalogInput('pH Sonde', 'ADC #1 in 3', 2.49, 'V', avg=3, interval=30) calib_ph = ScaleAux('pH Wert', adc_ph.id, 'pH', @@ -172,7 +181,7 @@ def create_default_nodes(self) -> None: points=[(2.99, 4.0), (2.51, 6.9)]) ph = MaximumCtrl('pH Steuerung', calib_ph.id, 6.7) - ph_broken = True + ph_broken = False # True if ph_broken: # WAR broken CO2 vent: # pulse it, as CO2 only flows when partially opened @@ -257,7 +266,7 @@ def create_default_nodes(self) -> None: wasser = PidCtrl('Temperaturregler', wasser_i.id, 25.0, p_fact=1.5, i_fact=0.1, d_fact=0.) wasser_o = SlowPwmDevice('Heizstab', wasser.id, - 'GPIO 12 out', inverted=True, cycle=20) + 'GPIO 12 out', inverted=False, cycle=20) wasser.plugin(self.bus) wasser_o.plugin(self.bus) wasser_i.plugin(self.bus) diff --git a/aquaPi/machineroom/ctrl_nodes.py b/aquaPi/machineroom/ctrl_nodes.py index 1e8b5fc..894a052 100644 --- a/aquaPi/machineroom/ctrl_nodes.py +++ b/aquaPi/machineroom/ctrl_nodes.py @@ -272,6 +272,7 @@ def listen(self, msg) -> bool: log.brief('PID -> %f (%+.1f)', self.data, -val * 100) self.post(MsgData(self.id, round(self.data, 4))) + #FIXME: test a permanent err_sum leak of 1% or 10% , avoid windup if self.data <= 0. or self.data >= 100.: self._err_sum /= 2 self._err_old = err diff --git a/aquaPi/machineroom/out_nodes.py b/aquaPi/machineroom/out_nodes.py index 1592329..670293c 100644 --- a/aquaPi/machineroom/out_nodes.py +++ b/aquaPi/machineroom/out_nodes.py @@ -234,9 +234,9 @@ def set(self, perc: float) -> None: def get_settings(self) -> list[tuple]: settings = super().get_settings() settings.append(('cycle', 'PWM cycle time', self.cycle, - 'type="number" min="10" max="300" step="1"', - 'inverted', 'Inverted', self.inverted, - 'type="number" min="0" max="1"')) + 'type="number" min="10" max="300" step="1"')) + settings.append(('inverted', 'Inverted', self.inverted, + 'type="number" min="0" max="1"')) # FIXME 'class="uk-checkbox" type="checkbox" checked' fixes appearance, but result is always False ) return settings