Page 2 sur 2

Re: [DzVents] Gestion de Chauffage TPI

Publié : 29 déc. 2022, 17:45
par victor81
j'ai un probleme mais je pense que c'est du au scipt doublement des ordres
https://easydomoticz.com/forum/viewtopic.php?f=17&t=480
en effet, cette nuit, seul l'ordre on etait envoyé, meme si la chauffe etait de 50 seconde, le chauffage continuait de tourner (alors que la consigne etait largement atteinte, 24 degres au lieu de 18! et la commande off n'etait pas envoyée, le chauffage s'est arrété au changement de consigne.
je fait le test cette nuit d'arreter le script doublement d'ordre
pour info, je met le script que j'utilise

Code : Tout sélectionner

--[[
	Prerequisits
	==================================
	Domoticz v2020.2 or later (dzVents version 3.1 or later)

	Chauffage TPI
	Le principe vient d'Agonaute du forum HACF.
	https://forum.hacf.fr/t/gestion-de-bout-en-bout-du-chauffage/4897
	
-- Authors  ----------------------------------------------------------------
	V1.0 - Argonaute - Version Home Assistant
	V2.0 - Neutrino - Adaptaption pour Domoticz en DzVents
]]--


-- Variables to customize --------------------------------------------------

local zone = "salon"
local sonde = {'temperature_salon'} -- Nom de la ou des sondes de température
local sonde_ext = {'temperature_exterieure'} -- Nom de la ou des sondes de température ext si présente (option)
local OnOff = 'chauffage_TPI' -- Nom de l'interrupteur virtuel de mise en route (été/hiver)
local thermostat = 'thermostat_salon' -- nom du thermostat virtuel

-- actionneur
local radiateur = 'prise_lidl_4' -- Nom de l'interrupteur de chauffage

--Pour une installation standard aux normes, on a coeffC = 0,6 et coeffT = 0,01
local coeffC = 0.8 -- coeff qui dépend de la puissance du chauffage et de la surface. A augmenter si la consigne n'est pas atteite.
local coeffT = 0.02 -- dépend lui de l’isolation de la pièce et des pertes thermiques.A augmenter si la consigne est difficile à atteindre par grand froid.
local bandeProportionnelle = 1.5 -- différence de température entre la lecture et la consigne où la chauffe est permanente.Peut être réduite si la consigne n'est pas dépassée après la montée en température. Permet une chauffe plus rapide.

local cycle = 10 -- temps en minutes d'un cycle TPI
local secu = 20 -- temps minimum en secondes entre 2 ordres opposés
	
------------------------------------------------------------------------------
local scriptName = 'chauffageTPI-'..zone
local scriptVersion = '2.0'

-- contraindre
local function constrain(x, a, b)
	if (x < a) then
		return a
	elseif (x > b) then
		return b
	else
		return x
	end
end

local function averageTemp(domoticz,t)
  local sum = 0
  local taille = 0
  for _,v in pairs(t) do -- Get the sum of all numbers in t
    if domoticz.devices(v).lastUpdate.minutesAgo < 60 
	and tonumber(domoticz.devices(v).temperature) ~= nil then
		sum = sum + domoticz.devices(v).temperature
		taille = taille + 1
	else
		domoticz.log(domoticz.devices(v).name .." "..domoticz.devices(v).temperature.." "..domoticz.devices(v).lastUpdate.minutesAgo,domoticz.LOG_INFO)
	end
  end
  return sum / taille
end

