Plugin thermostat et gestion PAC air / air

Oui, tout est en Auto coté clim chez moi.
J’ai repassé la saturation de l’intégrale à +1,9 / -1,9°C (pas besoin de plus chez moi, en tout cas dans cette pièce).
Ca tourne bien :

J’ai reçu mes sonde ds18b20 (pour les autres splits), mais je les ai renvoyées, car le câblage dans la maison aurait été trop lourd. J’ai commandé à la place :

  • des sondes bluetooth Xiaomi Mijia
  • des sondes SONOFF SNZB-02D Zigbee + Dongle USB ZBDONGLE-E
    → je ferai la comparaison (intégration Jeedom, réception signal, précision, fréquence rafraichissement, …) pour voir lesquelles je conserve.

Hello,

image

La température est à 17,7°C depuis 10h20 (il est 10h45) pour une consigne de 18°C.
Je trouve que la consigne donné à la PAC (17 à 10h45) remonte trop doucement, non ?

Tu es sûr qu’il fallait diviser par 2 ? :blush:

Bonjour,
Je ne sais pas si c’est normal, mais ca ne me choque pas d’avoir 0,3°C d’écart le temps que le système rejoigne la consigne…
Rien de t’empêche d’augmenter le Ki, il faut juste vérifier que la commande envoyée à la clim ne fasse pas trop le yoyo (exemple 23 puis 19 puis 23 toutes les 5min…).
Je vais l’augmenter un peu de mon coté, pour voir si ca gagne un peu en dynamique.

Pour ce qui est de la théorie :
Si tu as 0,3°C d’écart et que tu intègres toutes les 10min, au bout de 30min (si l’erreur reste à 0,3), l’intégrateur vaudra 0,3 x 3 = 0,9.
Si tu fais cela toutes les 5min, il vaudra 0,3 x 6 = 1,8, donc oui il faut le diviser par 2, si tu veux les mêmes réglages que moi.
Ces réglages sont à adapter en fonction de la pièce (volume, isolation, …) et du split. Le jeu que j’ai fourni est une base de travail, à chacun d’adapter. :wink:

Merci pour tes infos.
Tu as un site qui explique tout cela ? je n’ai pas trop trouvé :frowning:

Qlq liens :

http://www.ferdinandpiette.com/blog/2011/08/implementer-un-pid-sans-faire-de-calculs/
http://linuxcnc.org/docs/2.5/html/motion/pid_theory_fr.html

Merci. Les 1er liens piquent un peu :rofl:
Je continuerai à lire toutefois.
Edit : le lien ferdinandpiette est le plus clair et le plus simple d’approche.

Oui, pour la compréhension, il est top.
Il manque la partie anti-saturation de l’actionneur.

Dans la litérature, j’ai l’impression qu’on ne trouve que de la théorie enseignée à l’école et peu d’exemples de code de PID à implémenter.

Oui, je n’ai pas trouvé d’algorithme.
Et le lien qui est bien, je l’ai implémenté pour voir. Et bon, pas satisfait de la valeur de commande…
J’aurais bien aimé un plugin qui gère ma climatisation. Je pensais m’y pencher, mais je n’y comprends pas énormément au final…

J’aurais bien aimé un plugin qui gère mon chauffage. Je pensais m’y pencher, mais je ne sais pas faire de plugin. :wink:

Ici le code de ma fonction Regulation PID sous Node-RED

Ok, je vois le code de Node.
C’est du javascript, je le mettrai en PHP pour le mettre dans un scénario PHP.
Mon but sera d’y comprendre un peu plus.
Un petit challenge en soi. :slight_smile:

En attendant, le code de Pierrot69/Bisons tourne bien chez moi depuis 2 jours.
Et le soleil est revenu pour chauffer la maison en prime, la climatisation va se retrouver de plus en plus éteinte.

Edit : ah, c’est pour une vanne thermostatique.
Je regarde toutefois le code concernant les calculs
Y’a vraiment un besoin en tout cas pour la clim et pour les vannes…

Bonjour,
Je reviens donner des nouvelles après qlq mois.
Pour ce qui est des sondes, j’ai testé les sondes Xiaomi Mijia lywsd03mmc et SONOFF SNZB-02D voir ici :

Du coup, je reste avec les lywsd03mmc, je vais essayer de souder une antenne pour améliorer la portée.

