[LUA] Regulation 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.
jackyhi
Messages : 97
Inscription : 09 mai 2016, 23:49

Re: Regul chauffage PID

Message par jackyhi »

Re bonjour ou plutôt bonsoir, je pense avoir un petit peu progressé comme débutant mais maintenant je suis devant un mur d'interrogation!

j'ai implanté les scripts de la régul PID et j'obtiens les erreurs suivantes:
2016-05-17 22:30:23.051 Error: EventSystem: in /home/pi/domoticz/scripts/lua/script_device_conschauf.lua: /home/pi/domoticz/scripts/lua/script_device_conschauf.lua:1: unexpected symbol near char(255)
2016-05-17 22:31:00.383 Error: EventSystem: in /home/pi/domoticz/scripts/lua/script_time_cmdchauffv2.lua: /home/pi/domoticz/scripts/lua/script_time_cmdchauffv2.lua:1: unexpected symbol near char(255)

Voici le script que j'ai entré script_device_conschauf.lua:
-- script_device_conschauf.lua ---------------------------------------
-- G PETREMENT -----------------------------------------------2015----
----------------------------------------------------------------------
-- Pilotage d'un Thermostat setpoint Consigne pour pilotage regul ----
-- en fonction d'une programation journaliere ------------------------
----------------------------------------------------------------------
-- Le programme est basé sur l'action de 2 switchs (virtuels ou non) -
-- Le Switch EcoConfort dispose d'une programation mais peut aussi ---
-- être actionné manuellement. ---------------------------------------
-- Le switch HorsGel est un mode vacance qui stope la programmation --
-- Les temperatures de consignes sont stockées en variable direct ----
-- dans domoticz pour être modifiées par l'interface web. ------------
----------------------------------------------------------------------

----------------------------------------------------------------------
-- VARIABLES UTILISATEUR : mettre les nom des dispositifs ici --------
----------------------------------------------------------------------
local VarConsJour = 'ConsigneJour' --Variable consigne jour
local VarConsNuit = 'ConsigneNuit' --Variable consigne nuit
local VarConsVac = 'ConsigneVacance' --Variable consigne vacances
local VarSomErr = 'SommeErreur' --Variable Somme des erreurs
local SondeCons = 'ConsigneChauffage' --Sonde de temperature
local InterEcoConfort = 'EcoConfort' --Interrupteur programmé Off:eco On:confort
local InterHorsGel = 'HorsGel' --Interrupteur On:mode hors gel>> plus de programmation, consigne vacance ou manuelle
local domoticz_url = '192.168.0.203:8080' --Adresse IP:port de Domoticz
local IDXcons = '54' --IDx de l'afficheur de consigne
----------------------------------------------------------------------

-- Fonction retourant la differrence de temps en secondes ------------
function timedifference(s)
year = string.sub(s, 1, 4)
month = string.sub(s, 6, 7)
day = string.sub(s, 9, 10)
hour = string.sub(s, 12, 13)
minutes = string.sub(s, 15, 16)
seconds = string.sub(s, 18, 19)
t1 = os.time()
t2 = os.time{year=year, month=month, day=day, hour=hour, min=minutes, sec=seconds}
difference = os.difftime (t1, t2)
return difference
end

commandArray = {}
-- Recuperation des variables ---------------------------------------
local ConsJour = uservariables[VarConsJour]
local ConsNuit = uservariables[VarConsNuit]
local ConsVac = uservariables[VarConsVac]
local Consigne = otherdevices_temperature[SondeCons]
local t1 = os.date("%H:%M")

-- Lorsqu'un interrupteur est manipulé on modifie la temperature de consigne.
-- La variable SommeErreur utilisée pour calculer le gain intégral est aussi remise à 0 >> Gain intégral=0
if (((devicechanged[InterEcoConfort] == 'On') and (otherdevices[InterHorsGel] == 'Off')) or ((devicechanged[InterHorsGel] == 'Off') and (otherdevices[InterEcoConfort] == 'On'))) then
print("-------------- Temperature modifiée vers Confort à "..t1)
-- Mise a jour de l'afficheur via JSON -----------------------------
local url = domoticz_url..'/json.htm?type=command&param=udevice&idx='..IDXcons..'&nvalue=0&svalue='..ConsJour
commandArray[1]={['OpenURL']=url }
commandArray['Variable:'..VarSomErr]='0'