return {
	active = true,
	logging = {
		level = domoticz.LOG_DEBUG, -- Uncomment to override the dzVents global logging setting
		--level = domoticz.LOG_ERROR, -- Uncomment to override the dzVents global logging setting
		--level = domoticz.LOG_INFO, -- Uncomment to override the dzVents global logging setting
		marker = scriptName..' '..scriptVersion
	},
	on = {
		timer = {
			'every 1 minutes',  
		},
		devices ={thermostat,
		},
	},

	execute = function(domoticz, item)
		local heatTime
		-- récupération température
		local temp = domoticz.utils.round(averageTemp(domoticz,sonde),2)
		-- récupération température ext
		local temp_ext = nil
		if sonde_ext ~= '' and sonde_ext ~= nil then
			temp_ext = domoticz.utils.round(averageTemp(domoticz,sonde_ext),2)
		else
			temp_ext = domoticz.devices(thermostat).setPoint
		end
		
		-- à chaque cycle ou quand la consigne est modifiée
		if ( domoticz.time.minutes%cycle == 0 )or item.isDevice then						
			-- si l'on veut chauffer
			if ( domoticz.devices(OnOff).active ) then
				-- récupération de la consigne
				local consigne = domoticz.devices(thermostat).setPoint

				
				-- calcul de la commande en %
				local commande
				if consigne - temp >= bandeProportionnelle then
					commande = 100
				else
					commande = ((coeffC * (consigne - temp)) + (coeffT * (consigne - temp_ext)))*100
				end
				domoticz.log("Puissance de chauffe "..commande.."%", domoticz.LOG_DEBUG)
						
				-- calcul du temps de fonctionnement
				if commande >= 100 then
					-- débordement de 20s pour ne pas couper avant recalcule
					heatTime = (cycle*60)+20
				elseif commande > 0 and commande < 100 then
					-- secu mini maxi
					heatTime = domoticz.utils.round(constrain(commande*cycle*0.6,secu,(cycle*60)-secu))
				elseif commande <= 0 then
					-- coupure retardée
					heatTime = constrain(secu-domoticz.devices(radiateur).lastUpdate.secondsAgo,0,secu)
				end
				
				-- action sur l'élément chauffant
				if heatTime > 0 then
					domoticz.devices(radiateur).switchOn()
					domoticz.devices(radiateur).switchOff().afterSec(heatTime)
				else
					domoticz.devices(radiateur).switchOff()
				end			
			
				-- journalisation
			
				domoticz.log('TPI zone: '..string.upper(zone),domoticz.LOG_DEBUG)
				if temp_ext ~= nil then
					domoticz.log('temperature ext: '..temp_ext..'°C',domoticz.LOG_DEBUG)
				end
				domoticz.log('température int : '..temp..'°C pour '..consigne..'°C souhaité',domoticz.LOG_DEBUG)
				domoticz.log('Temps de chauffe : '..heatTime.."s",domoticz.LOG_DEBUG)
				domoticz.log('CoeffC : '..coeffC,domoticz.LOG_DEBUG)
				domoticz.log('CoeffT : '..coeffT,domoticz.LOG_DEBUG)
				domoticz.log('Cycle : '..cycle..'min (sécu: '..secu..'s)',domoticz.LOG_DEBUG)
				-- avertissement si secu dépasse 1/4 du cycle
				if ((100*secu)/(60*cycle)>25) then
					domoticz.log('sécu trop importante, ralonger durée de cycle..',domoticz.LOG_ERROR)
				end
			end
		end
		-- toutes les 5 minutes, si on ne veut pas chauffer
		if ( domoticz.time.minutes%5 == 0 and domoticz.devices(OnOff).state == 'Off' ) then

			-- arrêt chauffage (renvoi commande systematique par sécurité)
			domoticz.devices(radiateur).switchOff().afterSec(constrain(secu-domoticz.devices(radiateur).lastUpdate.secondsAgo,3,secu))
		end
	end
}
je vous dirai demain si j'ai eu une amelioration, mais ce script doublement d'ordre m'a deja fait des surprises ( tourne en boucle)

Re: [DzVents] Gestion de Chauffage TPI

Publié : 31 déc. 2022, 14:44
par victor81
re
donc, oui, c'et le script de doublement d'ordre qui pose probleme
les temperatures tourne a 0.1/0.3 de difference, et ca vient surtout du taux de rafraichissement des capteurs de temperature qui renvoient des données aleatoirement entre 5 et 30 minutes

