Smart Thermostat - le chauffage contrôlé par PID

Salut
A priori, aucune chance que le PID devienne instable si on ajoute la précommande de température extérieure.
Il n’y a pas de raison. En effet pour que le PID devienne instable, puisque la boucle fermée est par rapport à la température interne, il faudrait que tu ajoutes une composante liée à la température interne comme par exemple Ce*(Tint-Text)… ou des termes dérivés ou intégrales.

Je ne connais pas python mais je vois déjà qu’il manquerait un service à l’utilitaire intégrale:

C’est la remise à zéro…
Je pensais m’y mettre ou me faire un template mais pour cela je me demande comment récupérer la valeur de la précédente mesure…

Malheureusement, je ne parle pas l’ajax couramment :rofl:

Oui, je pense que le risque est faible, mais je pense que le gain par rapport au PID seul ne sera pas énorme non plus. Je vais implémenter la température extérieure, au pire c’est un coefficient à laisser à 0 par défaut et on revient au PID standard.

Oui en prenant les équations de température et le retour PID, la précommande en température (Tconsigne -Texterne) peut être sortie de la partie qui donne la stabilité.
A priori, elle permet d’avoir une partie intégrale plus stable puisque ce sera elle qui fera la partie long terme.
Pour moi, grâce à une mesure de consommation, ce serait dommage de m’en priver car il est simple de calculer cette compensation en regardant ce que le chauffage consomme en mode autonome avec son propre thermostat. Par exemple dans ma maison j’ai environ 100W/°, c’est à dire que je dois injecter 1000W en permanence pour un delta (Tinterne - Texterne) de 10°.

Bonsoir, je suis repassé avec la config standard et je n’ai pas de bon résultat:

climate:
  - platform: smart_thermostat
    name: Smart Thermostat Example
    heater: input_boolean.chauffe_radiateur_2
    target_sensor: sensor.zigbeechambre_temperature
    min_temp: 12
    max_temp: 25
    ac_mode: False
    target_temp: 18
    keep_alive:
      seconds: 60
    away_temp: 14
    kp : 75
    ki : 0.001
    kd : 70000
    pwm : 00:10:00

Attention, les gains indiqués dans l’exemple ne sont pas un « standard », ce sont des valeurs que j’ai utilisées sur mon installation (séche serviette 750W dans une salle de bain de 8m² en RT2012).

Sur les courbes on voit bien qu’à la moindre baisse de la température le chauffage est activé (et j’ai l’impression qu’il est au taquet). C’est le gain Kd qui est bien trop élevé, je ne sais pas quel type de chauffage tu as, mais mes gains correspondent plus à un radiateur qui va chauffer très fort.
Mon séche serviette a une forte inertie au démarrage mais une fois que la température ambiante commence à grimper elle accélère très vite, d’où le 70000.

Commence peut-être avec ces gains là :
Kp: 50
Ki: 0.01
Kd: 200

Et surveille la température. Pas besoin de laisser tourner très longtemps, déjà voir le comportement en 3 ou 4 heures sur un step de consigne peut aider à ajuster les gains.

Ce qui aide aussi beaucoup, c’est de récupérer les valeurs p, i et d calculées par le PID, en plus de la somme des trois qui est ensuite limitée à 0/100%. On peut le faire via des sensor template dans le fichier yaml de configuration de HA, ou alors faire rêver directement les attributs via ApexChart.

sensor:
  - platform: template
    sensors:
      smart_thermostat_output:
        friendly_name: PID Output
        unit_of_measurement: "%"
        value_template: "{{ state_attr('climate.salle_de_bain', 'control_output') | float }}"
      smart_thermostat_p:
        friendly_name: PID P
        unit_of_measurement: "%"
        value_template: "{{ state_attr('climate.salle_de_bain', 'pid_p') | float }}"
      smart_thermostat_i:
        friendly_name: PID I
        unit_of_measurement: "%"
        value_template: "{{ state_attr('climate.salle_de_bain', 'pid_i') | float }}"
      smart_thermostat_d:
        friendly_name: PID D
        unit_of_measurement: "%"
        value_template: "{{ state_attr('climate.salle_de_bain', 'pid_d') | float }}"