elseif (((devicechanged[InterEcoConfort] == 'Off') and (otherdevices[InterHorsGel] == 'Off')) or ((devicechanged[InterHorsGel] == 'Off') and (otherdevices[InterEcoConfort]=='Off' ))) then
print("-------------- Temperature modifiée vers Eco à "..t1)
-- Mise a jour de l'afficheur via JSON -----------------------------
local url = domoticz_url..'/json.htm?type=command&param=udevice&idx='..IDXcons..'&nvalue=0&svalue='..ConsNuit
commandArray[1]={['OpenURL']=url }
commandArray['Variable:'..VarSomErr]='0'

elseif (devicechanged[InterHorsGel] == 'On') then
print("-------------- Temperature modifiée vers HorsGel à "..t1)
-- Mise a jour de l'afficheur via JSON -----------------------------
local url = domoticz_url..'/json.htm?type=command&param=udevice&idx='..IDXcons..'&nvalue=0&svalue='..ConsVac
commandArray[1]={['OpenURL']=url }
commandArray['Variable:'..VarSomErr]='0'
end
return commandArray


et le suivant script_time_cmdchauffv2.lua:
-- script_time_cmdchauffv2.lua ---------------------------------------
-- G PETREMENT -------------------------------------------------------
----------------------------------------------------------------------
-- Permet de commander relais de pilotage de chaudiere à gaz ---------
-- Le cycle fait 900s / 15min ---------------------------------------
-- La commande est un nombre de 0 à 100 ------------------------------
-- Le cycle minimum de la chaudière est de 3min pour réduire l'usure -
----------------------------------------------------------------------

local InterOnOff = 'Chauffage On/Off' --Interrupteur général de mise en route du chauffage
local VarCmdChauff = 'CmdChauff' --Variable de commande de chauffage définie par script_device_thermostat
local CycleMini = 180 --Durée de chauffe minimum en secondes (fonction de la chaudière)
local InterRelais = 'Piface RelayChaud' --Sortie vers relais chaudière
local domoticz_url = '192.168.0.203:8080' --Adresse IP:port de Domoticz

-- Fonction retourant la differrence de temps en secondes
function timedifference(s)
year = string.sub(s, 1, 4)
month = string.sub(s, 6, 7)
day = string.sub(s, 9, 10)
hour = string.sub(s, 12, 13)
minutes = string.sub(s, 15, 16)
seconds = string.sub(s, 18, 19)
t1 = os.time()
t2 = os.time{year=year, month=month, day=day, hour=hour, min=minutes, sec=seconds}
difference = os.difftime (t1, t2)
return difference
end

commandArray = {}
-- Recuperation des variables
local CmdChauff = uservariables[VarCmdChauff]
local OnOff = otherdevices[InterOnOff]

-- Recuperation des minutes
time=os.time()
minutes=tonumber(os.date('%M',time))
hours=tonumber(os.date('%H',time))

-- Execution de cette partie du script toutes les 15 minutes
-- Contacte la chaudière et modifie la variable domoticz Cycle
if( (minutes==15) or (minutes==0) or (minutes==30) or (minutes==45) ) then
print('-- Lancement du script à '..hours..'h'..minutes)
print('-- OnOff ='..OnOff..' / CmdChauff ='..CmdChauff)

if OnOff == 'On' then --Si l'inter général est ON
local Cycle = CmdChauff * 9 --Calcul du temps de cycle en seconde

if Cycle < CycleMini then --Si le cycle est trop court on coupe
commandArray[InterRelais]='Off'
-- commandArray['Variable:'..VarCycle]= tostring('0')
print('Cycle :'..Cycle..'s >> Chaudière Off')

elseif Cycle > 870 then --Si le cycle est trop long (> 14min30) on allume sans coupure
commandArray[InterRelais]='On'
-- commandArray['Variable:'..VarCycle]= tostring(Cycle)
print('Cycle :'..Cycle..'s >> Chaudière On')

else --Enfin on lance pour X seconde
print('Cycle lancé pour : '..Cycle..'secondes')
commandArray[1]={[InterRelais]='On'}
commandArray[2]={[InterRelais]='Off AFTER '..tostring(Cycle)}
end
else
commandArray[InterRelais]='Off'
-- commandArray['Variable:'..VarCycle]= tostring('0')
print('Chaudière Off')
end
end

return commandArray

et voici une capture de ma page Domoticz:
CaptureEcran.jpg
CaptureEcran.jpg (58.82 Kio) Consulté 12501 fois
Autres questions:
1) je ne sais pas comment entrer les valeurs des Constantes Kp Ki Kd dans ma régulation! elles sont déclarées comme des variables mais à aucun moment je n'ai vu une entrée de ces constantes.

2) Comment obtenir dans domoticz le tableau des variables:
Tableau VariablePID.jpg
Tableau VariablePID.jpg (25.22 Kio) Consulté 12501 fois
3) Comment debuger un programme en script lua?

Merci d'avance à celui qui voudra bien me répondre.