Re: [DzVents] Gestion de Chauffage TPI

Publié : 14 janv. 2023, 21:14
par garycooper
Bonjour à tous, j'ai essayé d'adapter le script à mon type de programmation. J'ai un sélecteur qui me permet de choisir plusieurs modes (Off / Manu / Auto / Eco / Hors gel) et j'ai également un switch virtuel qui simule le programmateur horaire. Il fonctionne avec succès sur toutes les pièces où je l'utilise. Par contre, j'ai voulu l'employer pour une salle de bain avec sèche serviettes en ajoutant une condition de marche forcée (avec une consigne à 40°C pour être sûr que ça reste en chauffe) en fonction d'une plage horaire (le matin et le soir). Apparemment c'est cette partie là qui ne fonctionne pas. Je ne maîtrise pas du tout le Dzvents, et encore moins la gestion d'heure ...

Le script complet et le suivant :

Code : Tout sélectionner

--[[
                Prerequisits
                ==================================
                Domoticz v2020.2 or later (dzVents version 3.1 or later)

                Chauffage TPI
                Le principe vient d'Agonaute du forum HACF.
                https://forum.hacf.fr/t/gestion-de-bout-en-bout-du-chauffage/4897
                
-- Authors  ----------------------------------------------------------------
                V1.0 - Argonaute - Version Home Assistant
                V2.0 - Neutrino - Adaptaption pour Domoticz en DzVents
]]--


-- Variables to customize --------------------------------------------------

local zone = "SdB parents"
local sonde = {'SdB parents'}		                -- Nom de la ou des sondes de température
local sonde_ext = {'Cohennoz'}			        -- Nom de la ou des sondes de température ext si présente (option)
local OnOff = 'Chauffage'                               -- Nom de l'interrupteur virtuel de mise en route (été/hiver)
local thermostat = 'Thermostat SdB parents'		-- Nom du thermostat virtuel
local thermostat_eco = 'Eco'                            -- Consigne ou 'nom' de l'interrupteur virtuel du thermostat mode Eco
local thermostat_horsgel = 'Hors gel'                   -- Consigne ou 'nom' de l'interrupteur virtuel du thermostat mode Hors gel
local programmateur = 'Programmateur chauffage' 	-- Nom de l'interrupteur de programmation de la plage de fonctionnement en 

-- actionneur
local radiateur = 'Radiateur SdB parents' 		-- Nom de l'interrupteur de chauffage

--Pour une installation standard aux normes, on a coeffC = 0,6 et coeffT = 0,01
local coeffC = 0.60 					-- coeff qui dépend de la puissance du chauffage et de la surface.
local coeffT = 0.01 					-- dépend lui de l’isolation de la pièce et des pertes thermiques.
local bandeProportionnelle = 1.5 			-- différence de température entre la lecture et la consigne où la chauffe est permanente.

local cycle = 10 -- temps en minutes d'un cycle TPI
local secu = 30 -- temps minimum en secondes entre 2 ordres opposés
                
------------------------------------------------------------------------------
local scriptName = 'Chauffage '..zone
local scriptVersion = '2.0'

-- contraindre
local function constrain(x, a, b)
                if (x < a) then
                               return a
                elseif (x > b) then
                               return b
                else
                               return x
                end
end

local function averageTemp(domoticz,t)
  local sum = 0
  local taille = 0
  for _,v in pairs(t) do -- Get the sum of all numbers in t
    if domoticz.devices(v).lastUpdate.minutesAgo < 60 
                and tonumber(domoticz.devices(v).temperature) ~= nil then
                               sum = sum + domoticz.devices(v).temperature
                               taille = taille + 1
                else
                               domoticz.log(domoticz.devices(v).name .." "..domoticz.devices(v).temperature.." "..domoticz.devices(v).lastUpdate.minutesAgo,domoticz.LOG_INFO)
                end
  end
  return sum / taille