Mon scénario tourne toutes les 5 min (peu de gain a faire plus rapide).
J’ai modifié l’action dérivé pour la filtrer (ajout d’une variable en plus).
Je pilote le split de l’espace chambre et le split du salon via 2 PID indépendants.
Ca marche bien.

Le chauffage historique de la maison étant une chaudière gaz (Saunier Duval piloté par Migo), j’ai fait des scénarios qui active / désactive la PAC ou la chaudière en fonction de la Température extérieure. En effet, si trop froid, la PAC tourne à fond (on l’entend à l’intérieur), et perd en efficacité, donc je switch sur la chaudière. J’ai défini un seuil avec hystérésis (désactivation PAC à 2°C et réactivation à 4°C) pour le switch, on va voir ce que ca donne quand les grands froids vont arriver.

Bonjour à tous,
Comme j’ai eu la question par ailleurs en perso, j’en profite pour reposter ici sur la config finale de mes splits que j’utilise pour chauffer. Initialement je passais par des scénarios, mais j’ai migré sur le plugin agenda il y a 2 ans environ.
Les thermostats (1/split) :
Programmation en hystérésis, comme ce sont des splits, je ne gère pas du On/Off mais des consignes de chauffe ou de maintien en fonction de la température de la pièce :

J’ai 2 scénarios qui gèrent l’allumage de la clim, l’envoi de la consigne de chauffe, ou l’arrêt :

Pour les modes, j’ai un virtuel de sélection des températures, et je récupère la valeur dans chaque mode. J’ai également une variable qui me sert à laisser la clim allumée, j’y reviendrai plus tard, et une notif via Jeedom Connect sur le tél :



image

Scénario d’allumage :
Le principe est le suivant :
Si clim éteinte, on l’allume et on choisit le mode chaud ou froid (lié au plugin de ma clim) en fonction du mode du Thermostat. Puis on envoie l’ordre de chauffe. Si la clim est allumée, on n’envoie que l’ordre de chauffe. J’ai été obligé de faire ça, car c’est lié au fonctionnement du plugin Thermostat qui passe soit par la fonction allumage, soit par le changement de consigne en fonction de l’état du Thermostat au moment du changement d’état.

Scénario d’envoi ordre :
Si la clim est allumée, on définit la consigne en fonction de l’état du Thermostat dans une variable :

  • Si le Thermostat doit chauffer (Tpièce < Tconsigne), on envoie Tconsigne + 5*hystérésis
  • Si le Thermostat est arrêté (Tpièce >= Tconsigne), on envoie simplement la consigne pour le maintien de la pièce.
    Cela permet de ne pas faire de Off sur la clim.
    La variable hystérésis est à 0,5 chez moi.

Scénario Off :
Quand j’arrête le Thermostat, j’ai un scénario qui se lance en provoqué sur la commande Off :


Ensuite pour la programmation je gère par 2 types de mode : saison et mode chauffage. Pour saison j’en ai 3 : Hiver/mi-saison et été. Pour le mode chauffage, j’en ai 4 : Travail / Vacances / Absence / WE-JF. En fonction de ces 2 modes j’ai un agenda derrière pour gérer les horaires du Thermostat associé :

Les « modes chauffage » Travail / Vacances et WE-JF lancent un scénario qui active l’agenda correspondant et désactive les autres :
Mode :

Scénario mode chauffage :



Les modes saison Hiver et mi-saison lancent un scénario qui permet de repasser par le mode Travail / Vacances, etc… actif pour relancer le scénario précédent + activer/désactiver un scénario qui permet de passer automatiquement de Travail la semaine à WE les WE/jours fériés et inversement.
Mode :

Scénario WE-Travail auto :

Les modes Absence et Eté désactivent tout.
Voilà, j’ai ensuite d’autres modes mais qui sont liés à la maison : blocage de la clim si le poêle est allumé pour ne pas la lancer, maintien de la maison à une température si la température est trop basse dehors pour ne pas trop rattraper le soir, gestion des radiateurs des chambres à allumer ou pas, etc… mais le gros du fonctionnement est décrit ci-dessus, j’espère que c’est clair 

1 « J'aime »

Bonjour,

En préambule merci beaucoup pour ce code. :slightly_smiling_face:
Cela fait un moment que je cherchais à faire fonctionner mes clim en mode chauffage avec une température constante

J’ai des sondes de température GOVEE H5075 qui envoit l’info à chaque 0,1°C
Ce qui déclenche en permence le scénario

Que faut il modifier pour une variation tous les 0,5°C ?

