02-11-2025, 04:26 PM (Modification du message : 02-11-2025, 04:37 PM par Lolo69.)
Après avoir conduit au mode “demi-reset” avec la réduction du cycle et de la répartition des ON sur la sortie, on va pouvoir maintenant s attarder sur la partie algorithme du régulateur du routeur.
Le routeur d André est basé sur un régulateur Proportionnel Intégral Dérivée en ayant conservé que la partie Intégrale pour s affranchir des problèmes de période d échantillonnage et de pas de réglages.
Cette technique fonctionne plutôt bien et est bien adaptée mais ne permet pas des réactions rapides en cas de nuages qui passent ou de consommateurs électriques qui démarrent ou s arrêtent.
Plusieurs discussions sur le forum ont été écrites pour tenter d améliorer cet algorithme en introduisant de la proportionnelle, de la dérivée du feed forward mais aucune peut aboutir d un point de vue mathématique en raison du retard et de la fréquence d échantillonnage de la mesure trop faible pour ne pas faire rentrer le régulateur en auto oscillation.
Il n’y a donc rien à faire ?
He bien si …
Avant de vous expliquer le principe de l amélioration proposée je vais m attarder sur le principal inconvénient de l action intégrale pure.
On considère error comme l écart entre la mesure (de puissance totale) et la consigne ( seuil PW dans langage du routeur F1atb)
Tant que l erreur est positive l intégrale va augmenter son signal . Le signal continue d augmenter même si l erreur redescend. On est donc obligé d attendre de dépasser la consigne dans l autre sens pour réduire le signal. Cela provoque donc des autoscillations pour arriver à la stabilisation. Pour minimiser cet effet on est obligé d appliquer une réactivité relativement faible.
Le principe de la modification sera de surveiller le signe de la dérivée filtrée de l erreur. Si le changement de signe de cette erreur filtrée et dérivée est confirmé sur plusieurs échantillons, alors on met l intégration en pause car cela signifie que la bonne valeur de sortie est atteinte et donc inutile d aller plus loin et d attendre que la mesure repasse de l autre côté de la consigne.
Voila le décor est planté et l aperçu des programmes modifiés et résultat sur les courbes arriveront ici prochainement
// --- Détection robuste du changement de signe de la dérivée ---
bool signChange = (dot * dot_prev < 0) && (fabs(dot) > Dthres);
if (signChange) {
// Confirmer sur plusieurs échantillons pour éviter les rebonds dus au bruit
confirmCounter++;
} else {
if (confirmCounter > 0) confirmCounter--;
}
// Si la pente a vraiment changé de signe → on stoppe l’intégration
if (confirmCounter >= N_confirm) {
integratorEnabled = false;
}
// Si la dérivée revient dans le même signe que l’erreur → on redémarre
if ((dot * error) > 0 && fabs(dot) > Dthres) {
integratorEnabled = true;
confirmCounter = 0;
}
// --- INTÉGRATION ---
if (integratorEnabled) {
if (Puissance < SeuilPw && ReacCACSI > 1)
GainBoucle *= GainCACSI;
RetardF[i] += error * GainBoucle / 10000.0;
}
// --- Saturations ---
if (RetardF[i] < 100 - MaxTriacPw) RetardF[i] = 100 - MaxTriacPw;
if (ITmode < 0 && i == 0) RetardF[i] = 100;
if (RetardF[i] < 0) RetardF[i] = 0;
if (RetardF[i] > 100) RetardF[i] = 100;
Le fonctionnement
On gèle l’intégration dès que la dérivée change de signe (et dépasse le seuil Dthres).
L’intégrateur reste arrêté tant que la dérivée reste de signe opposé à celui de l’erreur (c’est-à-dire : le système est en train de revenir vers la consigne).
Dès que la dérivée reprend le même signe que l’erreur (donc que l’erreur repart dans le "mauvais" sens), l’intégration reprend automatiquement.
confirmCounter permet de filtrer les changements de signe rapides dus au bruit.
les tests d'aujourd'hui montrent une nette amélioration lors des passages nuageux /soleil mais comme c etait plutot pas de soleil, je n'ai pas pu prendre beaucoup de courbes qui montrent le progrès, je vous les posterai quand la méteo sera plus coopérative
Bonjour, je suis disponible pour des tests si besoin de bêta testeurs
Mon installation actuelle : pv 2600wc, rms 15.11 avec 3 ssr (CE 2000w, CE 2700w, marche forcée), UxI2 (jsy-mk-194g), et un rms nomade sur bain d'huile
Ici soleil et nuages actuellement, juste assez pour un ce et pour test avec fluctuations importantes
04-11-2025, 07:05 PM (Modification du message : 06-11-2025, 11:58 PM par Lolo69.)
Les résultats en images sur une journée assez ensoleillée
Les courbes sont plates et le pic de démarrage du frigo 120w crête sans routage au temps t-1 est quasiment absorbé et la courbe s aplatit en quelques secondes en sachant que le pas de réglage est de 1% c est à dire 20w dans le cas de mon convecteur 2kw)
Avec un routeur mesure Shelly, multisinus modifié (la même modif qui a conduit André à proposé le mode demi sinus ) et régulateur avec gel d intégrale dynamique
Seuil pw à -5
La même courbe avec les échelles zoomées
Petit exemple de cet algorithme en étant en découpe sinus et triac .
À t-2 démarrage pompe 1,2 kw très amortie et compensé en moins de 2 secondes.
06-11-2025, 06:57 PM (Modification du message : 06-11-2025, 07:00 PM par clyon44.)
Bonjour.
Test de la version spéciale de lolo69 en cette journée relativement ensoleillée, je dois dire que les courbes sont fantastiques c'est à peine croyable et très prometteur !
Routeur v16.04, mesures Shelly EM + sonde de température DS18B20
Triac Robodyn 24A/600V avec radiateur externe
Réglages réactivité 5, seuil de déclenchement -50, multi sinus
3 panneaux photovoltaïques Sunology Play 405W
Cumulus 200L 2200W méca 62°
06-11-2025, 08:04 PM (Modification du message : 06-11-2025, 08:08 PM par Lolo69.)
Merci Clyon44 pour ce retour d expérience.
Cela clos mes recherches sur la partie optimisation de la performance. On pourrait faire mieux avec un correcteur en Z on pourrait avoir des réponses visuellement droites comme des i , mais trop complexes à paramétrer par rapport au gain possible, autre voie possible un régulateur à logique floue pourrait donner de très bon résultats également, un peu plus simple que le correcteur en Z
Prochain chantier la refonte du serveur Web pour supprimer ce bug d affichage et enregistrement des paramètres , ce sera plus long car cela sors de mon domaine professionnel contrairement à la régulation.
Pour ceux qui veulent essayer ma version optimisée, faites moi signe en me précisément votre mode de mesure et la puissance électrique approximative de l appareil piloté
(06-11-2025, 08:04 PM)Lolo69 a écrit : Pour ceux qui veulent essayer ma version optimisée, faites moi signe en me précisément votre mode de mesure et la puissance électrique approximative de l appareil piloté
Le code actuel a des valeurs hardcodés en fonction du mode de mesure et de la puissance de l'appareil ?
Si tel est le cas, le mode de mesure peut être retrouvé dynamiquement via la variable globale Source :
Code :
if (Source == "ShellyEm") {
...
}
if (Source == "Linky") {
...
}
etc.
Concernant la puissance de l'appareil, une solution du "pauvre" qui n'impliquerait pas de rajouter un paramètre dans l'interface web pourrait être de mettre la puissance de l'appareil dans le titre de l'action par exemple Triac-2200W. Le code pourrait récupérer cette puissance depuis le titre via un code similaire à celui là :
Code :
int index = LesActions[i].Titre.lastIndexOf("-");
int puissanceAppareil = 0;
if (index > 0) {
puissanceAppareil = LesActions[i].Titre.substring(index + 1, LesActions[i].Titre.length() - 1).toInt();
}
if (puissanceAppareil == 0) {
StockMessage("Erreur : pas de puissance dans le titre " + LesActions[i].Titre);
}
Ça pourrait dépanner et permettre de rendre le code générique à moindre frais.
06-11-2025, 11:32 PM (Modification du message : 06-11-2025, 11:45 PM par Lolo69.)
Merci Mike
Ta réflexion est très judicieuse et met en avant ma connerie car la régulation n’est pas liée au mode de mesure donc finalement pas besoin de le savoir et donc pas besoin d aller chercher la variable!!!
Pour la puissance elle est effectivement nécessaire pour le régulateur que j ai pour l instant mis en dur.
Ta suggestion du pauvre est maligne car elle évite de rentrer dans la jungle du code de la page web en faisant un simple traitement de string. Je vais la mettre en place pour mes propres essais cela m évitera de refaire des compilations pour tester des ajustements de réglages, vraiment merci pour le tuyau
Je complèterai le traitement par “si pas de puissance dans le titre on reste sur l algorithme initial” et je choisirai un séparateur plus “complexe” pour éviter les “fausses” saisie
Si je vois qu il y a de la “demande” pour ce nouveau régulateur je prendrai quand même du temps pour rajouter un paramètre dans la page web ou la page action ce sera plus propre
( j en profiterai aussi pour mettre une boîte de saisie à la place d un slider pour la réactivité car le slider c’est fun mais au final peu pratique)
Si ce mode suscite de l’intérêt des forumeurs, je mettrai les détails du code ici
Avec plaisir, je suis content que ça puisse aider.
Concernant le choix du séparateur, je pense qu'il n'a pas nécessairement besoin d’être complexe, en gardant "-" comme séparateur, si par exemple un utilisateur aurait une action ayant pour titre "Ballon-cuisine", au final puissanceAppareil sera à 0 car "cuisin".toInt() renverra 0.
On pourrait blinder le code un peu plus en vérifiant la présence d'un "W" comme dernier caractère en plus de la présence de "-" mais pas sur que cela soit vraiment nécessaire.
Si à l'occasion tu postes le code, je pense que ça intéresserait du monde et ça te permettrait d'avoir plus de feedback.