end

return {
                active = true,
                logging = {
                               -- level = domoticz.LOG_DEBUG, -- Uncomment to override the dzVents global logging setting
                               level = domoticz.LOG_ERROR, -- Uncomment to override the dzVents global logging setting
                               -- level = domoticz.LOG_INFO, -- Uncomment to override the dzVents global logging setting
                               marker = scriptName..' '..scriptVersion
                },
                on = {
                               timer = {
                                               'every 1 minutes',  
                               },
                               devices ={thermostat,
                               },
                },

                execute = function(domoticz, item)
                               local heatTime
                               -- récupération température
                               local temp = domoticz.utils.round(averageTemp(domoticz,sonde),2)
                               -- récupération température ext
                               local temp_ext = nil
                               if sonde_ext ~= '' and sonde_ext ~= nil then
                                               temp_ext = domoticz.utils.round(averageTemp(domoticz,sonde_ext),2)
                               else
                                               temp_ext = domoticz.devices(thermostat).setPoint
                               end
                               
                               -- à chaque cycle ou quand la consigne est modifiée
                               if ( domoticz.time.minutes%cycle == 0 ) or item.isDevice then                                                                                   

	 			       -- fonctionnement Hors Gel
	                               if domoticz.devices(OnOff).state == 'Hors gel' then
                                               consigne = domoticz.devices(thermostat_horsgel).setPoint
				       end

 				       -- fonctionnement Off
                        	       if domoticz.devices(OnOff).state == 'Off' then
                                               consigne = 0
				       end

	 			       -- fonctionnement Manu
	                               if domoticz.devices(OnOff).state == 'Manu' then
                                               consigne = domoticz.devices(thermostat).setPoint
				       end

				       -- Fonction seche-serviette
				       if domoticz.devices(OnOff).state == 'Auto' and (((os.time(domoticz.time) > '07:00') and (os.time(domoticz.time) < '09:00')) or ((os.time(domoticz.time) > '18:00') and (os.time(domoticz.time) < '21:00'))) then
					       consigne = 40
				       end

	                               -- fonctionnement Auto
	                               if domoticz.devices(OnOff).state == 'Auto' then
						if domoticz.devices(programmateur).active then
                                                	consigne = domoticz.devices(thermostat).setPoint
						else
							consigne = domoticz.devices(thermostat_eco).setPoint
						end	
	                               end                                
                                                               -- calcul de la commande en %
                                                               local commande
                                                               if consigne - temp >= bandeProportionnelle then
                                                                               commande = 100
                                                               else
                                                                               commande = ((coeffC * (consigne - temp)) + (coeffT * (consigne - temp_ext)))*100
                                                               end
                                                               domoticz.log("Puissance de chauffe "..commande.."%", domoticz.LOG_DEBUG)
                                                                                              
                                                               -- calcul du temps de fonctionnement
                                                               if commande >= 100 then
                                                                               -- débordement de 20s pour ne pas couper avant recalcule
                                                                               heatTime = (cycle*60)+20
                                                               elseif commande > 0 and commande < 100 then
                                                                               -- secu mini maxi
                                                                               heatTime = domoticz.utils.round(constrain(commande*cycle*0.6,secu,(cycle*60)-secu))
                                                               elseif commande <= 0 then
                                                                               -- coupure retardée
                                                                               heatTime = constrain(secu-domoticz.devices(radiateur).lastUpdate.secondsAgo,0,secu)
                                                               end
                                                               
                                                               -- action sur l'élément chauffant
                                                               if heatTime > 0 then
                                                                               domoticz.devices(radiateur).switchOn()
                                                                               domoticz.devices(radiateur).switchOff().afterSec(heatTime)
                                                               else
                                                                               domoticz.devices(radiateur).switchOff()
                                                               end                                       
                                               
                                                               -- journalisation
                                               
                                                               domoticz.log('TPI zone: '..string.upper(zone),domoticz.LOG_DEBUG)
                                                               if temp_ext ~= nil then
                                                                               domoticz.log('temperature ext: '..temp_ext..'°C',domoticz.LOG_DEBUG)
                                                               end
                                                               domoticz.log('temperature int : '..temp..'°C pour '..consigne..'°C voulu',domoticz.LOG_DEBUG)
                                                               domoticz.log('Temps de chauffe : '..heatTime.."s",domoticz.LOG_DEBUG)
                                                               domoticz.log('CoeffC : '..coeffC,domoticz.LOG_DEBUG)
                                                               domoticz.log('CoeffT : '..coeffT,domoticz.LOG_DEBUG)
                                                               domoticz.log('Cycle : '..cycle..'min (secu: '..secu..'s)',domoticz.LOG_DEBUG)
                                                               -- avertissement si secu dépasse 1/4 du cycle
                                                               if ((100*secu)/(60*cycle)>25) then
                                                                               domoticz.log('secu trop importante, rallonger duree de cycle..',domoticz.LOG_ERROR)
                                                               end					
                              end
                              
                               -- toutes les 5 minutes, si on ne veut pas chauffer
                               if ( domoticz.time.minutes%5 == 0 and domoticz.devices(OnOff).state == 'Off' ) then

                                               -- arrêt chauffage (renvoi commande systematique par sécurité)
                                               domoticz.devices(radiateur).switchOff().afterSec(constrain(secu-domoticz.devices(radiateur).lastUpdate.secondsAgo,3,secu))
                               end
                end
}
La partie qui me met en erreur est celle-ci :