------------------------------------
[2024-12-31 15:19:48][SCENARIO] -- Début : Scenario execute automatiquement sur evenement venant de : [Salon][Sonde New][Temperature] (20.1).
[2024-12-31 15:19:48][SCENARIO] - Exécution du sous-élément de type [action] : code
[2024-12-31 15:19:48][SCENARIO] Exécution d'un bloc code
[2024-12-31 15:19:48][SCENARIO] |----------------------------------------------------------
[2024-12-31 15:19:48][SCENARIO] |  Consigne Salon : 21.3 °C / Temperature Salon : 20.1 °C
[2024-12-31 15:19:48][SCENARIO] |----------------------------------------------------------
[2024-12-31 15:19:48][SCENARIO] | .Correct_integr (valeur précédente) : 2.6
[2024-12-31 15:19:48][SCENARIO] | .Correct_erreur_previous (valeur précédente) : 1.1
[2024-12-31 15:19:48][SCENARIO] | .Correct_erreur : 1.2 -> mémorisation de la valeur
[2024-12-31 15:19:48][SCENARIO] | .Correct_prop : 2.4
[2024-12-31 15:19:48][SCENARIO] | .Correct_integr : 3.8
[2024-12-31 15:19:48][SCENARIO] | .Correct_integr borné [-2.6 / 2.6] : 2.6 -> mémorisation de la valeur
[2024-12-31 15:19:48][SCENARIO] | .Correct_deriv : 0.15
[2024-12-31 15:19:48][SCENARIO] | .Correct_total : 5.15
[2024-12-31 15:19:48][SCENARIO] | .Correct_total borné [-5 / 5] : 5
[2024-12-31 15:19:48][SCENARIO] | .Temp_consign_clim : 26
[2024-12-31 15:19:48][SCENARIO] | .Temp_consign_clim borné [15 / 24] : 24
[2024-12-31 15:19:48][SCENARIO] |----------------------------------------------------------
[2024-12-31 15:19:48][SCENARIO] - Exécution du sous-élément de type [condition] : if #[Salon][Sonde New][Température]# != tag(set_consign_clim)
[2024-12-31 15:19:48][SCENARIO] Evaluation de la condition : [20.1 != 24] = Vrai
[2024-12-31 15:19:48][SCENARIO] - Exécution du sous-élément de type [action] : then
[2024-12-31 15:19:48][SCENARIO] Exécution de la commande [Climatisation][Climatisation du Salon][Température] avec comme option(s) : {"background":"0","slider":24}
[2024-12-31 15:19:48][SCENARIO] Fin correcte du scénario
------------------------------------
[2024-12-31 15:19:53][SCENARIO] -- Début : Scenario execute automatiquement sur evenement venant de : [Salon][Sonde New][Temperature] (20.2).
[2024-12-31 15:19:53][SCENARIO] - Exécution du sous-élément de type [action] : code
[2024-12-31 15:19:53][SCENARIO] Exécution d'un bloc code
[2024-12-31 15:19:53][SCENARIO] |----------------------------------------------------------
[2024-12-31 15:19:53][SCENARIO] |  Consigne Salon : 21.3 °C / Temperature Salon : 20.2 °C
[2024-12-31 15:19:53][SCENARIO] |----------------------------------------------------------
[2024-12-31 15:19:53][SCENARIO] | .Correct_integr (valeur précédente) : 2.6
[2024-12-31 15:19:53][SCENARIO] | .Correct_erreur_previous (valeur précédente) : 1.2
[2024-12-31 15:19:53][SCENARIO] | .Correct_erreur : 1.1 -> mémorisation de la valeur
[2024-12-31 15:19:53][SCENARIO] | .Correct_prop : 2.2
[2024-12-31 15:19:53][SCENARIO] | .Correct_integr : 3.7
[2024-12-31 15:19:53][SCENARIO] | .Correct_integr borné [-2.6 / 2.6] : 2.6 -> mémorisation de la valeur
[2024-12-31 15:19:53][SCENARIO] | .Correct_deriv : -0.15
[2024-12-31 15:19:53][SCENARIO] | .Correct_total : 4.65
[2024-12-31 15:19:53][SCENARIO] | .Correct_total borné [-5 / 5] : 4.65
[2024-12-31 15:19:53][SCENARIO] | .Temp_consign_clim : 26
[2024-12-31 15:19:53][SCENARIO] | .Temp_consign_clim borné [15 / 24] : 24
[2024-12-31 15:19:53][SCENARIO] |----------------------------------------------------------
[2024-12-31 15:19:53][SCENARIO] - Exécution du sous-élément de type [condition] : if #[Salon][Sonde New][Température]# != tag(set_consign_clim)
[2024-12-31 15:19:53][SCENARIO] Evaluation de la condition : [20.2 != 24] = Vrai
[2024-12-31 15:19:53][SCENARIO] - Exécution du sous-élément de type [action] : then
[2024-12-31 15:19:53][SCENARIO] Exécution de la commande [Climatisation][Climatisation du Salon][Température] avec comme option(s) : {"background":"0","slider":24}
[2024-12-31 15:19:53][SCENARIO] Fin correcte du scénario