Raspberry Pi model B+,Dongle WIFI, RFXComm,6 modules volet roulant BLYSS, sonde Oregon
Raspberry Pi2 VPN, Pi 3, Pi4 ,RFXCom, 6 volets BLYSS, sondes Temp_humid Attiny85, zigbee, Mysensors, RFLINK , Zwave capteurs portes Prises, Alarme avec 2 sirènes maison esp8266, Thermostat NETAMO vannes thermostatiques
Hober Mallow
Messages : 9
Inscription : 02 oct. 2016, 21:54

Re: Regul chauffage PID

Message par Hober Mallow »

Super Boulot !

Je souhaite utiliser cette régulation dans différents environnement : Chauffage, congelateur etc...

PAr contre j'ai un petit soucis, je trouve cette erreur dans les logs :
2016-10-02 19:51:56.017 Error: EventSystem: in /home/pi/domoticz/scripts/lua/script_device_thermostatv3.lua: ...e/pi/domoticz/scripts/lua/script_device_thermostatv3.lua:105: attempt to perform arithmetic on local 'consigne' (a nil value)

Vous auriez une idée?

Cdt.
Hober Mallow
jackyhi
Messages : 97
Inscription : 09 mai 2016, 23:49

Re: Regul chauffage PID

Message par jackyhi »

Salut Hober Mallow

Depuis j'ai un peu modifié mais fichiers pour faire une simulation et voire comment la régulation répondait à un échelon ou à une rampe de variation de la température.
Je n'ai pas encore mis en application sur ma chaudière au Fuel!

Mais voici mes fichiers

Code : Tout sélectionner

-- script_device_conschauf.lua ---------------------------------------
-- G PETREMENT -----------------------------------------------2015----
----------------------------------------------------------------------
-- Pilotage d'un Thermostat setpoint Consigne pour pilotage regul ----
-- en fonction d'une programation journaliere ------------------------
----------------------------------------------------------------------
-- Le programme est basé sur l'action de 2 switchs (virtuels ou non) -
-- Le Switch EcoConfort dispose d'une programation mais peut aussi ---
-- être actionné manuellement. ---------------------------------------
-- Le switch HorsGel est un mode vacance qui stope la programmation --
-- Les temperatures de consignes sont stockées en variable direct ----
-- dans domoticz pour être modifiées par l'interface web. ------------
----------------------------------------------------------------------

----------------------------------------------------------------------
-- VARIABLES UTILISATEUR : mettre les nom des dispositifs ici --------
----------------------------------------------------------------------
local VarConsJour = 'ConsigneJour'       --Variable consigne jour
local VarConsNuit = 'ConsigneNuit'       --Variable consigne nuit
local VarConsVac = 'ConsigneVacance'     --Variable consigne vacances
local VarSomErr = 'SommeErreur'          --Variable Somme des erreurs
local SondeCons = 'Th_salon'               --Consigne thermostat de temperature
local InterEcoConfort = 'EcoConfort'     --Interrupteur programmé Off:eco On:confort
local InterHorsGel = 'HorsGel'           --Interrupteur On:mode hors gel>> plus de programmation, consigne vacance ou manuelle
local domoticz_url = '192.168.0.23:9085'  --Adresse IP:port de Domoticz
local IDXcons = '1'                     --IDx de l'afficheur de consigne
----------------------------------------------------------------------

-- Fonction retourant la differrence de temps en secondes ------------
--function timedifference(s)
--   year = string.sub(s, 1, 4)
--   month = string.sub(s, 6, 7)
--   day = string.sub(s, 9, 10)
--   hour = string.sub(s, 12, 13)
--   minutes = string.sub(s, 15, 16)
--   seconds = string.sub(s, 18, 19)
--   t1 = os.time()
--   t2 = os.time{year=year, month=month, day=day, hour=hour, min=minutes, sec=seconds}
--   difference = os.difftime (t1, t2)
--   return difference
--end

commandArray = {}
--  Recuperation des variables ---------------------------------------
local ConsJour = uservariables[VarConsJour]
local ConsNuit = uservariables[VarConsNuit]
local ConsVac = uservariables[VarConsVac]
--local Consigne = otherdevices_temperature[SondeCons]
--local Consigne = otherdevices_svalues[SondeCons]
--print('consignes jour= '..ConsJour..'°  Nuit= ' ..ConsNuit..'° Vac= '..ConsVac..'°  et Consigne Thermostat= '..Consigne..'°')

local t1 = os.date("%H:%M")