Code : Tout sélectionner

				       -- Fonction seche-serviette
				       if domoticz.devices(OnOff).state == 'Auto' and (((os.time(domoticz.time) > '07:00') and (os.time(domoticz.time) < '09:00')) or ((os.time(domoticz.time) > '18:00') and (os.time(domoticz.time) < '21:00'))) then
					       consigne = 40
				       end
J'imagine que ça provient de
os.time(domoticz.time)
mais je n'ai pas trouvé comment coder. Si quelquu'un peut me débugger ça, ce serait TOP

Re: [DzVents] Gestion de Chauffage TPI

Publié : 14 janv. 2023, 22:06
par Keros
Pour les fonctions avec une plage horaire, je créai un device virtuel dans lequel je mets mon planning et dans mes scripts, je vérifie le On ou le Off du planning pour faire des actions.

Vu que tu cherches des heures pleines, j'essaierai (je n'ai pas testé) :

Code : Tout sélectionner

local Time = require('Time')
local now = Time() -- current time 
if now.hour >= 7 and now.hour <= 9 then 
Wiki DzVents - Time

Re: [DzVents] Gestion de Chauffage TPI

Publié : 15 janv. 2023, 20:03
par garycooper
Merci Keros ! Je teste ça

Re: [DzVents] Gestion de Chauffage TPI

Publié : 24 oct. 2025, 23:10
par chrisgen
Bonsoir
Après avoir profité pendant de nombreux mois de la très bonne version de Neutrino , je l' ai légèrement modifiée pour gérer plusieurs pièces dans le même script .Ayant récupérer quelques xanlite en plus de mes vieux qbino , j' ai également intégré leurs gestions (légèrement différentes) . On peut gérer ainsi un certain nombres de pièces ( en fonction de la puissance de sa bécane ;) ) etr on peut surcharger les différentes constantes . J' ai laissé quelques commentaires et logs pour mon débogage ..

Code : Tout sélectionner

--[[
    GESTION TPI CHAUFFAGE - 
   
    - Traitement par timer toutes les X minutes
    - Gestion indépendante des zones
    	Le principe vient d'Agonaute du forum HACF.
	https://forum.hacf.fr/t/gestion-de-bout-en-bout-du-chauffage/4897
	
-- Authors  ----------------------------------------------------------------
	V1.0 - Argonaute - Version Home Assistant
	V2.0 - Neutrino - Adaptaption pour Domoticz en DzVents
	V3.0 - chrisgen dernière modif 03/10/2025
    
    
]]
local dz = domoticz
local scriptName = 'THERMOSTAT TPI MULTI-POSTES '
local scriptVersion = 'V3.0'