Merci et bon réveillon à toutes la communauté Jeedom :partying_face:

Salut,

Ce serait un paramètre au niveau de ta sonde qu’il faudrait modifier (ou tricher avec un virtuel mais pas simple).

A l’utilisation je fonctionne différemment maintenant et je fais tourner le scénario à intervalle constant, ici toutes les 5mn et donc plus de déclenchement sur changement de la température réelle (il faudra adapter les variables). En effet, la température ne varie quand même pas si vite que ça et même si c’est le cas (comme chez toi) on voit bien que ça ne sert à rien de faire varier la consigne si souvent donc 5mn me parait bien :slight_smile:

Actuellement je suis là dessus … à tester et adapter au besoin (suivant la pièce, les déperditions, etc …)

$Kp = 2;
$Ki = 0.6; // 0.5 au lieu de 1 car polling 5mn au lieu de 10mn ; Puis 0.6
$Kd = 0.7; // 0.7 au lieu de 1.5 car polling de 5mn au lieu de 10mn
$borne_min_integr = -1.9; // -1.9 au lieu de -2.6
$borne_max_integr = 1.9; // 1.9 au lieu de 2.6
$borne_min_total = -2; // -1 au lieu -5 pour limiter la coupure nette du compresseur
$borne_max_total = 5;
$borne_min_pac = 15;
$borne_max_pac = 24;

Bonjour,

Merci pour ton conseil
Je vais effectivement faire exécuter le scénario toutes les 5 minutes.

Par contre je ne retrouve pas ces 3 variables dans ton code d’origine ?


$Consigne_Salon = cmd::byString('#[Climatisation][Gestion PAC][Consigne Confort Salon]#')->execCmd();
$Temperature_Salon = cmd::byString('#[Salon][Sonde][Température]#')->execCmd();

$Kp = 2;
$Ki = 0.6; // 0.5 au lieu de 1 car polling 5mn au lieu de 10mn ; Puis 0.6
$Kd = 0.7; // 0.7 au lieu de 1.5 car polling de 5mn au lieu de 10mn
$borne_min_integr = -1.9; // -1.9 au lieu de -2.6
$borne_max_integr = 1.9; // 1.9 au lieu de 2.6
$borne_min_total = -2; // -1 au lieu -5 pour limiter la coupure nette du compresseur
$borne_max_total = 5;
$borne_min_pac = 15;
$borne_max_pac = 24;

 $scenario->setLog('|----------------------------------------------------------');
 $scenario->setLog('|  Consigne Salon : ' . $Consigne_Salon . ' °C / ' . 'Temperature Salon : ' . $Temperature_Salon . ' °C');
 $scenario->setLog('|----------------------------------------------------------');

$Correct_integr = $scenario->getData('Correct_integr',0);
 $scenario->setLog('| .Correct_integr (valeur précédente) : ' . $Correct_integr);
$Correct_erreur_previous = $scenario->getData('Correct_erreur_previous',0);
 $scenario->setLog('| .Correct_erreur_previous (valeur précédente) : ' . $Correct_erreur_previous);

$Correct_erreur = $Consigne_Salon - $Temperature_Salon;
 $scenario->setLog('| .Correct_erreur : ' . $Correct_erreur . ' -> mémorisation de la valeur');

$Correct_prop = 2 * $Correct_erreur;
 $scenario->setLog('| .Correct_prop : ' . $Correct_prop);

$Correct_integr = $Correct_integr + $Correct_erreur;
$Correct_integr = round($Correct_integr * 1000) / 1000;
 $scenario->setLog('| .Correct_integr : ' . $Correct_integr);