-- Lorsqu'un interrupteur est manipulé on modifie la temperature de consigne.
-- La variable SommeErreur utilisée pour calculer le gain intégral est aussi remise à 0 >> Gain intégral=0
if (((devicechanged[InterEcoConfort] == 'On') and (otherdevices[InterHorsGel] == 'Off')) or ((devicechanged[InterHorsGel] == 'Off') and (otherdevices[InterEcoConfort] == 'On'))) then
   print("-------------- Temperature modifiée vers Confort à "..t1)
   -- Mise a jour de l'afficheur via JSON -----------------------------
   local url = domoticz_url..'/json.htm?type=command&param=udevice&idx='..IDXcons..'&nvalue=0&svalue='..ConsJour
   commandArray[1]={['OpenURL']=url }
   commandArray['Variable:'..VarSomErr]='0'

elseif (((devicechanged[InterEcoConfort] == 'Off') and (otherdevices[InterHorsGel] == 'Off')) or ((devicechanged[InterHorsGel] == 'Off') and (otherdevices[InterEcoConfort]=='Off' ))) then
   print("-------------- Temperature modifiée vers Eco à "..t1)
   -- Mise a jour de l'afficheur via JSON -----------------------------
   local url = domoticz_url..'/json.htm?type=command&param=udevice&idx='..IDXcons..'&nvalue=0&svalue='..ConsNuit
   commandArray[1]={['OpenURL']=url }
   commandArray['Variable:'..VarSomErr]='0'
  
elseif (devicechanged[InterHorsGel] == 'On') then
   print("-------------- Temperature modifiée vers HorsGel à "..t1)
   -- Mise a jour de l'afficheur via JSON -----------------------------
   local url = domoticz_url..'/json.htm?type=command&param=udevice&idx='..IDXcons..'&nvalue=0&svalue='..ConsVac
   commandArray[1]={['OpenURL']=url }
   commandArray['Variable:'..VarSomErr]='0'
end
return commandArray

Code : Tout sélectionner

-- script_device_thermostatv3.lua ------------------------------------
----------------------------------------------------------------------
-- G PETREMENT 2015 --------------------------------------------------
-- This script is a heating regulation use to maintain temperatur ----
-- at a specific value. ----------------------------------------------
----------------------------------------------------------------------

--------------------------------
--- Variables utilisateur ------
--------------------------------
local VarConsigne =  'Th_salon'           --Température de consigne
local SondeSj = 'SondeSejour'			  --Nom de la sonde de température du séjour												nom
local Varsonde = 'SondeChauff'            --Variable Domoticz :Nom de la sonde simulée de température
local AffTexte = 'AffichageParams'        -- Dispositif affichages des paramètres
local IDerreur = '6'                     --IDX de l'afficheur "TempErreur" d'erreur
local IDSomerreur = '5'                  --IDX de l'afficheur "TempSomErreur" Somme d'erreur
local IDDeltaErreur = '7'                --IDX de l'afficheur "DiffErreur" Différence d'erreur
local IDCmdChauff = '8'                  --IDX de l'afficheur "Cmde_Chauff" Proportionnel Commande Chauffage
local IDAffTexte = '28'                   --IDX de l'afficheur des paramètres
local domoticz_url = '192.168.0.23:9085'  --Adresse IP:port de Domoticz
local VarKp = "Kp"                        --Variable Domoticz : Gain proportinnel
local VarKi = "Ki"                        --Variable Domoticz : Gain intégral
local VarKd = "Kd"                        --Variable Domoticz : Gain dérivé
local VarTempErr = 'TemperatureErreur'    --Variable domoticz pour l'erreur de temperature
local VarSomErr = 'SommeErreur'           --Variable domoticz pour la somme des erreurs
local VarDeltaErr = 'DeltaErreur'         --Variable domoticz pour la différences des erreurs
local VarCmdChauff = 'CmdChauff'          --Variable Domoticz de commande du chauffage : permet de passer la commande à script_time_chauff.lua
local VarCmdImax = 'CmdImax'              --Variable domoticz qui défini le gain intégral maximum
local fichier = '/var/tmp/dom_tmperr.txt' --Chemin d'acces du fichier sur un RAMdisque pour réduire l'usure de la carte SD
local nbr_stk = 22                        --Quantité de valeurs utilisées pour le calcul de la dérivée de l'erreur (ne pas mettre 0!!)