-- Configuration GLOBALE

local configGlobale = {
    sonde_ext = {'METEO EXTERIEURE'},  ---------table sonde extérieure 
    sonde_ext1 = {'THB'},			   ---------table sonde ext 2 
    			  
    coeffC = 0.63,                  ----Coefficient de proportionnalité pour l’écart de température intérieure.  Plus il est élevé, plus la réaction est forte sinon surchargé dans def 
    coeffT = 0.01,                  ----Coefficient de proportionnalité pour l’influence de la température extérieure  Plus il est élevé, plus le chauffage compense le froid extérieur. sinon surchargé dans def 
    bandeProportionnelle = 1.5,     ----Seuil au-delà duquel le chauffage est activé à 100%   Plus il est bas, plus le chauffage s’active tôt. sinon surchargé dans def 
    cycle = 15,               -- Cycle TPI en minutes sinon surchargé dans def 
    secu = 30,                -- Sécurité entre ordres opposés (secondes) sinon surchargée dans def 
    tempDefault = 20.0        -- Température par défaut si sonde invalide sinon surchargée dans def 
}

-- Configuration par ZONE
local regulation = {
    ["bureau"] = {
        zone = "BUREAU",
        sonde = {'MQTT_MAPPER - Bureau'},  ----- table température 
        thermostat = xx,             ----------device virtuel type thermostat
        IDXFILPILOTE = xxxx,           ----------device virtuel type selector (off,hg,eco,confort etc)
        idx_sonde = xxxx,              ----------sonde température  
        typeFilPilote = "xanlite"
    },
    ["radiateur1"] = {
        zone = "SALON",
        sonde = {'TEMPERATURE SALON (S2)'},
        thermostat = x,
        IDXFILPILOTE = x,
        idx_sonde = x,
        typeFilPilote = "qbino",
        coeffT = 0.01,                          -----------surcharge
        secu = 30								-----------surcharge 
    },
    ["radiateur2"] = {
        zone = "SALON",
        sonde = {'MQTT_MAPPER - Radiateur2'},
        thermostat = x,
        IDXFILPILOTE = x,
        idx_sonde = x,
        typeFilPilote = "xanlite",
        coeffT = 0.03,
        secu = 30
    },
    ["radiateur3"] = {
        zone = "CHAMBRE",
        sonde = {'MQTT_MAPPER - Radiateur3'},
        thermostat = x,
        IDXFILPILOTE = x,
        idx_sonde = x,
        typeFilPilote = "xanlite",
        cycle = 10,
        bandeProportionnelle = 1.5,
        coeffT = 0.03,
        secu = 30
    },
     ["sb"] = {
        zone = "SB",
        sonde = {'TEMPERATURE SB)'},      
        thermostat = x,                             
        IDXFILPILOTE = x,
        idx_sonde = x,
        typeFilPilote = "qbino",
        secu = 60
    },
    ["cuisine"] = {
        zone = "CUISINE",
        sonde = {'TEMPERATURE AT BMP28 cuisine'},
        thermostat = x,
        IDXFILPILOTE = x,
        idx_sonde = x,
        typeFilPilote = "qbino",
        secu = 45
    }, 
    ["couloir"] = {
        zone = "COULOIR",
        sonde = {'MQTT_MAPPER - Couloir'},
        thermostat = x,
        IDXFILPILOTE = x,
        idx_sonde = x,
        typeFilPilote = "xanlite",
        secu = 60
    }
}

-- Modes par type de fil pilote
local modesFilPilote = {
    qbino = { horsGel = 10, confort = 50 },
    xanlite = { horsGel = 50, confort = 20 }
}
------------------------------------------------------------------------------------------------------------------------------------------------
        -------------  ne pas oublier de  créer TPI_LastProcessed_bureau = {initial = 0},   TPI_LastProcessed_radiateur1 = {initial = 0},    etc dans global_data

