Je viens
ENFIN de comprendre pourquoi, lorsque je passais mon interrupteur virtuel en "Off", mon radiateur chauffait quand même....
Je pense qu'il y a une petite erreur dans la fonction "compute(pid)" sur la séquence suivante :
Code : Tout sélectionner
Variable du script Lua :
pid['OnOff'] = 'Présence' -- Nom de l'interrupteur virtuel de mise en parche oui/non
pid['cycle'] = 10 -- temps en minute d'un cycle PID
function compute(pid)
< code >
-- à chaque cycle
if ( time.min%pid['cycle'] == 0 ) then
< code >
-- si l'on veut chauffer
if ( otherdevices[pid['OnOff']] == 'On' ) then
< code >
end
-- toutes les 15 minutes, si on ne veut pas chauffer
elseif ( otherdevices[pid['OnOff']] == 'Off' and time.min%15 == 0 ) then
< code >
end
Lorsque time.min est un multiple de pid['cycle'] et un multiple de 15, alors on ne rentre
jamais dans le "si on ne veut pas chauffer".
Chez moi le cycle est fixé à 5 minutes, du coup le premier test est satisfait toutes les 5 minutes, en particulier toutes les 15 minutes, même si je suis en otherdevices[pid['OnOff']] == 'Off'.
Dans l'exemple que tu fournis, avec un cycle à 10 minutes, le radiateur ne reçoit jamais d'ordre "Off" à time.min=0 ou 30 puisque la première condition est satisfaite (0%10=0 et 30%10=0).
Dans ce cas précis, l'ordre Off est envoyé toutes les 1/2h (hh:15 et hh:45) et non tous les 1/4h.
Dans mon cas, aucun ordre n'était envoyé
Il y a plusieurs solutions pour corriger, chacun adoptera la sienne, mais je pense qu'il conviendra d'en reporter une dans ton fichier modules.lua pour ceux qui le découvriraient seulement maintenant

Ou toute autre solution différente, bien entendu !
Je vous en propose 3.
Solution 1 :
Code : Tout sélectionner
function compute(pid)
< code >
-- à chaque cycle
if ( time.min%pid['cycle'] == 0 ) then
< code >
-- si l'on veut chauffer
if ( otherdevices[pid['OnOff']] == 'On' ) then
< code >
end
end
-- toutes les 15 minutes, si on ne veut pas chauffer
if ( otherdevices[pid['OnOff']] == 'Off' and time.min%15 == 0 ) then
< code >
end
Solution 2 :
Code : Tout sélectionner
function compute(pid)
< code >
-- à chaque cycle, si l'on veut chauffer
if ( time.min%pid['cycle'] == 0 and otherdevices[pid['OnOff']] == 'On') then
< code >
-- toutes les 15 minutes, si on ne veut pas chauffer
elseif ( otherdevices[pid['OnOff']] == 'Off' and time.min%15 == 0 ) then
< code >
end
Solution 3 :
Choisir le cycle et la fréquence pour ne pas chauffer tels que PPCM > 60
Par exemple : cycle = 7 et off toutes les 15 minutes car PPCM(7,15)=105
Par exemple : cycle = 7 et off toutes les 10 minutes car PPCM(7,10)=70
nb : PPCM = Plus Petit Commun Multiple, cf le Web pour ceux que ça intéresse
La solution 2 a l'avantage d'être plus lisible, et permet en plus de s'affranchir d'un IF THEN END qui avait pour seule condition otherdevices[pid['OnOff']] == 'On' : cette condition est remontée dans le test principal.
C'est cette solution que j'ai adoptée.
==========================================
J'ai apporté une autre modification à l'ordre de chauffe quand commande = 100%.
En effet, inutile de prévoir un "OFF AFTER Cycle + 20 secondes" puisqu'un nouvel ordre va arriver au prochain cycle... J'ai constaté que ça perturbait le fonctionnement pour la bonne et simple raison qu'au cycle d'après si on avait encore 100%, alors le radiateur recevait un Off au bout de 20 secondes...
Exemple avec cycle = 10 minutes
HH.00:00 : supposons que le calcul donne "commande = 100", le radiateur reçoit "ON" à HH:00:00 et "OFF AFFTER 620", càd "OFF" à HH:10:20
HH:10:00 : supposons à nouveau "commande = 100", le radiateur reçoit "ON" à HH:10:00 et "OFF AFFTER 620", càd "OFF" à HH:20:20
HH:10:20 : le radiateur reçoit le OFF envoyé à HH:00:00
Et ainsi de suite tant qu'on calcule 100%.
Donc 20 secondes de chauffe au lieu des 10 minutes attendues !
Avant modif :
Code : Tout sélectionner
-- action sur l'élément chauffant
if heatTime > 0 then
log(pid['zone']..' : Temp='..temp..', Consigne='..consigne..', Chauffage pendant '..string(round(heatTime/60,0))..' minutes')
commandArray[1] = {[pid['radiateur']] = marche}
commandArray[2] = {[pid['radiateur']] = arret..' AFTER '..heatTime}
else
log(pid['zone']..' : Temp='..temp..', Consigne='..consigne..', Pas de chauffage dans les '..pid['cycle']..' prochaines minutes')
commandArray[pid['radiateur']]=arret
end
Après modif :
Code : Tout sélectionner
-- action sur l'élément chauffant
if heatTime > 0 then
log(pid['zone']..' : Temp='..temp..', Consigne='..consigne..', Chauffage pendant '..string(round(heatTime/60,0))..' minutes')
commandArray[1] = {[pid['radiateur']] = marche}
if commande < 100 then
commandArray[2] = {[pid['radiateur']] = eco..' AFTER '..heatTime}
end
else
log(pid['zone']..' : Temp='..temp..', Consigne='..consigne..', Pas de chauffage dans les '..pid['cycle']..' prochaines minutes')
commandArray[pid['radiateur']]=arret
end
==========================================
Au final, j'ai adopté ce script plutôt que le précédent (ne pas m'en vouloir !).
Avec ces modifications il est très lisible et beaucoup plus facile à implémenter.
Seul bémol : la maintenance de modules.lua nécessite une connexion de type putty/ssh, mais en dehors de mon réseau local le proxy de mon employeur m'en empêche ^_^