Et après dans la configuration du serveur on fait recharger les entités modèles, et on peut ensuite trouver les 4 sensors dans Lovelace pour tracer mais courbes. Ca permet de voir qui domine à chaque instant et donc quel gain monter ou quel gain descendre.

@lulakhub : J’ai fait un système de test de l’autotune, qui le fasse tourner de façon instantanée en se basant sur tes extractions, et après un peu de changement dans son process, il m’a sorti ça :
Set Kp, Ki, Kd. Smart thermostat now runs on PID Controller. 2.0242282110256964, 0.004151792253579836, 246.73078516749413

Est-ce que tu pourrais essayer de désactiver l’autotune dans ta configuration et mettre les paramètres qu’il a calculé pour les trois gains, stp ? Après redémarrage de HA, surveille l’évolution de la température, si c’est stable, je publierai un update de l’autotuner.
Merci.

Hello, c’est fait j’ai redémarré avec les nouveaux paramètres pour Kp, Ki et Kd.
Merci, j’espère que ca va être stable :slight_smile:

j’ai mis en place un graph pour surveiller les paramètres du PID comme tu me l’as conseillé avec ApexChart! (c’est top comme outil :slight_smile: )
Par contre je trouve étonnant que mon PID output oscille toujours entre 0 et 100 %. ll ne prend jamais de valeurs intermédiaires. Si j’ai bien compris le fonctionnement normalement le pourcentage Output représente le ratio du temps pendant lequel le radiateur est allumé pendant l’intervalle de temps défini par PWM. Donc si j’ai 100 il est allumé pendant les 10 minutes.

Oui le PID envoie sa commande aux radiateurs en PWM: pulse width modulation.
C’est à dire sur une fenêtre de temps donnée: X% à fond et (1-X)% éteint.
Je ne connais pas comment se comporte ce PID mais j’ai l’impression que ta fenêtre de temps est de 30mn (4 activations en 2 heures) et pas 10mn, ce qui ne permet pas de bien voir la moyenne des signaux.
En regardant tes courbes, je suis étonné de voir 0% sur la partie intégrale et une valeur énorme sur la partie dérivée. Pour un système comme le chauffage d’une maison, j’aurais plutôt ajouté au proportionnel (comme le post initial de @Argonaute) de l’intégrale plutôt qu’une dérivée.

C’est très étrange que la dérivée soit aussi élevée, je ne vois pas de variation importante de la température mesurée. Si on prend les formules :
P = Kp * error
I = last_I + (Ki * error * dt)
D = -(Kd * di) / dt
output = P + I + D