--------------------------------------------------------------
-- Fonction pour arrondir un nombre à la décimale souhaitée --
--------------------------------------------------------------
math.round = function(number, precision)
   precision = precision or 0
   local decimal = string.find(tostring(number), ".", nil, true);
   
   if ( decimal ) then   
      local power = 10 ^ precision;  
      if ( number >= 0 ) then 
         number = math.floor(number * power + 0.5) / power;
      else 
         number = math.ceil(number * power - 0.5) / power;      
      end
      
      -- convert number to string for formatting
      number = tostring(number);         
      -- set cutoff
      local cutoff = number:sub(decimal + 1 + precision);
      -- delete everything after the cutoff
      number = number:gsub(cutoff, "");
   else
      -- number is an integer
      if ( precision > 0 ) then
         number = tostring(number);
         number = number .. ".";
         for i = 1,precision
         do
            number = number .. "0";
         end
      end
   end      
   return number;
end

---------------------------------------------------------
---  Fonction pour calculer la commande de chauffage  ---
---------------------------------------------------------
Chauff = function(Kp,Err,Ki,SomErr, Kd, DifErr)
    --print('Kp'..Kp..'Err'..Err..'Ki'..Ki..'SomErr'..SomErr..'Kd'..Kd..'DifErr'..DifErr)
  local cmd = Kp*Err + Ki*SomErr + Kd*DifErr
   -- La commande de chauffage est un nombre entier compris entre 0 et 100
   if cmd < 0 then 
      cmd = 0
   elseif cmd > 100 then
      cmd = 100
   else
      cmd = math.round(cmd, 0)
   end
   return cmd
end