$Correct_integr = max(min($Correct_integr, $borne_max_integr), $borne_min_integr);
 $scenario->setLog('| .Correct_integr borné ['.$borne_min_integr.' / '.$borne_max_integr.'] : ' . $Correct_integr . ' -> mémorisation de la valeur');

$Correct_deriv = 1.5 * ($Correct_erreur - $Correct_erreur_previous);
 $scenario->setLog('| .Correct_deriv : ' . $Correct_deriv);

$Correct_total = $Correct_prop + $Correct_integr + $Correct_deriv;
 $scenario->setLog('| .Correct_total : ' . $Correct_total);
$Correct_total = max(min($Correct_total, $borne_max_total), $borne_min_total);
 $scenario->setLog('| .Correct_total borné ['.$borne_min_total.' / '.$borne_max_total.'] : ' . $Correct_total);

$Temp_consign_clim = round($Consigne_Salon + $Correct_total);
 $scenario->setLog('| .Temp_consign_clim : ' . $Temp_consign_clim);
$Temp_consign_clim = max(min($Temp_consign_clim, $borne_max_pac), $borne_min_pac);
 $scenario->setLog('| .Temp_consign_clim borné ['.$borne_min_pac.' / '.$borne_max_pac.'] : ' . $Temp_consign_clim);
 $scenario->setLog('|----------------------------------------------------------');

$scenario->setData('Correct_integr', $Correct_integr);
$scenario->setData('Correct_erreur_previous', $Correct_erreur);

$tags['#set_consign_clim#'] = $Temp_consign_clim;
$scenario->setTags($tags);

Re,

Voici ce que nous dit l’IA

// Récupération des données des capteurs et des consignes
// ----------------------------------------------------------------------
// On récupère la consigne (température cible) et la température actuelle
// via les commandes spécifiques de Jeedom.
$Consigne_Salon = cmd::byString('#[Climatisation][Gestion PAC][Consigne]#')->execCmd();
$Temperature_Salon = cmd::byString('#[Salon][Sonde][Température]#')->execCmd();

// Définition des coefficients du PID
// ----------------------------------------------------------------------
// Ces coefficients déterminent le poids de chaque composante dans le calcul.
// Kp (proportionnel) : ajustement immédiat en fonction de l'écart actuel.
// Ki (intégral) : correction basée sur l'erreur cumulée dans le temps.
// Kd (dérivé) : correction basée sur l'évolution de l'erreur (anticipation).
$Kp = 2;   // Coefficient proportionnel
$Ki = 0.6; // Coefficient intégral ajusté
$Kd = 0.7; // Coefficient dérivé ajusté

// Définition des bornes pour limiter les corrections
// ----------------------------------------------------------------------
// Ces limites garantissent que le régulateur PID reste dans des valeurs
// acceptables pour la régulation et protège l'équipement (PAC).
$borne_min_integr = -1.9; // Limitation minimum pour la composante intégrale
$borne_max_integr = 1.9;  // Limitation maximum pour la composante intégrale
$borne_min_total = -2;    // Limitation minimum pour la correction totale
$borne_max_total = 5;     // Limitation maximum pour la correction totale
$borne_min_pac = 15;      // Température minimale pour la consigne PAC
$borne_max_pac = 26;      // Température maximale pour la consigne PAC

// Logging des données initiales
// ----------------------------------------------------------------------
// On enregistre dans les logs la consigne et la température actuelle
// pour faciliter le suivi et le débogage.
$scenario->setLog('|----------------------------------------------------------');
$scenario->setLog('| Consigne Salon : ' . $Consigne_Salon . ' °C / ' . 'Température Salon : ' . $Temperature_Salon . ' °C');
$scenario->setLog('|----------------------------------------------------------');

// Vérification des valeurs des capteurs
// ----------------------------------------------------------------------
// Si les valeurs des capteurs ou de la consigne ne sont pas valides
// (exemple : capteur défaillant ou données manquantes), on arrête le script.
if (!is_numeric($Consigne_Salon) || !is_numeric($Temperature_Salon)) {
    $scenario->setLog('| ERREUR : Les valeurs des capteurs ou de la consigne ne sont pas valides.');
    return; // Arrêt du script
}

// Récupération des données stockées lors de l'exécution précédente
// ----------------------------------------------------------------------
// Ces données sont nécessaires pour les calculs intégral et dérivé.
// - Correct_integr : somme des erreurs passées (composante intégrale).
// - Correct_erreur_previous : dernière erreur enregistrée (pour la dérivée).
$Correct_integr = $scenario->getData('Correct_integr', 0);
$Correct_erreur_previous = $scenario->getData('Correct_erreur_previous', 0);