Le P à 3.9% indique une erreur de -1.9 pour une température à 17.9, donc j’en comprends que ta consigne est à 16°C. Sur le graph il semble que ça ait baissé de 0.1°C depuis l’échantillon précédent, avec un temps de 10 minutes soit 600 secondes. Donc la dérivée devrait être de -(246 * (-0.1) / 600 = 0.041 donc pas de quoi chauffer à 100%. L’intégrale est restée à 0, c’est normal, y’a un système anti-emballement qui bloque l’intégration quand la sortie est à 0% ou à 100%, donc vu que la sortie n’a fait que 0 ou 100%, l’intégrale n’a jamais bougé.

Pour avoir 1428 sur le D, il faudrait qu’il y ait eu une chute de température de 3482°C ou alors une baisse de 0.1°C entre deux échantillons séparés de seulement 17 millisecondes :thinking:

J’ai refais un export des datas du thermostat, et j’ai remarqué que à un événement précis j’ai le calcul du PI_d qui est réalisé trois fois avec des valeurs différentes.

state attributes.7 attributes.8 attributes.9 attributes.11 attributes.12 attributes.13 attributes.14 attributes.15 attributes.16 attributes.17 attributes.18 last_updated created old_state_id
heat current_temperature:18.6 temperature:16.0 hvac_action:idle control_output:0 pid_p:-5.343967200000002 pid_i:0.0 pid_d:-0.0 autotune_status:off Kp:2.02423 Ki:0.00415 Kd:246.73078 20/11/2021 17:01 20/11/2021 17:01 4445173
heat current_temperature:18.6 temperature:16.0 hvac_action:idle control_output:100.0 pid_p:-5.182028799999998 pid_i:0.0 pid_d:9495.25310221029 autotune_status:off Kp:2.02423 Ki:0.00415 Kd:246.73078 20/11/2021 17:01 20/11/2021 17:01 4445526
heat current_temperature:18.6 temperature:16.0 hvac_action:heating control_output:100.0 pid_p:-5.182028799999998 pid_i:0.0 pid_d:9495.25310221029 autotune_status:off Kp:2.02423 Ki:0.00415 Kd:246.73078 20/11/2021 17:01 20/11/2021 17:01 4445535

Ces trois événements ont la même date: 20/11/2021 17:01:04

@lulakhub : Essaie de mettre un sampling_period à 5mn, ça devrait filtrer ces faux échantillons.

forcer le temps d’échantillonnage oui ou aussi, peut être, aussi filtrer les mesures
c’est ce qui me gène avec les dérivées quand on ne maîtrise pas bien les entrées et leur instant de production.
On se retrouve avec des pics. Là un filtre de quelques minutes devrait peut être suffire.

C’est la difficulté de ce système, on ne maîtrise pas quand les échantillons arrivent (c’est selon le sensor, qu’on ne pilote pas), du coup il faut prévoir dans le code de zapper tout ce qui risque de poser des problèmes, et configurer correctement les différents paramètres de temps.

@lulakhub : En testant l’autotune avec 18°C de setpoint (j’ai l’impression que la température oscille autour de 18°C plutôt que les 17°C indiqués dans l’export) l’autotune me donne les coefficients suivants en fonction de chaque règle :

Tuning rule ziegler-nichols:
	Kp = 3.510770803497692
	Ki = 0.008831109627570399
	Kd = 348.92307293445987
Tuning rule tyreus-luyben:
	Kp = 2.7128683481573073
	Ki = 0.001535408832975308
	Kd = 342.3776184638279
Tuning rule ciancone-marlin:
	Kp = 1.8085788987715383
	Ki = 0.010008590911246453
	Kd = 177.52913549976262
Tuning rule pessen-integral:
	Kp = 4.263078832818626
	Ki = 0.013404362827562213
	Kd = 509.7050259837438
Tuning rule some-overshoot:
	Kp = 1.9894367886486921
	Ki = 0.005004295455623226
	Kd = 527.261532434295
Tuning rule no-overshoot:
	Kp = 1.1936620731892154
	Ki = 0.003002577273373936
	Kd = 316.35691946057705
Tuning rule brewing:
	Kp = 47.74648292756861
	Ki = 0.018015463640243614
	Kd = 1998.0437018562754

Je vais publier une nouvelle version avec des améliorations dans le processing de l’autotuner.

Hello, après une bonne nuit d’utilisation j’ai de très bon résultats. Sûrement grâce à l’échantillonnage. Il faut que je refasse un test avec un Delta T plus important par rapport à la consigne pour voir comment réagis le système.

voici les paramètres du PID:

    kp : 2.02423
    ki : 0.00415
    kd : 246.73078

J’ai quelques questions:

Je remarque que mon output oscille toujours entre 0 et 100 mais prend aussi quelques valeurs intermédiaires ce qui n’était pas le cas jusqu’à présent.

Lors de la descente de la chauffe des impulsions de 41 sec ont étaient envoyées au radiateur. (voir screen ci dessous entre 21:00 et 23:00. Est ce qu’il serait possible d’éviter de piloter le radiateur pendant ces courts intervalles?
en tous cas ca avance bien! :blush:

Quelques screen:

courbes PID
image

Historique régulation:

J’ai essayé de synthétiser un peu, n’hésitez pas me signaler les incohérences et idées, je mettrait à jour :

1 « J'aime »

C’et très intéressant tout ca. Par contre un truc physique me freine.
Mes chauffages sont controlé par des switch zigbee qui font « tic » a chaque changement d’ordre. J’imagine que la, l’enchainement est bien plus frequent sur les ordres et donc bien plus nuisible de façon sonore … particulièrement dans une chambre

Oui et mal réglé ça peut aussi les abimer…