-----------------------------
---- Programme principal ----
-----------------------------
commandArray = {}
--La sonde Oregon 'Salon' emet toutes les 40 secondes. Ce sera approximativement la fréquence d'exécution de ce script.
--print('Anciennes valeurs: Consigne Temp.: '..otherdevices_svalues[VarConsigne]..'° '..'Temp. de sonde (ou simul.): '..' '..otherdevices_svalues[Varsonde]..'° ')
if ( (devicechanged[SondeSj]) or (devicechanged[VarConsigne]) or (devicechanged[Varsonde])  ) then
  -- Initialisation des variables
  local t = {} --Table buffer avec le fichier texte
  local SomErreur = tonumber(uservariables[VarSomErr]) --Somme des erreurs
  local Kp = tonumber(uservariables[VarKp])
  local Ki = tonumber(uservariables[VarKi])
  local Kd = tonumber(uservariables[VarKd])
  local CmdImax = tonumber(uservariables[VarCmdImax]) --Limitation de l'action intégrale (debug)
  local consigne =  otherdevices_svalues[VarConsigne]  --Température de consigne
    
  ---------------------------------
  ---  Calcul du proportionnel  ---
  ---------------------------------
  --Temperature relevée dans le salon
  --local temperature = devicechanged[sonde..'_Temperature'] 
  local temperature = tonumber(otherdevices_svalues[Varsonde])
  temperature = tonumber(math.round(temperature,2))
  print('Température sonde (ou simulation):'..temperature..'° ,  Consigne thermostat: '..consigne..'°')
  -- Update de la sonde d'erreur
  local TmpErreur = consigne - temperature
  local url = domoticz_url..'/json.htm?type=command&param=udevice&idx='..IDerreur..'&nvalue=0&svalue='..TmpErreur
  commandArray[1]={['OpenURL']=url }
  
  ------------------------------
  ---  Calcul de la dérivée  ---
  ------------------------------
  --Creation si le ficher n'existe pas
  local f = io.open(fichier, "a+")
  f:close()
  --Lecture du fichier et remplissage de la table t
  f = io.open(fichier, "r")
  for line in f:lines() do
    if line ~= nil then
      table.insert(t,line)
    end
  end
  f:close()
  -- Ajout de la nouvelle ligne a la table
  table.insert(t,tostring(os.time()..";"..math.round(TmpErreur,2)))  
  --Suppression de l'élement le plus vieu
  while #t > nbr_stk do
      table.remove(t,1)
  end
    -- Eriture dans fichier'
  f = io.open(fichier,"w")
  for key,value in pairs(t) do
     f:write(value.."\n")
  end
  f:close()
  -- Calcul Difference entre deux erreurs à (22/2) x TintervalSonde = 55min d'interval + calibration) (sonde Bresser tous les 5min)
  local MoyErr1 = 0
  local MoyErr2 = 0
  for i=1,#t/2 do
    MoyErr1 = MoyErr1 + tostring(string.sub(t[i],string.find(t[i], ";")+1))
    MoyErr2 = MoyErr2 + tostring(string.sub(t[#t+1-i],string.find(t[#t+1-i], ";")+1))
  end
  --Le delta erreur est calculé sur la moyenne de 22 erreurs ce qui permet de 'lisser' la variation
  local DeltaErreur = tonumber(math.round(((MoyErr2 / (#t/2)) - (MoyErr1 / (#t/2)))*8 ,2)) --Delta en d°/heure
  print('--DeltaErreur = ('..MoyErr2..'/'..(#t/2)..') - ('..MoyErr1..'/'..(#t/2)..') * 8= '..DeltaErreur)
  -- Update de la sonde DeltaErreur
  url = domoticz_url..'/json.htm?type=command&param=udevice&idx='..IDDeltaErreur..'&nvalue=0&svalue='..DeltaErreur
  commandArray[2]={['OpenURL']=url }
  
  -------------------------------
  ---  Calcul de l'intégrale  ---
  -------------------------------
  -- Calcul de la somme des erreurs + Update de la sonde Somme d'erreur
  -- Si la l'erreur est supérieure à +-1° on ne somme pas pour limiter l'impact des changements de consigne
  if ((TmpErreur > -1) and (TmpErreur < 1) and (Ki ~= 0)) then
    SomErreur = tonumber(math.round(TmpErreur + SomErreur,2))
    if (SomErreur > (CmdImax/Ki)) then
        SomErreur = CmdImax/Ki
    elseif (SomErreur < 0) then
      SomErreur = 0
    end
  end
  url = domoticz_url..'/json.htm?type=command&param=udevice&idx='..IDSomerreur..'&nvalue=0&svalue='..SomErreur
  commandArray[3]={['OpenURL']=url }

  ------------------------------------------
  --- Calcul de la commande de chauffage ---
  ------------------------------------------
  local CmdChauff = Chauff(Kp, TmpErreur, Ki, SomErreur, Kd, DeltaErreur)
  -- Update de la mesure Commande
  url = domoticz_url..'/json.htm?type=command&param=udevice&idx='..IDCmdChauff..'&nvalue=0&svalue='..CmdChauff
  commandArray[4]={['OpenURL']=url }
  print('Nouveaux param.: Commande de chauffage (0>100): '..CmdChauff..'% ; = Kp*Err ='..tostring(Kp*TmpErreur)..'% + Ki*SomErr ='..tostring(Ki*SomErreur)..'% + Kd*DifErr ='..tostring(Kd*DeltaErreur)..'%')
 commandArray['UpdateDevice'] = IDAffTexte .. '|0|Cmde_chauff: '..CmdChauff..'% ; = Kp*Err('..tostring(Kp*TmpErreur)..'%) + Ki*SomErr('..tostring(Ki*SomErreur)..'%) + Kd*DifErr('..tostring(Kd*DeltaErreur)..'%)'
 --Passage des variables à domoticz
  commandArray['Variable:'..VarTempErr]= tostring(TmpErreur)
  commandArray['Variable:'..VarSomErr]= tostring(SomErreur)
  commandArray['Variable:'..VarDeltaErr]= tostring(DeltaErreur)
  commandArray['Variable:'..VarCmdChauff]= tostring(CmdChauff)
  
end
return commandArray

Code : Tout sélectionner

-- script_time_cmdchauffv2.lua ---------------------------------------
-- G PETREMENT -------------------------------------------------------
----------------------------------------------------------------------
-- Permet de commander relais de pilotage de chaudiere à gaz ---------
-- Le cycle fait 900s / 15min  ---------------------------------------
-- La commande est un nombre de 0 à 100 ------------------------------
-- Le cycle minimum de la chaudière est de 3min pour réduire l'usure -
----------------------------------------------------------------------
local InterOnOff = 'Chauffage On/Off'    --Interrupteur général de mise en route du chauffage
local VarCmdChauff = 'CmdChauff'         --Variable de commande de chauffage définie par script_device_thermostat
local CycleMini = 30                     -- 30s Durée de chauffe minimum en secondes (fonction de la chaudière période 10 minutes)
local CycleMaxi = 570                    -- 570s Durée de chauffe limite en secondes si >=570s cycle = 100% (fonction de la chaudièrepériode 10 minutes)
local Tperiode = 600					-- Tperiode = 600s duree maxi du cycle
--local IpTelJacky = '192.168.0.10'
local InterRelais = 'RelayChaud'         --Sortie vers relais chaudière
--------------------------------------------------------------
-- Fonction pour arrondir un nombre à la décimale souhaitée --
--------------------------------------------------------------
math.round = function(number, precision)
   precision = precision or 0
   local decimal = string.find(tostring(number), ".", nil, true);
   
   if ( decimal ) then   
      local power = 10 ^ precision;  
      if ( number >= 0 ) then 
         number = math.floor(number * power + 0.5) / power;
      else 
         number = math.ceil(number * power - 0.5) / power;      
      end
      
      -- convert number to string for formatting
      number = tostring(number);         
      -- set cutoff
      local cutoff = number:sub(decimal + 1 + precision);
      -- delete everything after the cutoff
      number = number:gsub(cutoff, "");
   else
      -- number is an integer
      if ( precision > 0 ) then
         number = tostring(number);
         number = number .. ".";
         for i = 1,precision
         do
            number = number .. "0";
         end
      end
   end      
   return number;
end

commandArray = {}
--  Recuperation des variables
CycleMaxi = Tperiode * 0.975
CycleMini = Tperiode * 0.025
local OnOff = otherdevices[InterOnOff]
local CmdChauff = uservariables[VarCmdChauff]
local Cycle=(CmdChauff * Tperiode/100)  --  Calcul du temps de cycle  = CmdChauff(0<>100)* Tpériode/100 = CmdChauff * 120/100 = CmdChauff * 1.2
Cycle=tonumber(math.round(Cycle, 0))
--  Recuperation des minutes et unités de minutes
time=os.time()
minutes=tonumber(os.date('%M',time))
hours=tonumber(os.date('%H',time))
unites=tonumber(string.sub(os.date('%M',time),2,2))
-- print('il est:'..hours..'h'..minutes..'  '..' > unites = '..unites..' '..' minutes Cycle = '..Cycle..'s')
-- Execution de cette partie du script toutes les 10  minutes
-- Contacte la chaudière et modifie la variable domoticz Cycle
if( (unites%10==0) or (unites==0) ) then --or (unites==2) or (unites==4) or (unites==6) or (unites==8) ) then  période toutes les 10 minutes (ou 2 minutes -- or(unites==5)
    print('-- Lancement du script cycle chauffage à '..hours..'h'..minutes)
    --print('-- et Lancement du ping SmartphoneJacky')
    --if (otherdevices['SmartphoneJacky']=='Off' or (otherdevices['SmartphoneJacky']=='On' and timedifference(otherdevices_lastupdate['SmartphoneJacky']) > 300)) then
	--ping_success_tel=os.execute('ping -c1 '..IpTelJacky)
	--if ping_success_tel  then  -- or ping_success_tel
	--        commandArray['SmartphoneJacky']='On'
	--		print'succès présence SmartphoneJacky !!'
	--   else
	--       commandArray['SmartphoneJacky']='Off'
	--	   print'erreur absence SmartphoneJacky !!'
	--end
	if OnOff == 'On' then
        if Cycle < CycleMini then --Si le cycle est trop court on coupe
            commandArray[InterRelais]='Off'
            print('Cycle < mini:'..Cycle..'s >> Chaudière Off à '..hours..'h'..minutes..' sur la durée du cycle maxi')
          elseif Cycle >= CycleMaxi then --Si le cycle est trop long > Période-30s on allume sans coupure  
                commandArray[InterRelais]='On'
				print('Cycle >= maxi :'..Cycle..'s >> Chaudière On sur la durée du cycle maxi')
        else
            --Enfin on lance pour X seconde
            print('Cycle  Chaudière On lancé à '..hours..'h'..minutes..'pour : '..Cycle..'s et Off ensuite sur la période restante du cycle maxi')
            commandArray[1]={[InterRelais]='On'}
            commandArray[2]={[InterRelais]='Off AFTER '..tostring(Cycle)}
        end
    else
      commandArray[InterRelais]='Off'
      print('Chaudière  est sur Off en permanence bouton On/Off sur Off')    
    end
end
return commandArray
et voici les captures d'écran obtenues:
TableauDomoticzChauffagePID.jpg
TableauDomoticzChauffagePID.jpg (62.2 Kio) Consulté 12353 fois
TableauVariablesChauffage.jpg
TableauVariablesChauffage.jpg (32.44 Kio) Consulté 12353 fois
LogLuaChauffage.jpg
LogLuaChauffage.jpg (18.24 Kio) Consulté 12353 fois
Pour ton erreur vérifie le nom des variables et il faut créer le fichier dom_tmperr.txt avec des valeurs bidons au départ qui sert au calcul de la dérivée pour amorcer la régulation.
Bon courage
Raspberry Pi2 VPN, Pi 3, Pi4 ,RFXCom, 6 volets BLYSS, sondes Temp_humid Attiny85, zigbee, Mysensors, RFLINK , Zwave capteurs portes Prises, Alarme avec 2 sirènes maison esp8266, Thermostat NETAMO vannes thermostatiques
Hober Mallow
Messages : 9
Inscription : 02 oct. 2016, 21:54

Re: Regul chauffage PID

Message par Hober Mallow »

Bonjour ;

Merci pour ce complément.
J'ai toujours un message d'erreur dans les logs :
2016-10-03 17:19:51.094 Error: EventSystem: in /home/pi/domoticz/scripts/lua/script_device_thermostatv3.lua: ...e/pi/domoticz/scripts/lua/script_device_thermostatv3.lua:107: attempt to concatenate local 'consigne' (a nil value)

Je ne comprend pas pourquoi
Cela est il possible que vous me transmettiez vos paramétres de Dispositifs (Menu Regles dispositifs)

Merci d'avance
Hober Mallow
jackyhi
Messages : 97
Inscription : 09 mai 2016, 23:49

Re: Regul chauffage PID

Message par jackyhi »

Re bonsoir

L'erreur provient du fait que mon système est en simulation, c'est à dire que j'ai créé un thermostat salon set point Th_salon pour la consigne mais aussi je simule la température du chauffage en remplaçant la sonde salon par un thermostat set point SondeChauff voir les premières lignes du fichier:local VarConsigne = 'Th_salon' --Température de consigne (thermostat set point)
local SondeSj = 'SondeSejour' --Nom de la sonde de température du séjour(pas utilisée dans la simulation et à substituer à SondeChauff)
local Varsonde = 'SondeChauff' --Variable Domoticz :Nom de la sonde simulée de température (thermostat set point)
La permutation est à faire lignes 104 et 105.

En espérant que ça t'aidera.
Raspberry Pi2 VPN, Pi 3, Pi4 ,RFXCom, 6 volets BLYSS, sondes Temp_humid Attiny85, zigbee, Mysensors, RFLINK , Zwave capteurs portes Prises, Alarme avec 2 sirènes maison esp8266, Thermostat NETAMO vannes thermostatiques
Hober Mallow
Messages : 9
Inscription : 02 oct. 2016, 21:54

Re: Regul chauffage PID

Message par Hober Mallow »

Re

J'ai essayé rapidement sans sucés
Je regarderai cela tranquillement ce week end

J'ai hâte de la voir tourner, tu as un meilleur recul depuis ca miseen service ? ca réagit correctement aux element externe (ouverture porte en hiver, etc..)

cdt
jackyhi
Messages : 97
Inscription : 09 mai 2016, 23:49

Re: Regul chauffage PID

Message par jackyhi »

Je te rappelle quand même que le projet a été initié par Guitoo et que c'est son projet que je suis en train de réaliser!

Si tu veux des informations sur un fonctionnement en mode réel il vaut mieux que tu demandes à l'auteur.

Moi je n'ai pas encore essayé de le faire en réel parce que je suis en train de réaliser des sondes et des relais MySensors avec liaison radio 2,4GHz basé sur NRF24L01 qui me serviront à substituer l'horloge thermostat THEBEN qui pilote actuellement ma chaudière.
Raspberry Pi2 VPN, Pi 3, Pi4 ,RFXCom, 6 volets BLYSS, sondes Temp_humid Attiny85, zigbee, Mysensors, RFLINK , Zwave capteurs portes Prises, Alarme avec 2 sirènes maison esp8266, Thermostat NETAMO vannes thermostatiques
deennoo
Messages : 4036
Inscription : 25 janv. 2015, 02:00

Re: Regul chauffage PID

Message par deennoo »

La conceration pour Guitoo ! Son script a en parti ete adapter pour Jeedom ! Un beau plugin a 4€.

Bravo a lui, et bravo au createur du plugin qui le cite.
De quoi se faire Plaisir et essayer d'aider...
http://www.domo-attitude.fr
Neutrino
Messages : 2662
Inscription : 10 juil. 2015, 15:42
Localisation : Les Herbiers(85)

Re: Regul chauffage PID

Message par Neutrino »

:o
Il faut qu'on mettent nos scripts sous licence pour éviter que d'autre se fasse du fric avec ?
Ma maison à plein d'IP ! :mrgreen:
SAV Bonjour. Vous avez vidé le cache ?
deennoo
Messages : 4036
Inscription : 25 janv. 2015, 02:00

Regul chauffage PID

Message par deennoo »

C'est l'open source ... Il y a aussi une parti de code pour une régul PID prise ailleurs.

Il y a un fait similaire sur un autre plugin thermostat qui aurait été pompé depuis la VERA.

De façon général difficile de mettre sous licence une formule Mathématiques.

L'auteur a quand même :
Traduit le LUA en php
Fait une interface graphique
Et fait une belle documention hyper lisible et compréhensible de tous.

Soyez fière d'être source d'inspiration !

Pour le côté pecunier : je ne penses pas que les développeurs vivent bien de leurs plugins (le nombre de téléchargement ne reflète pas le nombre d'achat, car il compte le download des updates + achats + retelechargements).

Pour la license rien ne t'empêche de le faire.
De quoi se faire Plaisir et essayer d'aider...
http://www.domo-attitude.fr
Répondre