// Calcul de l'erreur actuelle
// ----------------------------------------------------------------------
// L'erreur correspond à la différence entre la consigne et la température actuelle.
// Si cette erreur est positive, il fait trop froid ; si elle est négative, il fait trop chaud.
$Correct_erreur = $Consigne_Salon - $Temperature_Salon;
$scenario->setLog('| Erreur calculée : ' . $Correct_erreur . ' (Consigne - Température)');

// Calcul de la composante proportionnelle
// ----------------------------------------------------------------------
// Cette composante agit directement sur l'erreur actuelle, amplifiée par Kp.
$Correct_prop = $Kp * $Correct_erreur;
$scenario->setLog('| Composante proportionnelle : ' . $Correct_prop);

// Calcul de la composante intégrale
// ----------------------------------------------------------------------
// Cette composante cumule les erreurs passées pour corriger un décalage persistant.
// On applique un facteur Ki et on limite cette valeur dans les bornes définies.
$Correct_integr += $Correct_erreur * $Ki; // Intégration de l'erreur
$Correct_integr = round($Correct_integr, 3); // Limitation à 3 décimales pour éviter les imprécisions
$Correct_integr = max(min($Correct_integr, $borne_max_integr), $borne_min_integr); // Bornage
$scenario->setLog('| Composante intégrale (bornée) : ' . $Correct_integr);

// Calcul de la composante dérivée
// ----------------------------------------------------------------------
// Cette composante anticipe les variations de l'erreur (exemple : éviter les oscillations).
// On calcule la différence entre l'erreur actuelle et l'erreur précédente, amplifiée par Kd.
$Correct_deriv = $Kd * ($Correct_erreur - $Correct_erreur_previous);
$scenario->setLog('| Composante dérivée : ' . $Correct_deriv);

// Calcul de la correction totale
// ----------------------------------------------------------------------
// La correction totale est la somme des trois composantes (P, I, D).
// On applique des bornes pour garantir que cette correction reste dans une plage acceptable.
$Correct_total = $Correct_prop + $Correct_integr + $Correct_deriv;
$Correct_total = max(min($Correct_total, $borne_max_total), $borne_min_total); // Bornage
$scenario->setLog('| Correction totale (bornée) : ' . $Correct_total);

// Calcul de la nouvelle consigne pour la climatisation
// ----------------------------------------------------------------------
// La nouvelle consigne est obtenue en ajoutant la correction totale à la consigne initiale.
// On limite ensuite cette valeur dans les bornes admissibles pour la PAC.
$Temp_consign_clim = round($Consigne_Salon + $Correct_total);
$Temp_consign_clim = max(min($Temp_consign_clim, $borne_max_pac), $borne_min_pac); // Bornage
$scenario->setLog('| Nouvelle consigne climatisation (bornée) : ' . $Temp_consign_clim);

// Détection d'écart important
// ----------------------------------------------------------------------
// Si l'écart entre la consigne et la température actuelle dépasse 5°C,
// on enregistre une alerte dans les logs (utile pour détecter un problème).
if (abs($Correct_erreur) > 5) {
    $scenario->setLog('| ATTENTION : Écart important détecté (' . $Correct_erreur . '). Vérifiez les capteurs ou la configuration.');
}

// Sauvegarde des données pour la prochaine exécution
// ----------------------------------------------------------------------
// On mémorise les valeurs nécessaires pour les calculs intégral et dérivé
// lors de la prochaine exécution.
$scenario->setData('Correct_integr', $Correct_integr);
$scenario->setData('Correct_erreur_previous', $Correct_erreur);

// Application de la nouvelle consigne
// ----------------------------------------------------------------------
// On met à jour la consigne pour la PAC via les tags Jeedom.
$tags['#set_consign_clim#'] = $Temp_consign_clim;
$scenario->setTags($tags);

// Fin du script et enregistrement des logs
// ----------------------------------------------------------------------
// Cette partie marque la fin de l'exécution, avec un log final.
$scenario->setLog('|----------------------------------------------------------');
$scenario->setLog('| Fin du traitement.');
$scenario->setLog('|----------------------------------------------------------');

J’ai pas regardé son arrangement mais chez moi c’est ça :

$Consigne_Salon = cmd::byString('#[Maison][Gestion des PAC][ConsigneConfortSalon]#')->execCmd();
//$Temperature_Salon = cmd::byString('#[Salon][Sensor Salon (MQTT)][Température]#')->execCmd();
$Temperature_Salon = cmd::byString('#[Maison][Temperatures MQTT][Salon (Moyenne)]#')->execCmd();

$Kp = 2;
$Ki = 0.6; // 0.5 au lieu de 1 car polling 5mn au lieu de 10mn ; Puis 0.6
$Kd = 0.7; // 0.7 au lieu de 1.5 car polling de 5mn au lieu de 10mn
$borne_min_integr = -1.9; // -1.9 au lieu de -2.6
$borne_max_integr = 1.9; // 1.9 au lieu de 2.6
$borne_min_total = -2; // -1 au lieu -5 pour limiter la coupure nette du compresseur
$borne_max_total = 5;
$borne_min_pac = 15;
$borne_max_pac = 24;

 $scenario->setLog('|----------------------------------------------------------');
 $scenario->setLog('|  Consigne Salon : ' . $Consigne_Salon . ' °C / ' . 'Temperature Salon : ' . $Temperature_Salon . ' °C');
 $scenario->setLog('|----------------------------------------------------------');

$Correct_integr = $scenario->getData('Correct_integr',0);
 $scenario->setLog('| .Correct_integr (valeur précédente) : ' . $Correct_integr);
$Correct_erreur_previous = $scenario->getData('Correct_erreur_previous',0);
 $scenario->setLog('| .Correct_erreur_previous (valeur précédente) : ' . $Correct_erreur_previous);

$Correct_erreur = $Consigne_Salon - $Temperature_Salon;
 $scenario->setLog('| .Correct_erreur : ' . $Correct_erreur . ' -> mémorisation de la valeur');

$Correct_prop = $Kp * $Correct_erreur;
 $scenario->setLog('| .Correct_prop : ' . $Correct_prop);

$Correct_integr = $Correct_integr + $Ki * $Correct_erreur; 
$Correct_integr = round($Correct_integr * 1000) / 1000;
 $scenario->setLog('| .Correct_integr : ' . $Correct_integr);
$Correct_integr = max(min($Correct_integr, $borne_max_integr), $borne_min_integr);
 $scenario->setLog('| .Correct_integr borné ['.$borne_min_integr.' / '.$borne_max_integr.'] : ' . $Correct_integr . ' -> mémorisation de la valeur');

$Correct_deriv = $Kd * ($Correct_erreur - $Correct_erreur_previous); // 0.7 au lieu de 1.5 car polling de 5mn au lieu de 10mn
 $scenario->setLog('| .Correct_deriv : ' . $Correct_deriv);

$Correct_total = $Correct_prop + $Correct_integr + $Correct_deriv;
 $scenario->setLog('| .Correct_total : ' . $Correct_total);
$Correct_total = max(min($Correct_total, $borne_max_total), $borne_min_total);
 $scenario->setLog('| .Correct_total borné ['.$borne_min_total.' / '.$borne_max_total.'] : ' . $Correct_total);

$Temp_consign_clim = round($Consigne_Salon + $Correct_total);
 $scenario->setLog('| .Temp_consign_clim : ' . $Temp_consign_clim);
$Temp_consign_clim = max(min($Temp_consign_clim, $borne_max_pac), $borne_min_pac);
 $scenario->setLog('| .Temp_consign_clim borné ['.$borne_min_pac.' / '.$borne_max_pac.'] : ' . $Temp_consign_clim);
 $scenario->setLog('|----------------------------------------------------------');

$scenario->setData('Correct_integr', $Correct_integr);
$scenario->setData('Correct_erreur_previous', $Correct_erreur);

$tags['#set_consign_clim#'] = $Temp_consign_clim;
$scenario->setTags($tags);

Bonjour,
Il dit surtout que tu as bien travaillé😊

1 « J'aime »

Bonjour,

Voici les differences entre ton code et celui de l’IA

$Correct_integr = $Correct_integr + $Ki * $Correct_erreur; 
$Correct_integr = round($Correct_integr * 1000) / 1000;

vs

$Correct_integr += $Correct_erreur * $Ki;
$Correct_integr = round($Correct_integr, 3);

Hello,

ça donne le même résultat, donc tout va bien l’IA n’a pas craqué :blush:

1 « J'aime »