[LUA] Chauffage PID

Vous avez crée un script lua dont vous êtes fier, un .sh génial, un programme python hors du commun, un tuto , c'est ici que vous pouvez les partager.
Soyez précis quant aux prérequis, les manips à faire pour que votre bijou fonctionne (des chmod ?, un apt-get à faire ...)
Décrivez précisément son fonctionnement
Entourez votre code source avec les balises Quote grâce au bouton correspondant
olorin
Messages : 19
Enregistré le : 08 nov. 2017, 16:36

Re: Chauffage PID

Message par olorin »

Salut tous le monde et merci pour ce petit script

Est-ce qu'il serait possible de rajouter dans le script un test de l'URL ?

En effet quand je rentrais toutes mes informations, j'avais fait une faute de frappe dans le mot de passe et du coup les curl ne passaient pas (ex: dans creaVar).
Et ça tournait en boucle sur "initialisation" dans les logs, sans savoir pourquoi.
On pourrait dire "paramètres URL KO, revoir vos paramètres domoticzIP/PORT/USER/PASSWD etc...." avec le code d'erreur de retour.
Ce sera plus explicite pour savoir où est le problème ;)

De plus j'aimerais a créer un script pour mettre une sonde de température virtuel pour effectuer une "moyenne" de température selon 3 ou 4 sondes. En prenant compte l'état de leur actualisation (si la sonde n'a plus de batterie et ne remonte plus la température depuis plus d'une heure, elle n'est plus prise en compte dans la moyenne)

vwstepha
Messages : 42
Enregistré le : 20 nov. 2014, 15:15

Re: Chauffage PID

Message par vwstepha »

Salut a tous.
Est ce que quelqu'un peut mettre en ligne la dernière version du script de ce beau projet. :D
Il y a tellement de modif. :o
Merci beaucoup!!!! :mrgreen:
Rpi 2B Dz V2020.1 stable master ;)
Rpi 3B Dz V2020.1 stable slave + Rflink + USB ZWAVE+ + Rflink RTS :ugeek:
Rpi 2A withRapItow 8-)
2xMijia Xiaomi V2 + acc
1x SP3
2xVR + 3xPC DIO Chacon
5x1 voie Sonoff (4 d'origine....1 seul flashé)

garycooper
Messages : 326
Enregistré le : 07 août 2017, 23:58

Re: [LUA] Chauffage PID

Message par garycooper »

Bonjour à tous, j'essaie d'ajouter la gestion du "Hors gel" dans la fonction "compute(pid)" mais apparemment je dois me tromper dans les conditions parce que maintenant je n'ai que le mode "Hors gel" qui fonctionne et le mode "Auto" ne fonctionne pas.
Quelques éléments de contexte pour expliquer plus précisément mon installation et ma configuration :
Il s'agit d'une résidence secondaire pilotée par Domoticz en filaire et je commande les fils pilotes de chaque radiateur via une carte relais et donc un script par radiateur. Dans Domoticz, j'ai un sélecteur avec les positions "Off / Hors gel / Auto / Manu", des thermostats "Eco", "Confort", "Hors gel" et un interrupteur "Programmateur chauffage" qui me servira de pour basculer entre "Confort" et "Eco" pendant la nuit. Ce que je souhaite faire, c'est :
1- En mode "hors gel" le chauffage est régulé selon la valeur du thermostat "hors gel" sans condition de la position du programmateur
2- En mode "Manu" le chauffage est régulé selon la valeur du thermostat "Confort" sans condition de la position du programmateur
3- En mode "Auto" le chauffage est régulé selon la valeur du thermostat "Confort" quand le programmateur est sur "On" et il passe en mode "Eco" quand le programmateur est sur "Off"

Le script de la fonction "Compute" est celui-ci :

Code : Tout sélectionner

function compute(pid)
                local init = 0
                local programmateur = 'Programmateur chauffage'

                -- récupération température
                local temp = getTemp(pid['sonde'])
                -- récupération température ext
                local temp_ext = nil
                if pid['sonde_ext'] ~= '' and pid['sonde_ext'] ~= nil then
                               temp_ext = getTemp(pid['sonde_ext'])
                end
                
                -- création variable : 4 dernières températures
                if (uservariables['PID_temps_'..pid['zone']] == nil ) then
                               creaVar('PID_temps_'..pid['zone'],string.rep(temp..';',3)..temp) 
                               init = 1
                end
                -- création variable : intégrale
                if (uservariables['PID_integrale_'..pid['zone']] == nil ) then
                               creaVar('PID_integrale_'..pid['zone'],'0')
                               init = 1
                end
                
                if init == 1 then
                               log('PID '..pid['zone']..' initialisation..',pid['debug'])
                               do return end
                end
                
                -- définition des variables locales
                local moy_erreur = 0
                local n = 1
                local somme_erreurs = 0
                local heatTime
                local marche
                local arret
                local tmp = {}

                -- définition des commandes marche/arrêt
                if pid['invert'] then
                               marche = 'Off' ; arret = 'On'
                else
                               marche = 'On' ; arret = 'Off'
                end
                
                -- à chaque cycle
                if ( time.min%pid['cycle'] == pid['freq'] ) then
                
                               -- maj des 4 dernières temps
                               local temps = string.match(uservariables['PID_temps_'..pid['zone']],";([^%s]+)")..";"..temp
                               commandArray[#commandArray+1] = {['Variable:PID_temps_'..pid['zone']] = temps}

                              


                               -- fonctionnement Auto

                               if ( otherdevices[pid['OnOff']] == 'Auto' ) then

                                               -- récupération de la consigne
                                               if ( otherdevices[pid['programmateur']] == 'On' ) then
                                                               consigne = tonumber(otherdevices_svalues[pid['thermostat']]) or pid['thermostat']
                                               else
                                                               consigne = tonumber(otherdevices_svalues[pid['thermostat_eco']]) or pid['thermostat_eco']
                                               end
 			       -- fonctionnement hors gel

                               elseif ( otherdevices[pid['OnOff']] == 'Hors gel' ) then
                                               consigne = tonumber(otherdevices_svalues[pid['thermostat_horsgel']]) or pid['thermostat_horsgel']

                               -- fonctionnement Manu

                               elseif ( otherdevices[pid['OnOff']] == 'Manu' ) then
                                               consigne = tonumber(otherdevices_svalues[pid['thermostat']]) or pid['thermostat']

                                               -- calcul de l'erreur
                                               local erreur = consigne-temp
                                               -- calcul intégrale auto consumée et moyenne erreur glissante
                                               temps:gsub("([+-]?%d+%.*%d*)",function(t)
                                                                                                                      tmp[n] = tonumber(t)
                                                                                                                      err = tonumber(consigne-t)
                                                                                                                      somme_erreurs = somme_erreurs+err
                                                                                                                      moy_erreur = moy_erreur+err*n^3
                                                                                                                      n = n+1
                                                                                                                      end)

                                               somme_erreurs = round(constrain(somme_erreurs,0,255),1)
                                               moy_erreur = round(moy_erreur/100,2)
                                               
                                               -- calcul de la dérivée (régression linéaire - méthode des moindres carrés)
                                               local delta_erreurs = round((4*(4*tmp[1]+3*tmp[2]+2*tmp[3]+tmp[4])-10*(tmp[1]+tmp[2]+tmp[3]+tmp[4]))/20,2)
                                               
                                               -- aux abords de la consigne, passage au second systême integrale
                                               if somme_erreurs < 2 then
                                                               somme_erreurs = tonumber(uservariables['PID_integrale_'..pid['zone']])
                                                               -- re calcule intégrale si hors hysteresis
                                                               -- à moins d'un dixièmes de degré d'écart avec la consigne
                                                               -- le ratrapage est considéré OK, l'intégrale n'est pas recalculée
                                                               if math.abs(erreur) > 0.11 then
                                                                              -- calcule intégrale
                                                                              somme_erreurs = round(constrain(somme_erreurs+erreur/2,0,5),2)
                                                                              -- maj
                                                                              commandArray[#commandArray+1] = {['Variable:PID_integrale_'..pid['zone']] = tostring(somme_erreurs)}
                                                               end
                                               end
                                               
                                               -- boucle ouverte,
                                               -- modification dynamique des paramètres de régulation suivant température extérieure
                                               local Kb = 0
                                               if temp_ext ~= nil then
                                                               Kb = pid['Kb'] * (consigne - temp_ext - pid['ref']) / 100
                                               end        
                                               pid['Kp'] = round(pid['Kp'] + pid['Kp'] * Kb)
                                               pid['Ki'] = round(pid['Ki'] + pid['Ki'] * Kb)
                                               pid['Kd'] = round(pid['Kd'] + pid['Kd'] * Kb)
                
                                               -- calcul pid
                                               local P = round(pid['Kp']*moy_erreur,2)
                                               local I = round(pid['Ki']*somme_erreurs,2)
                                               local D = round(pid['Kd']*delta_erreurs,2)
                                               
                                               -- calcul de la commande en %
                                               local commande = round(constrain(P+I+D,0,100))
                                                                              
                                               -- calcul du temps de fonctionnement
                                               if commande == 100 then
                                                               -- débordement de 20s pour ne pas couper avant recalcule
                                                               heatTime = (pid['cycle']*60)+20
                                               elseif commande > 0 then
                                                               -- secu mini maxi
                                                               heatTime = round(constrain(commande*pid['cycle']*0.6,pid['secu'],(pid['cycle']*60)-pid['secu']))
                                               elseif commande == 0 then
                                                               -- coupure retardée
                                                               heatTime = constrain(pid['secu']-lastSeen(pid['radiateur']),0,pid['secu'])
                                               end
                                               
                                               -- AFTER n'aime pas 1 ou 2..
                                               if heatTime == 1 or heatTime == 2 then
                                                               heatTime = 0
                                               end        
                                               
                                               -- action sur l'élément chauffant
                                               if heatTime > 0 then
                                                               commandArray[#commandArray+1] = {[pid['radiateur']] = marche}
                                                               commandArray[#commandArray+1] = {[pid['radiateur']] = arret..' AFTER '..heatTime}
                                               else
                                                               commandArray[#commandArray+1] = {[pid['radiateur']]=arret}
                                               end                                       
                               
                                               -- journalisation
                                               if pid['debug'] then
                                                               log('PID zone: '..string.upper(pid['zone']))
                                                               if temp_ext ~= nil then
                                                                              log('temperature ext: '..temp_ext..'°C')
                                                               end
                                                               log('température int: '..temp..'°C pour '..consigne..'°C souhaité')
                                                               log('Kp: '..pid['Kp'])
                                                               log('Ki: '..pid['Ki'])
                                                               log('Kd: '..pid['Kd'])
                                                               log('erreur: '..moy_erreur)
                                                               log('somme erreurs: '..somme_erreurs)
                                                               log('delta erreurs: '..delta_erreurs)
                                                               log('P: '..P)
                                                               log('I: '..I)
                                                               log('D: '..D)
                                                               log('cycle: '..pid['cycle']..'min (sécu: '..pid['secu']..'s)')
                                                               -- avertissement si secu dépasse 1/4 du cycle
                                                               if ((100*pid['secu'])/(60*pid['cycle'])>25) then
                                                                              warn('sécu trop importante, ralonger durée de cycle..')
                                                               end
                                                               log('commande: '..commande..'% ('..string.sub(os.date("!%X",heatTime),4,8):gsub("%:", "\'")..'\")')
                                                               log('')
                                               end
                                               
                                               -- maj sonde virtuelle
                                               --commandArray[#commandArray+1] = {['UpdateDevice'] = otherdevices_idx[pid['sonde']..'_pid']..'|0|'..temp..';'..commande..';0'}
                                               
                               end
                               
                end
                -- toutes les 15 minutes, si on ne veut pas chauffer
                if ( time.min%15 == 0 and otherdevices[pid['OnOff']] == 'Off' ) then

                               -- arrêt chauffage (renvoi commande systematique par sécurité)
                               commandArray[#commandArray+1] = {[pid['radiateur']] = arret..' AFTER '..constrain(pid['secu']-lastSeen(pid['radiateur']),3,pid['secu'])}
                               
                               -- maj sonde virtuelle
                               --commandArray[#commandArray+1] = {['UpdateDevice'] = otherdevices_idx[pid['sonde']..'_pid']..'|0|'..temp..';0;0'}
                end

end
et la partie qui, je pense, pose problème est celle de la définition de la consigne :

Code : Tout sélectionner

-- fonctionnement Auto
                if ( otherdevices[pid['OnOff']] == 'Auto' ) then
                        -- récupération de la consigne
                        if ( otherdevices[pid['programmateur']] == 'On' ) then
                              consigne = tonumber(otherdevices_svalues[pid['thermostat']]) or pid['thermostat']
                        else
                               consigne = tonumber(otherdevices_svalues[pid['thermostat_eco']]) or pid['thermostat_eco']
                        end
                        
-- fonctionnement hors gel
                elseif ( otherdevices[pid['OnOff']] == 'Hors gel' ) then
                               consigne = tonumber(otherdevices_svalues[pid['thermostat_horsgel']]) or pid['thermostat_horsgel']

-- fonctionnement Manu
                 elseif ( otherdevices[pid['OnOff']] == 'Manu' ) then
                                consigne = tonumber(otherdevices_svalues[pid['thermostat']]) or pid['thermostat']

ogulf
Messages : 383
Enregistré le : 15 juin 2017, 14:41

Re: [LUA] Chauffage PID

Message par ogulf »

Je pourrai rentrer dans le détail, mais chez moi je gère :
- chaque niveau de la maison de manière globale via un selector switch avec une consigne max à ne pas dépasser
- chaque pièce avec un selector switch sur les 4 ordres + un manuel
- chaque radiateur avec un selzctor switch qui communique l'ordre au récepteur fil pilote
- 2 thermostats Eco et Conf par pièce
- 1 thermomètre par pièce
- Et 1 script PID par pièce !

Pour illustrer, voici une copie partielle de Domoticz sur la gestion du chauffage du haut :
Screenshot_20211012-182428_Samsung Internet.jpg
Screenshot_20211012-182428_Samsung Internet.jpg (710.22 Kio) Vu 301 fois
Screenshot_20211012-184508_Samsung Internet.jpg
Screenshot_20211012-184508_Samsung Internet.jpg (633.04 Kio) Vu 301 fois
On peut lire que le Haut est à On ==> pas de limite max en Haut. Si j'avais positionné HG18, je précalcule un max à 18, à ne pas dépasser, et ce quelque soient les modes des pièces du Haut.

Ensuite, le salon : consigne Confort, le script récupéré la consigne Conf du salon : comme l'étage n'est pas borné, c'est cette consigne qui fait foi. Si jamais mis HG15, la consigne serait ramenée à 15 ! :mrgreen:

Ensuite, le radiateur : normalement je ne l'affiche pas, la c'est pour bien illustrer. C'est le selector qui commande le module fil pilote.
On peut constater que le script PID à mis le radiateur en Off.

Je répète avec la cuisine, la ch1, la ch2 etc.

Vient ensuite (2nde image) la température mesurée du salon, de la cuisine etc.

Et enfin les valeurs des consignes Eco et Conf de chaque pièce (pareil, normalement je ne les affiche pas).


Et je répète le tout pour le bas et les pièces du bas.


Ça fait usine à gaz, mais je peux en 2 actions mettre toute la maison en HG si vacances, juste un niveau si personne en bas etc.
Ça fait presque 4 ans que ça tourne comme ça 8-)

J'utilise les plannings par niveau et par zone (1 zone=1 pièce).
Je pourrais aussi modifier par planning chaque consigne de thermostat Eco et Conf.... mais là ça devient totalement ingérable !!! :D

Je peux partager un script PiD personnalisé si besoin ;)
Domoticz Stable sur RPi3 + RFPlayer + ZWave+ + RFLink R48 :
- 11 x RF660P
- 1 x FGSD-002
- 10 x F007TH
- 5 x Emcoluxr EV1527 + 4 x NAS-DS01Z
- 4 x NAS-PD02Z
- 1 x Shelly 1PM

garycooper
Messages : 326
Enregistré le : 07 août 2017, 23:58

Re: [LUA] Chauffage PID

Message par garycooper »

Effectivement, ça a l'air beaucoup plus complexe que ce que j'essaie de faire ... Mais je n'ai pas besoin de quelque chose d'aussi complet pour 50m2 :?

pronoob
Messages : 1
Enregistré le : 16 oct. 2021, 18:16

Re: [LUA] Chauffage PID

Message par pronoob »

Bonjour,

Merci d'avoir fait remonter ce sujet vers lequel je ne serais pas allé naturellement.
c'est sympa cette méthode de gestion et effectivement ça fonctionne au poil.

gary, as tu pensé à simplement faire une truc de ce genre ?

directement dans le script et non dans modules.lua

Code : Tout sélectionner

if otherdevice['Mode_chauffage'] == 'Auto' and otherdevice['programmateur'] == 'On' then
	pid['thermostat'] = 'thermostat'
elseif otherdevice['Mode_chauffage'] == 'Auto' and otherdevice['programmateur'] == 'Off' then
	pid['thermostat'] = 'thermostat_eco'
elseif otherdevice['Mode_chauffage'] == 'Hors gel' then
	pid['thermostat'] = 'thermostat_horsgel'
elseif otherdevice['Mode_chauffage'] == 'Manu' then
	pid['thermostat'] = 'thermostat'
end	
Bon je ne suis pas certain de l'exactitude mais ça donne l'idée ;)
je trouve personnellement cela plus simple à lire et ça évite de toucher à la fonction compute() ce qui en plus de faciliter les mises à jour, permet d'éventuellement faire autrement dans une autre zone de la maison

garycooper
Messages : 326
Enregistré le : 07 août 2017, 23:58

Re: [LUA] Chauffage PID

Message par garycooper »

Merci pour l'idée. Je suis tout de même resté sur la modification de la fonction "compute" parce que je n'ai pas d'intérêt à gérer mes chauffages indépendamment, hormis pour la température. Du coup, j'ai fini par m'en sortir en déplaçant un "end". Ce n'est pas très joli ou optimisé mais comme je ne maitrise pas le "elseif", j'ai procédé comme suit :

Code : Tout sélectionner

 			       -- fonctionnement hors gel
                               if ( otherdevices[pid['OnOff']] == 'Hors gel' ) then
                                               consigne = tonumber(otherdevices_svalues[pid['thermostat_horsgel']]) or pid['thermostat_horsgel']
			       end

                               -- fonctionnement Manu
                               if ( otherdevices[pid['OnOff']] == 'Manu' ) then
                                               consigne = tonumber(otherdevices_svalues[pid['thermostat']]) or pid['thermostat']
			       end

                               -- fonctionnement Auto
                               if ( otherdevices[pid['OnOff']] == 'Auto' ) then
                                               -- récupération de la consigne
                                               if ( otherdevices[pid['programmateur']] == 'On' ) then
                                                               consigne = tonumber(otherdevices_svalues[pid['thermostat']]) or pid['thermostat']
                                               else
                                                               consigne = tonumber(otherdevices_svalues[pid['thermostat_eco']]) or pid['thermostat_eco']
                                               end
                               end
La fonction "compute" devient donc :

Code : Tout sélectionner

function compute(pid)
                local init = 0
                local programmateur = 'Programmateur chauffage'

                -- récupération température
                local temp = getTemp(pid['sonde'])
                -- récupération température ext
                local temp_ext = nil
                if pid['sonde_ext'] ~= '' and pid['sonde_ext'] ~= nil then
                               temp_ext = getTemp(pid['sonde_ext'])
                end
                
                -- création variable : 4 dernières températures
                if (uservariables['PID_temps_'..pid['zone']] == nil ) then
                               creaVar('PID_temps_'..pid['zone'],string.rep(temp..';',3)..temp) 
                               init = 1
                end
                -- création variable : intégrale
                if (uservariables['PID_integrale_'..pid['zone']] == nil ) then
                               creaVar('PID_integrale_'..pid['zone'],'0')
                               init = 1
                end
                
                if init == 1 then
                               log('PID '..pid['zone']..' initialisation..',pid['debug'])
                               do return end
                end
                
                -- définition des variables locales
                local moy_erreur = 0
                local n = 1
                local somme_erreurs = 0
                local heatTime
                local marche
                local arret
                local tmp = {}

                -- définition des commandes marche/arrêt
                if pid['invert'] then
                               marche = 'Off' ; arret = 'On'
                else
                               marche = 'On' ; arret = 'Off'
                end
                
                -- à chaque cycle
                if ( time.min%pid['cycle'] == pid['freq'] ) then
                
                               -- maj des 4 dernières temps
                               local temps = string.match(uservariables['PID_temps_'..pid['zone']],";([^%s]+)")..";"..temp
                               commandArray[#commandArray+1] = {['Variable:PID_temps_'..pid['zone']] = temps}

 			       -- fonctionnement hors gel
                               if ( otherdevices[pid['OnOff']] == 'Hors gel' ) then
                                               consigne = tonumber(otherdevices_svalues[pid['thermostat_horsgel']]) or pid['thermostat_horsgel']
			       end

                               -- fonctionnement Manu
                               if ( otherdevices[pid['OnOff']] == 'Manu' ) then
                                               consigne = tonumber(otherdevices_svalues[pid['thermostat']]) or pid['thermostat']
			       end

                               -- fonctionnement Auto
                               if ( otherdevices[pid['OnOff']] == 'Auto' ) then
                                               -- récupération de la consigne
                                               if ( otherdevices[pid['programmateur']] == 'On' ) then
                                                               consigne = tonumber(otherdevices_svalues[pid['thermostat']]) or pid['thermostat']
                                               else
                                                               consigne = tonumber(otherdevices_svalues[pid['thermostat_eco']]) or pid['thermostat_eco']
                                               end
                               end
                                               -- calcul de l'erreur
                                               local erreur = consigne-temp
                                               -- calcul intégrale auto consumée et moyenne erreur glissante
                                               temps:gsub("([+-]?%d+%.*%d*)",function(t)
                                                                                                                      tmp[n] = tonumber(t)
                                                                                                                      err = tonumber(consigne-t)
                                                                                                                      somme_erreurs = somme_erreurs+err
                                                                                                                      moy_erreur = moy_erreur+err*n^3
                                                                                                                      n = n+1
                                                                                                                      end)

                                               somme_erreurs = round(constrain(somme_erreurs,0,255),1)
                                               moy_erreur = round(moy_erreur/100,2)
                                               
                                               -- calcul de la dérivée (régression linéaire - méthode des moindres carrés)
                                               local delta_erreurs = round((4*(4*tmp[1]+3*tmp[2]+2*tmp[3]+tmp[4])-10*(tmp[1]+tmp[2]+tmp[3]+tmp[4]))/20,2)
                                               
                                               -- aux abords de la consigne, passage au second systême integrale
                                               if somme_erreurs < 2 then
                                                               somme_erreurs = tonumber(uservariables['PID_integrale_'..pid['zone']])
                                                               -- re calcule intégrale si hors hysteresis
                                                               -- à moins d'un dixièmes de degré d'écart avec la consigne
                                                               -- le ratrapage est considéré OK, l'intégrale n'est pas recalculée
                                                               if math.abs(erreur) > 0.11 then
                                                                              -- calcule intégrale
                                                                              somme_erreurs = round(constrain(somme_erreurs+erreur/2,0,5),2)
                                                                              -- maj
                                                                              commandArray[#commandArray+1] = {['Variable:PID_integrale_'..pid['zone']] = tostring(somme_erreurs)}
                                                               end
                                               end
                                               
                                               -- boucle ouverte,
                                               -- modification dynamique des paramètres de régulation suivant température extérieure
                                               local Kb = 0
                                               if temp_ext ~= nil then
                                                               Kb = pid['Kb'] * (consigne - temp_ext - pid['ref']) / 100
                                               end        
                                               pid['Kp'] = round(pid['Kp'] + pid['Kp'] * Kb)
                                               pid['Ki'] = round(pid['Ki'] + pid['Ki'] * Kb)
                                               pid['Kd'] = round(pid['Kd'] + pid['Kd'] * Kb)
                
                                               -- calcul pid
                                               local P = round(pid['Kp']*moy_erreur,2)
                                               local I = round(pid['Ki']*somme_erreurs,2)
                                               local D = round(pid['Kd']*delta_erreurs,2)
                                               
                                               -- calcul de la commande en %
                                               local commande = round(constrain(P+I+D,0,100))
                                                                              
                                               -- calcul du temps de fonctionnement
                                               if commande == 100 then
                                                               -- débordement de 20s pour ne pas couper avant recalcule
                                                               heatTime = (pid['cycle']*60)+20
                                               elseif commande > 0 then
                                                               -- secu mini maxi
                                                               heatTime = round(constrain(commande*pid['cycle']*0.6,pid['secu'],(pid['cycle']*60)-pid['secu']))
                                               elseif commande == 0 then
                                                               -- coupure retardée
                                                               heatTime = constrain(pid['secu']-lastSeen(pid['radiateur']),0,pid['secu'])
                                               end
                                               
                                               -- AFTER n'aime pas 1 ou 2..
                                               if heatTime == 1 or heatTime == 2 then
                                                               heatTime = 0
                                               end        
                                               
                                               -- action sur l'élément chauffant
                                               if heatTime > 0 then
                                                               commandArray[#commandArray+1] = {[pid['radiateur']] = marche}
                                                               commandArray[#commandArray+1] = {[pid['radiateur']] = arret..' AFTER '..heatTime}
                                               else
                                                               commandArray[#commandArray+1] = {[pid['radiateur']]=arret}
                                               end                                       
                               
                                               -- journalisation
                                               if pid['debug'] then
                                                               log('PID zone: '..string.upper(pid['zone']))
                                                               if temp_ext ~= nil then
                                                                              log('temperature ext: '..temp_ext..'°C')
                                                               end
                                                               log('température int: '..temp..'°C pour '..consigne..'°C souhaité')
                                                               log('Kp: '..pid['Kp'])
                                                               log('Ki: '..pid['Ki'])
                                                               log('Kd: '..pid['Kd'])
                                                               log('erreur: '..moy_erreur)
                                                               log('somme erreurs: '..somme_erreurs)
                                                               log('delta erreurs: '..delta_erreurs)
                                                               log('P: '..P)
                                                               log('I: '..I)
                                                               log('D: '..D)
                                                               log('cycle: '..pid['cycle']..'min (sécu: '..pid['secu']..'s)')
                                                               -- avertissement si secu dépasse 1/4 du cycle
                                                               if ((100*pid['secu'])/(60*pid['cycle'])>25) then
                                                                              warn('sécu trop importante, ralonger durée de cycle..')
                                                               end
                                                               log('commande: '..commande..'% ('..string.sub(os.date("!%X",heatTime),4,8):gsub("%:", "\'")..'\")')
                                                               log('')
                                               end
                                               
                                               -- maj sonde virtuelle
                                               --commandArray[#commandArray+1] = {['UpdateDevice'] = otherdevices_idx[pid['sonde']..'_pid']..'|0|'..temp..';'..commande..';0'}
                                               

                               
                end
                -- toutes les 15 minutes, si on ne veut pas chauffer
                if ( time.min%15 == 0 and otherdevices[pid['OnOff']] == 'Off' ) then

                               -- arrêt chauffage (renvoi commande systematique par sécurité)
                               commandArray[#commandArray+1] = {[pid['radiateur']] = arret..' AFTER '..constrain(pid['secu']-lastSeen(pid['radiateur']),3,pid['secu'])}
                               
                               -- maj sonde virtuelle
                               --commandArray[#commandArray+1] = {['UpdateDevice'] = otherdevices_idx[pid['sonde']..'_pid']..'|0|'..temp..';0;0'}
                end

end

Répondre