-- Fonctions utilitaires
local function constrain(x, a, b)
    return x < a and a or (x > b and b or x)
end

local function averageTemp(dz, t)
    local sum, count = 0, 0
    for _, v in pairs(t) do
        local device = dz.devices(v)
        if device and device.lastUpdate.minutesAgo < 60 and device.temperature then
            sum = sum + device.temperature
            count = count + 1
        else
            --dz.log(string.format("⚠️ %s : donnée invalide (age: %d min, temp: %.1f)",device and device.name or "nil",device and device.lastUpdate.minutesAgo or -1,device and device.temperature or 20),dz.LOG_INFO)
        end
    end
    return count > 0 and (sum / count) or nil
end

return {
    active = true,
    logging = {
        level = dz.LOG_INFO,
        marker = scriptName..scriptVersion
    },
    on = {
        devices = {
            regulation.bureau.thermostat,
            regulation.radiateur1.thermostat,
            regulation.radiateur2.thermostat,
            regulation.radiateur3.thermostat,
            regulation.cuisine.thermostat,
            regulation.sb.thermostat,
            regulation.couloir.thermostat
        },
        timer = {'every minute'}
    },

    execute = function(dz, item)
        -- Récupération température extérieure (commune)
        local temp_ext = averageTemp(dz, configGlobale.sonde_ext) or
                         averageTemp(dz, configGlobale.sonde_ext1) or
                         configGlobale.tempDefault
        temp_ext = math.floor(temp_ext * 10) / 10
        
        local Time = require('Time')
        local maintenant = Time().dDate

        -- Initialisation pour les événements device
        local changedThermostatIdx = item.isDevice and item.idx or 0

        -- Boucle sur chaque zone
        for zoneName, r in pairs(regulation) do
            -- Clé pour stocker la dernière date de traitement de cette zone
            local lastProcessedKey = 'TPI_LastProcessed_' .. zoneName
            local lastProcessed = dz.globalData[lastProcessedKey] 
            if  lastProcessed ==nil
               then 
               dz.globalData[lastProcessedKey] =0
               lastProcessed = tonumber(dz.globalData[lastProcessedKey])
            end    
           

            -- Récupération température intérieure
            local temp = averageTemp(dz, r.sonde) or
                         dz.devices(r.idx_sonde).temperature or
                         configGlobale.tempDefault
            temp = math.floor(temp * 10) / 10          -------plus grand entier inférieur ou egal au nombre

            -- Récupération de la consigne actuelle
            local consigne = dz.devices(r.thermostat).setPoint or configGlobale.tempDefault
            local cycle = r.cycle or configGlobale.cycle
          
            if ( dz.time.minutes%cycle == 0 ) or (item.isDevice and item.idx ==changedThermostatIdx) then	
                -- Mettre à jour la date de dernier traitement
                dz.globalData[lastProcessedKey] = maintenant
               
                -- Utilise les coefficients globaux, sauf si redéfinis localement
                local coeffC = r.coeffC or configGlobale.coeffC
                local coeffT = r.coeffT or configGlobale.coeffT
                local bande = r.bandeProportionnelle or configGlobale.bandeProportionnelle
                local secu = r.secu or configGlobale.secu

                -- Calcul de la commande
                local commande = (consigne - temp) >= bande and 100 or
                                 math.max(0, (coeffC * (consigne - temp) + coeffT * (consigne - temp_ext)) * 100)

 -- Calcul du temps de chauffe
                local heatTime
                if commande >= 100 then
                    heatTime = cycle * 60 + 20      ------en secondes 
                elseif commande > 0 then
                    heatTime = dz.utils.round(constrain(commande * cycle * 0.6, secu, cycle * 60 - secu))
                else
                    -- Si la température est déjà au-dessus de la consigne, pas de chauffe
                    if commande <= 0 and temp >= consigne then
                        heatTime = 0
                    else
                        heatTime = constrain(secu - (dz.devices(r.IDXFILPILOTE).lastUpdate.secondsAgo or 0), 0, secu)
                    end
                end
                dz.log(string.format("ℹ️ [%s]  heatTime  temps de chauffe calculé  %d secondes  ",zoneName, heatTime),dz.LOG_INFO)
                -- Récupération des modes selon le type de fil pilote
                local modes = modesFilPilote[r.typeFilPilote]

                -- Action sur le fil pilote
                if temp == -1 then  --------erreur dans la valeur des sondes températures 
                    dz.devices(r.IDXFILPILOTE).switchSelector(modes.horsGel).checkFirst()
                    dz.log(" mode hors gel pour erreur sonde   :".. zoneName,dz.LOG_DEBUG)
                elseif heatTime > 90 then      ----- pour éviter cycle allumage inf à 90 s  on peut laisser à 0 -----> secu 
                    dz.devices(r.IDXFILPILOTE).switchSelector(modes.confort)             ----.checkFirst()
                    dz.log(" mode confort   :".. zoneName,dz.LOG_DEBUG)
                    dz.devices(r.IDXFILPILOTE).switchSelector(modes.horsGel).afterSec(heatTime)
                    
                else
                    dz.devices(r.IDXFILPILOTE).switchSelector(modes.horsGel).checkFirst()
                    dz.log(string.format("🐛".."[%s]  heatTime : %d  ",zoneName, heatTime),dz.LOG_INFO)
                end

                -- Journalisation
                dz.log(string.format("ℹ️".." [%s]   Température intérieure: %.1f°C | Consigne: %.1f°C | Commande: %.0f%% | Chauffe: %ds | Mode: %s",
                    zoneName, temp, consigne, commande, heatTime, r.typeFilPilote), dz.LOG_INFO)
            end
        end
    end
}

