[LUA] Chauffage PID

Vous avez créé 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.
vil1driver
Messages : 5661
Inscription : 30 janv. 2015, 11:07
Localisation : Rennes (35)

Re: chauffage PID

Message par vil1driver »

Mauvais nom de sonde probablement
MAJ = VIDER LE CACHE(<-Clicable)
/!\Les mises à jour de Domoticz sont souvent sources de difficultés, ne sautez pas dessus
modules.lua

Un ex domoticzien
batdiver77
Messages : 11
Inscription : 24 févr. 2018, 11:40

Re: chauffage PID

Message par batdiver77 »

Bonjour,

Ben justement quelque soit la sonde et le nom que je mets j'ai toujours cette erreur... ???

Une idée ...
vil1driver
Messages : 5661
Inscription : 30 janv. 2015, 11:07
Localisation : Rennes (35)

Re: chauffage PID

Message par vil1driver »

tu n'aurais pas fait un truc "à ta sauce" pas prévu... comme tronquer le fichier modules.lua ?
le chiffre 18 me surprends dans ton code d'erreur
MAJ = VIDER LE CACHE(<-Clicable)
/!\Les mises à jour de Domoticz sont souvent sources de difficultés, ne sautez pas dessus
modules.lua

Un ex domoticzien
batdiver77
Messages : 11
Inscription : 24 févr. 2018, 11:40

Re: chauffage PID

Message par batdiver77 »

Bonjour,

Voici ce que j'ai mis dans le fichier modules.lua :

Code : Tout sélectionner

--------------------------------
------ 	  USER SETTINGS	  ------
--------------------------------

-- domoticz
domoticzIP = '192.168.1.130'	--'127.0.0.1'
domoticzPORT = '8080'

--------------------------------
------         END        ------
--------------------------------

-- régulation chauffage (PID)
function compute(pid)
	local init = 0
	
	-- récupération température
	local temp = getTemp(pid['sonde'])
	
	-- 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'])
		return commandArray
	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'] == 0 ) then
	
		-- maj des 4 dernières temps
		local temps = string.match(uservariables['PID_temps_'..pid['zone']],";([^%s]+)")..";"..temp
		commandArray['Variable:PID_temps_'..pid['zone']] = temps
		
		-- si l'on veut chauffer
		if ( otherdevices[pid['OnOff']] == 'On' ) then

			-- récupération de la consigne
			local 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,2),2)
					-- maj
					commandArray['Variable:PID_integrale_'..pid['zone']] = tostring(somme_erreurs)
				end
			end
			
			-- 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[1] = {[pid['radiateur']] = marche}
				commandArray[2] = {[pid['radiateur']] = arret..' AFTER '..heatTime}
			else
				commandArray[pid['radiateur']]=arret
			end			
		
			-- journalisation
			if pid['debug'] then
				log('PID zone: '..string.upper(pid['zone']))
				log('température: '..temp..'°C pour '..consigne..'°C souhaité')
				log('Kp: '..pid['Kp'])
				log('Ki: '..pid['Ki'])
				log('Kd: '..pid['Kd'])
				log('erreur: '..moy_erreur)
				log('&#8721; erreurs: '..somme_erreurs)
				log('&#916; 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
			
		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[pid['radiateur']] = arret..' AFTER '..constrain(pid['secu']-lastSeen(pid['radiateur']),3,pid['secu'])
		
	end

end
Deplus j'ai mainenat l'erreur suivante :

" Error: EventSystem: in /home/pi/domoticz/scripts/lua/script_time_thermostatalicia.lua: ...pi/domoticz/scripts/lua/script_time_thermostatalicia.lua:33: attempt to call global 'compute' (a nil value)"

voici mon fichier script_time :

Code : Tout sélectionner

-- Ce script permet réguler la température de la zone

-- chargement des modules
dofile('/home/pi/domoticz/scripts/lua/modules.lua')

--------------------------------
------ Variables à éditer ------
--------------------------------
local pid={}

pid['debug'] = true	-- true pour voir les logs dans la console log Dz ou false pour ne pas les voir
pid['zone'] = 'Chambre Alicia' -- nom de la zone pour affichage dans les logs et distinction de variables
pid['sonde'] = 'T°C Chambre Alicia' -- Nom de la sonde de température
pid['OnOff'] = 'Thermostat Alicia PID' -- Nom de l'interrupteur virtuel de mise en route
pid['thermostat'] = 19 -- consigne ou 'nom' de l'interrupteur virtuel de thermostat
-- actionneur
pid['radiateur'] = 'Radiateur_Alicia' -- Nom de l'interrupteur de chauffage
pid['invert'] = true	-- si On et Off doivent être inversé ou non

-- PID
pid['Kp'] = 45 -- Coefficient proportionnel 
pid['Ki'] = 20 -- Coefficient intégrateur
pid['Kd'] = 45 -- Coefficient dérivateur

pid['cycle'] = 10	-- temps en minute d'un cycle PID
pid['secu'] = 30	-- temps mini en seconde entre 2 ordres opposés

--------------------------------
-- Fin des variables à éditer --
--------------------------------

commandArray = {} 
compute(pid)
return commandArray


Je ne vois où est le pb ??? :-(
vil1driver
Messages : 5661
Inscription : 30 janv. 2015, 11:07
Localisation : Rennes (35)

Re: chauffage PID

Message par vil1driver »

J'avais donc vu juste.
MAJ = VIDER LE CACHE(<-Clicable)
/!\Les mises à jour de Domoticz sont souvent sources de difficultés, ne sautez pas dessus
modules.lua

Un ex domoticzien
batdiver77
Messages : 11
Inscription : 24 févr. 2018, 11:40

Re: chauffage PID

Message par batdiver77 »

vil1driver a écrit :J'avais donc vu juste.
Bonjour,

Je ne comprend ta réponse....???

de plus dans mes scripts, que je mettent n'importe quel noms de sonde, j'ai toujours la même erreur...
vil1driver
Messages : 5661
Inscription : 30 janv. 2015, 11:07
Localisation : Rennes (35)

Re: chauffage PID

Message par vil1driver »

Tu tailles à la hache dans un script et tu ne sais pas pourquoi ça ne fonctionne pas ?

La fonction compute n'est pas autonome, elle a besoin d'autres fonctions, que tu as pour je ne sais quelles raisons supprimé.

Le fichier modules.lua est à prendre en entier.
MAJ = VIDER LE CACHE(<-Clicable)
/!\Les mises à jour de Domoticz sont souvent sources de difficultés, ne sautez pas dessus
modules.lua

Un ex domoticzien
batdiver77
Messages : 11
Inscription : 24 févr. 2018, 11:40

Re: chauffage PID

Message par batdiver77 »

Ok merci je vais corriger le tir, je pensé qu'il avait juste la partie qui concerne le PID.... :?
batdiver77
Messages : 11
Inscription : 24 févr. 2018, 11:40

Re: chauffage PID

Message par batdiver77 »

Ca coince toujours, en reprenant tous le fichier entier, voici l'erreur que j'ai :

"/home/pi/domoticz/scripts/lua/modules.lua:280: attempt to perform arithmetic on local 'num' (a nil value)"
vil1driver
Messages : 5661
Inscription : 30 janv. 2015, 11:07
Localisation : Rennes (35)

Re: chauffage PID

Message par vil1driver »

Ligne 280 du fichier modules.lua, tentative de calcul sur une valeur inexistante
MAJ = VIDER LE CACHE(<-Clicable)
/!\Les mises à jour de Domoticz sont souvent sources de difficultés, ne sautez pas dessus
modules.lua

Un ex domoticzien
Répondre