PID et ESPHOME

Bonjour à tous,

Je suis actuellement de faire un thermostat pour gérer de vieux sèche serviette avec pilotage en hystérésis. j’ai déjà fait l’exercice l’année dernière avec un arduino sans la composante domotique et qui fonctionnait pas trop mal et aujourd’hui, l’idée est de faire la même avec ESP32, la variante étant ADU.

Par contre, avec un peu de recherche, j’ai une question :

Le système nécessite une régulation double couche dite en cascade avec un PID qui reçoit la consigne et la température ambiante de la pièce en entrée et qui sort une consigne puissance. ensuite la deuxième couche reçoit la sortie du premier niveau, plus la température du bain d’huile et régule sa puissance afin de respecter une consigne de température maximale de confort du bain d’huile.

Du coup, sous esp home, j’ai trouvé le script Climat qui semble être un PID mono niveau.

Ma question est donc, pensez vous qu’il soit possible d’appeler 2 fois le “climat:” de suite pour générer la cascade PID ?

je commence ce matin à faire une bread board avec un C6 que j’ai en stock, par contre, ça va faire un peu gros, va falloir que je prenne plus petit genre un C1 mini.

Salut,

Si tu ne partages pas d’infos ou de sources sur les scripts dont tu parles ça va être compliqué, car tu ne vas pouvoir avoir de réponse que par des gens qui ont fait exactement ce que tu cherches, ce qui limite pas mal surement les potentielles aides.

Bonjour,

en effet ça peut aider.

Alors de base, le principe d’un PID à double boucle ou encore PID en cascade :

Les avantages de la régulation en cascade | Watlow .

d’origine, mon code sous Arduino ressemblait à ça :

float TempAdjust = -2;
float LastRoomHum = 0;
float temperaturePiece = 0;
float CorrectedPartTemp = 0;
float HeatTemp = 0;
constexpr float pasDeLaConsigne = 0.50; // 0.5°C par cran
float consignePiece = 23;
constexpr float HeatTempMax = 40;

// PID
double entreePiece, sortiePiece, consignePIDPiece;
double kpPiece = 1, kiPiece = 0.5, kdPiece = 1;

double entreeChauffe, HeatOutput, consignePIDChauffe;
double kpChauffe = 2, kiChauffe = 0.8, kdChauffe = 4;

PID pidPiece(&entreePiece, &sortiePiece, &consignePIDPiece, kpPiece, kiPiece, kdPiece, DIRECT);
PID pidChauffe(&entreeChauffe, &HeatOutput, &consignePIDChauffe, kpChauffe, kiChauffe, kdChauffe, DIRECT);

void calculPID() {
  entreePiece = temperaturePiece;
  consignePIDPiece = consignePiece;
  pidPiece.Compute();
  
  consignePIDChauffe = sortiePiece;
  if (consignePIDChauffe > HeatTempMax) {
    consignePIDChauffe = HeatTempMax;
  }

  entreeChauffe = HeatTemp;
  pidChauffe.Compute();
}

l’idée est d’utiliser ce composant :

Donc en gros, en travaillant mon code à partir de la doc amis aussi de perplexity.ai (je ne suis pas un programmeur fou) :

# Consignes modifiables HA/local (step 0.5)
number:
  - platform: template
    name: "Temp Consigne"
    id: temp_consigne
    min_value: 15
    max_value: 30
    step: 0.5
    initial_value: 25
    optimistic: true
    update_interval: never
  - platform: template
    name: "Heater Max Temp"
    id: heater_max_temp
    min_value: 30
    max_value: 50
    step: 1
    initial_value: 35
    optimistic: true
    update_interval: never

# PID interne: limite Temp_Heater (output: PWM)
climate:
  - platform: pid
    name: "PID Heater Limit"
    id: pid_inner
    sensor: temp_heater
    heat_output: pwm_heater
    control_parameters:
      kp: 10
      ki: 1
      kd: 0.1
    autotune_action:
      - climate.pid.autotune

# PID externe: Temp ambiante → target pour inner PID
  - platform: pid
    name: "PID Ambient Control"
    id: pid_outer
    sensor: temp
    heat_output: target_setter  # Custom cascade
    control_parameters:
      kp: 5
      ki: 0.5
      kd: 0.05
    autotune_action:
      - climate.pid.autotune

# Cascade: PID outer → target inner PID
output:
  - platform: template
    id: target_setter
    type: float
    write_action:
      - climate.control:
          id: pid_inner
          target_temperature: !lambda 'return state;'

# Mise à jour consignes PID toutes les 10s
interval:
  - interval: 10s
    then:
      - climate.control:
          id: pid_outer
          target_temperature: !lambda 'return id(temp_consigne).state;'
      - climate.control:
          id: pid_inner
          target_temperature: !lambda 'return id(heater_max_temp).state;'

Mais je voulais avoir votre avis parce que je comprends pas encore le fonctionnement du YAML et de ESPHOME. et dans ce code, est ce bien cette boucle (Interval) qui pilote la mise à jour des consignes ?

De ce que j’en sais (j’ai utilisé qu’une seule fois), le composant PID climate de ESPHome attend en entrée une consigne et une mesure de température, et il fournit en sortie une consigne entre 0 et 100%
Je doute qu’il soit explicitement prévu pour être cascadé.
Après tu peux sans doute utiliser la sortie 0-100% pour la mettre en forme (dans un template ou un lambda) pour entrer dans un autre composant climate.
Mais ça dépasse largement mes compétences, aussi bien en matière de YAML qu’en matière de regulation PID…
Déjà qu’un PID simple c’est pas simple justement, alors cascadé c’est pour les barbus de l’automatique.

Je te remercie pour ton retour.

je suis en train de finaliser toutes les étapes du programme (fonctionnalités primaires) pour avoir un système fonctionnel en dehors de cette fonction PID. comme ça une fois fait, je pourrais expérimenter avec les retours des logs pour voir si je peux cascader ou pas.

je vous tiens au courant des avancées dès que la plateforme de test est fonctionnelle.