Re: [DzVents] Gestion de Chauffage TPI

Publié : 29 oct. 2025, 18:14
par chrisgen
J ' ai modifié le calcul du temps de chauffe : si température supérieure ou = à la consigne heatime =0 ; je trouvais que le script finassait trop ..

Code : Tout sélectionner

 -- Calcul du temps de chauffe
                local heatTime
                if commande >= 100 then
                    heatTime = cycle * 60 + 20      ------en secondes 
                elseif commande > 0 then
                    heatTime = dz.utils.round(constrain(commande * cycle * 0.6, secu, cycle * 60 - secu))
                else
                    -- Si la température est déjà au-dessus de la consigne, pas de chauffe
                    if commande <= 0 and temp >= consigne then
                        heatTime = 0
                    else
                        heatTime = constrain(secu - (dz.devices(r.IDXFILPILOTE).lastUpdate.secondsAgo or 0), 0, secu)
                    end
                end
                dz.log(string.format("ℹ️ [%s]  heatTime  temps de chauffe calculé  %d secondes  ",zoneName, heatTime),dz.LOG_INFO)
                -- Récupération des modes selon le type de fil pilote
                local modes = modesFilPilote[r.typeFilPilote]

Re: [DzVents] Gestion de Chauffage TPI

Publié : 20 nov. 2025, 08:22
par ogulf
Voilà plusieurs années que j'utilise le script PID de Vill1driver : 7 scripts pour 7 pièces, chacun s'exécutant à tour de rôle (heure modulo 7) pour ne pas saturer le donneur d'ordre.

Et il est vrai que j'ai un effet de pompage, d'oscillation avant d'atteindre la consigne.

Suite au déterrage de ce post, je vais regarder cette nouvelle approche, en testant sur des pièces non critiques (je vais me faire eng...ler si un matin il fait 16 dans la cuisine, surtout en ce moment :mrgreen:).
Et ça va me permettre de rentrer dans le monde DzVents :geek: