Régulation d'une chaudière Frisquet ECO radio System

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
Placez votre code entre
et {/Quote]

allezlelosc
Messages : 49
Enregistré le : 21 oct. 2015, 21:34

Re: Régulation d'une chaudière Frisquet ECO radio System

Message par allezlelosc »

caplam a écrit :Le but avoué est d'avoir une automatisation du choix des consignes en fonction d'un planning (présence / absence). Pour la geoloc ça ne me semble pas possible, les enfants n'ayant pas de smartphone.

Comme toi, mon but à la base était d'agir sur la consigne en fonction de l'occupation, mais l'analyse du comportement du système m'a fait conclure qu'une température moyenne constante valait mieux que des transitions en fonction de l'occupation. Mais comme je l'ai déjà dit "ce qui est vrai chez moi ne l'est pas forcement chez vous"

à toi d'opter pour le meilleur algorithme qui calcule la température de référence !
bon courage et surtout amuse toi !
si je peux t'aider je le ferai !

Trebor
Messages : 1
Enregistré le : 04 avr. 2016, 11:26

Re: Régulation d'une chaudière Frisquet ECO radio System

Message par Trebor »

bonjour,

J'envisage de changer ma chaudière par une condensation frisquet 18/25 kw et ecs 120 l.

après avoir regardé plusieurs vieux posts sur le net dont certains pas content de la régulation du thermostat (post de 2008), j'ai ciblé plus récent et je suis tombé sur ce post.

Le thermostat d'origine de la chaudière frisquet fait-il son travail correctement ???

Etant équipé de radiateurs acier normaux (pas basse température), dans ce cas la sonde extérieure serait elle un plus pour améliorer la condensation de la chaudière ???

allezlelosc
Messages : 49
Enregistré le : 21 oct. 2015, 21:34

Re: Régulation d'une chaudière Frisquet ECO radio System

Message par allezlelosc »

Trebor a écrit :bonjour,

J'envisage de changer ma chaudière par une condensation frisquet 18/25 kw et ecs 120 l.

après avoir regardé plusieurs vieux posts sur le net dont certains pas content de la régulation du thermostat (post de 2008), j'ai ciblé plus récent et je suis tombé sur ce post.

Le thermostat d'origine de la chaudière frisquet fait-il son travail correctement ???

Etant équipé de radiateurs acier normaux (pas basse température), dans ce cas la sonde extérieure serait elle un plus pour améliorer la condensation de la chaudière ???

Bonjour,

Pour ma part le thermostat d'origine me donnait entière satisfaction sur le plan de la régulation. J'ai décidé de changer afin de profiter des avantages d'un thermostat connecté.

si tu optes pour une chaudière Frisquet elle sera surement équipée du thermostat Eco radio system visio qui ne permet pas d'être remplacé par un autre système. Tu peux faire le test sur les sites de Netatmo ou Nest, ils te diront que leur thermostat n'est pas compatible avec la chaudière.

Concernant la condensation, si ta chaudière actuelle sort de l'eau à 70°C par 0°C extérieur afin de maintenir 20°C dans la maison, n'importe quelle chaudière devra fournir de l'eau à 70°C dans les même conditions pour maintenir 20°C. Mais à ces températures on oubli la condensation. Donc si ton installation actuelle tourne trop souvent à des températures élevées il n'est peut pas inintéressant d'investir dans une condensation, une chaudière haut rendement peut être une alternative plus judicieuse.

a+

bruch05
Messages : 43
Enregistré le : 27 févr. 2016, 21:06

Re: Régulation d'une chaudière Frisquet ECO radio System

Message par bruch05 »

Bonsoir,

Ayant une Frisquet Prestige, je travaille sur son Pilotage sur la base du fabuleux travail de allezlelosc :D

Ci après une évolution du script :

- Appel à Domoticz via les WebServices, création fonction Read et Write
- Fonction dédiée à l'interface de la chaudière (Domoticz par défaut, mais on peut mettre autre chose)
- Ajout des commentaires, cela m'a permis de maîtriser la bête !
- Implémentation d'un mode trace pour comprendre l’enchaînement des étapes

A cette heure, je n'en suis qu'à l'expérimentation, je passe ma chaudière de l'Eco Système à la Régul RIF pour se faire.
Mon ambition est la mise en oeuvre d'une régulation basée sur la T° Ext et les T° des pièces majeures.
En effet, les inerties des grandes pièces et des petites étant différentes, j'ai de grandes variations de T° dans les petites pièces vs les grandes pièces.

Tof

Code : Tout sélectionner

#!/usr/bin/python
# -*- coding: utf-8 -*

__namescript__='Regulateur-V3r0.py'
__author__= 'SSO'
__update__= 'CBR'
__version__= '3.0'
__status__= 'Build'
__created__='13/2/16'
__modified__='03/05/16'

# import pdb #Activation du mode Debug Python
import re

import ConfigParser
import sys

import json
import requests
from requests.auth import HTTPBasicAuth
import time

import domoticz
#import DbError

from datetime import datetime
import time

#***************************************************************
# Renvoie le nombre de secondes d'une date "16/08/2013 09:51:43" 
#***************************************************************
def Secondes(s):
	#s = "2013-08-16 09:51:43"
	d = datetime.strptime(s, "%Y-%m-%d %H:%M:%S")
	r = time.mktime(d.timetuple())
	return (r)

#*********************************************
# Debug Output
#*********************************************
def DebugPrint(chaine,valeur):
    if  trace == 1:
        print ("Debug Regulation : " + chaine + " : " + str(valeur))

#*********************************************
# Error Output
#*********************************************
def ErrorPrint(chaine):
    print ("Error Regulation : " + chaine)
	
#*********************************************
# Extrait valeur numérique
#*********************************************
def Valeur(chaine):
	pat = "[^A-Za-z%]+"         	#expression régulière à utilise
	prog = re.compile(pat)      	#création de l'objet d'analyse
	result = prog.search(chaine)    #extration de la chaîne à l'aide de l'expression régulière
	return (result.group())

#*********************************************
# Ecriture Device Domoticz
#*********************************************
#http://IP:PORT/json.htm?type=command&param=udevice&idx=mon_idx&svalue=POURCENTAGE
#WriteDevice("57","udevice","98")

def WriteDevice(domoticz_idx,param,val):

    write_url_text1='/json.htm?type=command&param='
    write_url_text2='&idx='
    write_url_text3='&'

    requete='http://'+domoticz_ip+':'+domoticz_port+write_url_text1+param+write_url_text2+str(domoticz_idx)+write_url_text3+val 
    #DebugPrint("WriteDevice Requete", requete)
    r=requests.get(requete,auth=HTTPBasicAuth(user,password))
    #DebugPrint("WriteDevice Return", r)	    

    if  r.status_code != 200:
        ErrorPrint ("-1-Erreur Lecture API Domoticz")
	return("KO")
    else:
	return("OK")
 

#*********************************************
# Lecture Device Domoticz
#*********************************************
#http://127.0.0.1:8080/json.htm?type=devices&rid=57
#ReadDevice("57","Data")


def ReadDevice(domoticz_idx,param):

    read_url_text1='/json.htm?type=devices&rid='

    requete='http://'+domoticz_ip+':'+domoticz_port+read_url_text1+str(domoticz_idx)
    #DebugPrint("ReadDevice Requete", requete)	
    r=requests.get(requete,auth=HTTPBasicAuth(user,password))
    #DebugPrint("ReadDevice Return", r)
	
    domoticzjson=r.json()
    for i, v in enumerate(domoticzjson["result"]):
       val= domoticzjson["result"][i][param] 
    if  r.status_code != 200:
        ErrorPrint ("-2-Erreur Lecture API Domoticz")
	return("KO")
    else:
	return(val)	

#*********************************************
# Ecriture Device Pilotage chaudière
#*********************************************
# Cette section peut etre remplacée pour piloter un device autre qu'un Device Domoticz

def WriteBoiler(domoticz_idx,param,val):

    write_url_text1='/json.htm?type=command&param='
    write_url_text2='&idx='
    write_url_text3='&'

    requete='http://'+domoticz_ip+':'+domoticz_port+write_url_text1+param+write_url_text2+str(domoticz_idx)+write_url_text3+val 
    #DebugPrint("WriteDevice Requete", requete)
    r=requests.get(requete,auth=HTTPBasicAuth(user,password))
    #DebugPrint("WriteDevice Return", r)	    

    if  r.status_code != 200:
        ErrorPrint ("-1-Erreur Lecture API Domoticz")
	return("KO")
    else:
	return("OK")


#------Paramètres généraux ----------
trace=1
domoticz_ip='192.168.0.252'
domoticz_port='8084'
user=''
password=''
CfgPID=ConfigParser.ConfigParser()
CfgPID.read('/volume1/@appstore/domoticz/var/scripts/python/NewPid.cfg')
Periode=CfgPID.getint('ParamGlobal','Periode')
ScsAdress=CfgPID.get('ParamGlobal','ScsAdress')
#----------------------------------

#--------------Idx-------------------
IdxSwitchRegul='78'		# Regulation On/Off	
IdxBoilerFault='79'		# Chaudière en sécurité
IdxSetPointTempAmb='80'		# Consigne température ambiante
IdxTempAmb='67'			# Mesure température ambiante
IdxRapCyclique='81' 		# Rapport Cyclique commande  
IdxCommande='2' 		# Switch commande chaudière  
IdxTempDepart='30'		# Mesure température départ chaudière
IdxSetPointTempDepart='82'	# Consigne température départ chaudière
#----------------------------------

#------Paramètres PID1--------------
ErrPreviousTempAmb=0.0
T0=Secondes(ReadDevice(IdxTempAmb,'LastUpdate'))
DebugPrint("T0",T0)
Integral1=0.0
Derivee1=0.0
SetPointTempDepart=0.0
StepTempDepart=False
ReleaseSetPointTempDepart=False
#----------------------------------

#------Paramètres PID2--------------
ErrPreviousTempDepart=0.0
ErrPrevious0TempDepart=0.0
RapCyc=0.0
#----------------------------------

#------Paramètres Relance----------
BoostMode=True
BoostDemand=False
ExitFromBm=False
StandBy=False
#----------------------------------

# pdb.set_trace() #Activation du mode Debug Python

while True:
	try:

		#WriteDevice(IdxSetPointTempAmb,"udevice","svalue=20") # On met la consigne à 22°C pour les tests
		DebugPrint("-----------------------","-----------------------")
		
		SwitchRegul=ReadDevice(IdxSwitchRegul,"Data")
		DebugPrint("-1-SwitchRegul", SwitchRegul)	

		BoilerFault=ReadDevice(IdxBoilerFault,"Data")
		DebugPrint("-2-BoilerFault",BoilerFault)
		
		if SwitchRegul=='On' and BoilerFault=='Off':
			StandBy=False
			DebugPrint("-3-StandBy",StandBy)

			CfgPID.read('/volume1/@appstore/domoticz/var/scripts/python/NewPID.cfg')

			#------Paramètres PID1--------------
			Kp=CfgPID.getfloat('ParamPID1','Kp')
			Ki=CfgPID.getfloat('ParamPID1','Ki')
			Kd=CfgPID.getfloat('ParamPID1','Kd')
			Bm1=CfgPID.getfloat('ParamPID1','Bm')
			ErrMaxTempAmb=CfgPID.getfloat('ParamPID1','ErrMaxTempAmb')
			LimitBasTempDepart=CfgPID.getfloat('ParamPID1','LimitBas')
			SetPointStepTempDepart=CfgPID.getfloat('ParamPID1','SetPointStepTempDepart')
			#----------------------------------

			#------Paramètres PID2--------------
			K1=CfgPID.getfloat('ParamPID2','K1')
			K2=CfgPID.getfloat('ParamPID2','K2')
			K3=CfgPID.getfloat('ParamPID2','K3')
			Bm2=CfgPID.getfloat('ParamPID2','Bm')
			ErrMaxTempDepart=CfgPID.getfloat('ParamPID2','ErrMaxTempDepart')
			RapCyc0=CfgPID.getfloat('ParamPID2','RapCyc0')
			RapCycMax=CfgPID.getfloat('ParamPID2','RapCycMax')
			#----------------------------------

			#------Paramètres Relance----------
			BoostDelay=CfgPID.getfloat('ParamBoost','Delay')
			#----------------------------------

			SetPointTempAmb=float(Valeur(ReadDevice(IdxSetPointTempAmb,"Data")))
			DebugPrint("-4-SetPointTempAmb",SetPointTempAmb)

			TempAmb=float(Valeur(ReadDevice(IdxTempAmb,"Data")))
			DebugPrint("-5-TempAmb",TempAmb)
	      
			ErrNowTempAmb=SetPointTempAmb-TempAmb
			DebugPrint("-6-ErrNowTempAmb",ErrNowTempAmb)
			
		        if BoostMode==True:
			 DebugPrint("-7-BoostMode",BoostMode)

			 if ErrNowTempAmb>Bm1:
			    RapCyc=100.0
			    Status=WriteDevice(IdxRapCyclique,"udevice","svalue=" + str(RapCyc))
			    DebugPrint("-8-RapCyc",RapCyc)	
			    if Status!='OK':
			      ErrorPrint("-3-Erreur d'écriture dans Domoticz du rapport cyclique")

			    #-------- Fermeture contact du relais--------------
		       	    Status=WriteDevice(IdxCommande,"switchlight","switchcmd=On")
			    DebugPrint("-18b-TOn","On")

			    DebugPrint("-9-BoostDelay",BoostDelay)
			    time.sleep(BoostDelay)
 			    
			    #-------- Ouverture contact du relais--------------
		       	    Status=WriteDevice(IdxCommande,"switchlight","switchcmd=Off")
			    DebugPrint("-19b-TOff","Off")
			    
			    BoostMode=False
			    FirstCycle=True
			    Integral1=0.0
			 else:
			    Status=WriteDevice(IdxSetPointTempDepart,"udevice","svalue=0.0")
			    DebugPrint("-10-SetPointTempDepart",SetPointTempDepart)	
			    if Status!='OK':
			      ErrorPrint("-4-Erreur d'écriture dans Domoticz de la consigne de température de déaprt")
			      Status=WriteDevice(IdxRapCyclique,"udevice","svalue=0")
			    if Status!='OK':
			      ErrorPrint("-5-Erreur d'écriture dans Domoticz du rapport cyclique")
		        else:
			  #----------------PID 1-------------------------
			  if ErrNowTempAmb>ErrMaxTempAmb:
			    BoostMode=True
			  elif abs(ErrNowTempAmb)>Bm1:
			    if FirstCycle==True:
			      DebugPrint("-11-FirstCycle",FirstCycle)
			      SetPointInitTempDepart=float(Valeur(ReadDevice(IdxTempDepart,'Data')))
			      SetPointTempDepart=SetPointInitTempDepart
			      FirstCycle=False
			    else:
			      if ErrNowTempAmb!=ErrPreviousTempAmb:
			        T=Secondes(ReadDevice(IdxTempAmb,'LastUpdate'))
				DebugPrint("-12-Timestamp",T)			    
				try:
				  Derivee1=(ErrNowTempAmb-ErrPreviousTempAmb)/(T-T0)
				  DebugPrint("-13a-Derivee1",Derivee1)   
				except ZeroDivisionError:
				  Derivee1=0.0
				  DebugPrint("-13b-Derivee1","Timestamp identique")
			        ErrPreviousTempAmb=ErrNowTempAmb
			        T0=T
			      if ExitFromBm==True:
			        SetPointInitTempDepart=SetPointTempDepart-Kp*ErrNowTempAmb
				DebugPrint("-14-SetPointInitTempDepart",SetPointInitTempDepart)
			        Integral1=0.0
			        ExitFromBm=False
			      SetPointTempDepart=SetPointInitTempDepart+Kp*ErrNowTempAmb+Ki*(Integral1+ErrNowTempAmb)+Kd*Derivee1
			      DebugPrint("-15-SetPointTempDepart",SetPointTempDepart)
			      DebugPrint("-15-SetPointInitTempDepart",SetPointInitTempDepart)
			      DebugPrint("-15-ErrNowTempAmb",ErrNowTempAmb)
			      DebugPrint("-15-Integral1",Integral1)
			      DebugPrint("-15-Derivee1",Derivee1)

			    if SetPointTempDepart<LimitBasTempDepart:
			      if ErrNowTempAmb>Bm1:
			        SetPointTempDepart=LimitBasTempDepart
			      else:
			        SetPointTempDepart=0.0
			        if BoostDemand==False:
				  BoostDemand=True
				  StartTimeBoostDemand=time.time()
			        else:
				  if StartTimeBoostDemand>DelayTimeBoostDemand:
				    BoostMode=True
				    BoostDemand=False
			    elif SetPointTempDepart>=SetPointStepTempDepart:
			      if StepTempDepart==False:
			        StepTempDepart=True
			        StartTimeStepTempDepart=time.time()
			      else:				
			        if (time.time()-StartTimeStepTempDepart)>3600 and ReleaseSetPointTempDepart==False:
				  ReleaseSetPointTempDepart=True			      
			      if ReleaseSetpointTempDepart==False:
			        SetPointTempDepart=SetPointStepTempDepart
			      else:
			        Integral1=Integral1+ErrNowTempAmb
			    else:			      
			      Integral1=Integral1+ErrNowTempAmb
			      StepTempDepart=False
			      ReleaseSetPointTempDepart=False
			  else:
			    ExitFromBm=True
			  Status=WriteDevice(IdxSetPointTempDepart,"udevice","svalue=" + str(round(SetPointTempDepart,1)))
			  DebugPrint("-16-SetPointTempDepart",SetPointTempDepart)
			  if Status!='OK':
			      ErrorPrint("-6-Erreur d'écriture dans Domoticz de la consigne de température de départ")
			  #----------------------------------------------

			  #----------------PID 2-------------------------
			  TempDepart=float(Valeur(ReadDevice(IdxTempDepart,'Data')))
			  ErrNowTempDepart=SetPointTempDepart-TempDepart
			  if ErrNowTempDepart>ErrMaxTempDepart:
			    BoostMode=True
			  else:
			    if SetPointTempDepart==0.0:
			      RapCyc=0.0
			    else:
			      if abs(ErrNowTempDepart)>Bm2:
			        RapCyc=RapCyc0+K1*ErrNowTempDepart+K2*(ErrNowTempDepart-ErrPreviousTempDepart)+K3*(ErrNowTempDepart+ErrPrevious0TempDepart-2*ErrPreviousTempDepart)
			      else:#Activation du mode Debug Python
			        RapCyc=RapCyc0
			    if RapCyc>RapCycMax:
			      RapCyc=RapCycMax
			    elif RapCyc<0.0:
			      RapCyc=0.0
			    ErrPrevious0TempDepart=ErrPreviousTempDepart
			    ErrPreviousTempDepart=ErrNowTempDepart
			  #----------------------------------------------

			  #------------Pilotage chaudière---------------
			  Status=WriteDevice(IdxRapCyclique,"udevice","svalue=" + str(RapCyc))
			  DebugPrint("-17-RapCyc",RapCyc)
			  
			  if Status!='OK':
			    ErrorPrint("-7-Erreur d'écriture dans Domoticz du rapport cyclique")
			  TOn=RapCyc*Periode/100
			  TOff=Periode-TOn
			  #-------- Fermeture contact du relais--------------
		       	  if TOn!=0.0:
			      Status=WriteBoiler(IdxCommande,"switchlight","switchcmd=On")
			      DebugPrint("-18a-TOn",TOn)
			      time.sleep(TOn)
			  #-------- Ouverture contact du relais--------------			  
			  if TOff!=0.0:
			      Status=WriteBoiler(IdxCommande,"switchlight","switchcmd=Off")
			      DebugPrint("-19a-TOff",TOff)
			      time.sleep(TOff)			    
			  #----------------------------------------------

		else:
		        #-------- Mise à zéro de la commande------------
		        Status=WriteBoiler(IdxRapCyclique,"udevice","svalue=0")
			DebugPrint("-20-RapCyc","0")
		        if Status!='OK':
			  ErrorPrint("-8-Erreur d'écriture dans Domoticz du rapport cyclique")
		        #----------------------------------------------

			if StandBy==False:
			  #-------- Ouverture contact du relais--------------	        
			  Status=WriteBoiler(IdxCommande,"switchlight","switchcmd=Off")
			  #----------------------------------------------

			  #------Paramètres PID1--------------
			  ErrPreviousTempAmb=0.0
			  T0=float(Valeur(ReadDevice(IdxTempAmb,'Data')))
			  Integral1=0.0
			  Derivee1=0.0
			  SetPointTempDepart=0.0
			  #----------------------------------

			  #------Paramètres PID2--------------
			  ErrPreviousTempDepart=0.0
			  ErrPrevious0TempDepart=0.0
			  #----------------------------------

			  #------Paramètres Relance----------
			  BoostMode=True
			  #----------------------------------
			  StandBy=True
		        DebugPrint("-20-Periode",Periode)
		  	time.sleep(Periode)
	except Exception, e:
    		try:
      			ErrorPrint("Exception : " + str(e))
    		except Exception, e:
      			pass
		DebugPrint("-21-Periode",Periode)
		time.sleep(Periode)
	


allezlelosc
Messages : 49
Enregistré le : 21 oct. 2015, 21:34

Re: Régulation d'une chaudière Frisquet ECO radio System

Message par allezlelosc »

Bonjour à tous,

ravi que mon travail puisse perdurer et servir à d'autres que moi !!
De mon côté j'ai mis en standby le développement car j'ai commencé un autre projet : la création de ma société. Mais le fonctionnement actuel du script me donne toujours satisfaction.

Je vous joins quand même une nouvelle version qui corrige quelques bugs dans la partie BoostMode.

Code : Tout sélectionner

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""RegulChauff.py : Script pour la régulation de chauffage"""

__namescript__='RegulChauff.py'
__author__= 'SSO'
__version__= '2.3'
__status__= 'Exploitation'
__created__='13/2/16'
__modified__='20/3/16'

import ConfigParser
import DomoJson
import time
import DbError
import SCS

#------Paramètres généraux ----------
CfgPID=ConfigParser.ConfigParser()
CfgPID.read('/home/pi/domoticz/scripts/python/Chauffage/NewPID.cfg')
Periode=CfgPID.getint('ParamGlobal','Periode')
ScsAdress=CfgPID.get('ParamGlobal','ScsAdress')
#----------------------------------

#--------------Idx-------------------
IdxSwitchRegul='112'
IdxSetPointTempAmb='111'
IdxTempAmb='16'
IdxCommande='116'
IdxTempDepart='130'
IdxBoilerFault='132'
IdxSetPointTempDepart='168'
#----------------------------------

#------Paramètres PID1--------------
ErrPreviousTempAmb=0.0
T0=DomoJson.Read(IdxTempAmb,0)
Integral1=0.0
Derivee1=0.0
SetPointTempDepart=0.0
StepTempDepart=False
ReleaseSetPointTempDepart=False
#----------------------------------

#------Paramètres PID2--------------
ErrPreviousTempDepart=0.0
ErrPrevious0TempDepart=0.0
RapCyc=0.0
#----------------------------------

#------Paramètres Relance----------
BoostMode=True
BoostDemand=False
ExitFromBm=False
#----------------------------------

#*********************************************



while True:
  try:
    SwitchRegul=DomoJson.Read(IdxSwitchRegul,3)
    BoilerFault=DomoJson.Read(IdxBoilerFault,3)
    if SwitchRegul=='On' and BoilerFault=='Off':
      StandBy=False
      CfgPID.read('/home/pi/domoticz/scripts/python/Chauffage/NewPID.cfg')

      #------Paramètres PID1--------------
      Kp=CfgPID.getfloat('ParamPID1','Kp')
      Ki=CfgPID.getfloat('ParamPID1','Ki')
      Kd=CfgPID.getfloat('ParamPID1','Kd')
      Bm1=CfgPID.getfloat('ParamPID1','Bm')
      ErrMaxTempAmb=CfgPID.getfloat('ParamPID1','ErrMaxTempAmb')
      LimitBasTempDepart=CfgPID.getfloat('ParamPID1','LimitBas')
      SetPointStepTempDepart=CfgPID.getfloat('ParamPID1','SetPointStepTempDepart')
      #----------------------------------

      #------Paramètres PID2--------------
      K1=CfgPID.getfloat('ParamPID2','K1')
      K2=CfgPID.getfloat('ParamPID2','K2')
      K3=CfgPID.getfloat('ParamPID2','K3')
      Bm2=CfgPID.getfloat('ParamPID2','Bm')
      ErrMaxTempDepart=CfgPID.getfloat('ParamPID2','ErrMaxTempDepart')
      RapCyc0=CfgPID.getfloat('ParamPID2','RapCyc0')
      RapCycMax=CfgPID.getfloat('ParamPID2','RapCycMax')
      #----------------------------------

      #------Paramètres Relance----------
      BoostDelay=CfgPID.getfloat('ParamBoost','Delay')
      DelayTimeBoostDemand=CfgPID.getfloat('ParamBoost','DelayTimeBoostDemand')
      BoostDeltaTemp=CfgPID.getfloat('ParamBoost','BoostDeltaTemp')
      SlowDownDelay=CfgPID.getfloat('ParamBoost','SlowDownDelay')
      #----------------------------------

      SetPointTempAmb=float(DomoJson.Read(IdxSetPointTempAmb,3))
      TempAmb=DomoJson.Read(IdxTempAmb,1)
      ErrNowTempAmb=SetPointTempAmb-TempAmb

      if BoostMode:
        if ErrNowTempAmb>Bm1:
          TempDepart=DomoJson.Read(IdxTempDepart,1)
          StartTempDepart=TempDepart
          StopTempDepart=StartTempDepart+BoostDeltaTemp
          StartTimeBoostMode=time.time()
          RapCyc=100.0
          Status=DomoJson.WritePercent(IdxCommande,RapCyc)
          if Status!='OK':
            DbError.Write(__namescript__,"Erreur d'écriture dans Domoticz du rapport cyclique")
          Status=SCS.LightCommand(16,ScsAdress)
          if Status!='CommandSucceeded':
            DbError.Write(__namescript__,Status)
          TempDepart=DomoJson.Read(IdxTempDepart,1)
          while TempDepart<StopTempDepart and (time.time()-StartTimeBoostMode)<BoostDelay:
            time.sleep(Periode)
            TempDepart=DomoJson.Read(IdxTempDepart,1)
          RapCyc=0.0
          Status=DomoJson.WritePercent(IdxCommande,RapCyc)
          if Status!='OK':
            DbError.Write(__namescript__,"Erreur d'écriture dans Domoticz du rapport cyclique")
          Status=SCS.LightCommand(0,ScsAdress)
          if Status!='CommandSucceeded':
            DbError.Write(__namescript__,Status)
          SetPointInitTempDepart=DomoJson.Read(IdxTempDepart,1)
          SetPointTempDepart=SetPointInitTempDepart
          time.sleep(SlowDownDelay)
          BoostMode=False
          Integral1=0.0
        else:
          Status=DomoJson.WriteTemp(IdxSetPointTempDepart,0.0)
          if Status!='OK':
            DbError.Write(__namescript__,"Erreur d'écriture dans Domoticz de la consigne de température de déaprt")
          Status=DomoJson.WritePercent(IdxCommande,0.0)
          if Status!='OK':
            DbError.Write(__namescript__,"Erreur d'écriture dans Domoticz du rapport cyclique")
      else:
        #----------------PID 1-------------------------
        if ErrNowTempAmb>ErrMaxTempAmb:
          BoostMode=True
        elif abs(ErrNowTempAmb)>Bm1:
          if ErrNowTempAmb!=ErrPreviousTempAmb:
            T=DomoJson.Read(IdxTempAmb,0)
            try:
              Derivee1=(ErrNowTempAmb-ErrPreviousTempAmb)/(T-T0)
            except ZeroDivisionError:
              Derivee1=0.0
            ErrPreviousTempAmb=ErrNowTempAmb
            T0=T
          if ExitFromBm:
            SetPointInitTempDepart=SetPointTempDepart-Kp*ErrNowTempAmb
            Integral1=0.0
            ExitFromBm=False
          SetPointTempDepart=SetPointInitTempDepart+Kp*ErrNowTempAmb+Ki*(Integral1+ErrNowTempAmb)+Kd*Derivee1
          if SetPointTempDepart<LimitBasTempDepart:
            if ErrNowTempAmb>Bm1:
              SetPointTempDepart=LimitBasTempDepart
            else:
              SetPointTempDepart=0.0
              if not BoostDemand:
                BoostDemand=True
                StartTimeBoostDemand=time.time()
              else:
                if (time.time()-StartTimeBoostDemand)>DelayTimeBoostDemand:
                  BoostMode=True
                  BoostDemand=False
          elif SetPointTempDepart>=SetPointStepTempDepart:
            if not StepTempDepart:
              StepTempDepart=True
              StartTimeStepTempDepart=time.time()
            else:
              if (time.time()-StartTimeStepTempDepart)>3600 and not ReleaseSetPointTempDepart:
                ReleaseSetPointTempDepart=True
            if not ReleaseSetpointTempDepart:
              SetPointTempDepart=SetPointStepTempDepart
            else:
              Integral1=Integral1+ErrNowTempAmb
          else:
            Integral1=Integral1+ErrNowTempAmb
            StepTempDepart=False
            ReleaseSetPointTempDepart=False
        else:
          ExitFromBm=True
          if ErrNowTempAmb!=ErrPreviousTempAmb:
            T=DomoJson.Read(IdxTempAmb,0)
            try:
              Derivee1=(ErrNowTempAmb-ErrPreviousTempAmb)/(T-T0)
            except ZeroDivisionError:
              Derivee1=0.0
            ErrPreviousTempAmb=ErrNowTempAmb
            T0=T
            SetPointTempDepart=SetPointTempDepart+Kd*Derivee1
        Status=DomoJson.WriteTemp(IdxSetPointTempDepart,round(SetPointTempDepart,1))
        if Status!='OK':
            DbError.Write(__namescript__,"Erreur d'écriture dans Domoticz de la consigne de température de départ")
        #----------------------------------------------

        #----------------PID 2-------------------------
        TempDepart=DomoJson.Read(IdxTempDepart,1)
        ErrNowTempDepart=SetPointTempDepart-TempDepart
        if ErrNowTempDepart>ErrMaxTempDepart:
          BoostMode=True
        else:
          if SetPointTempDepart==0.0:
            RapCyc=0.0
          else:
            if abs(ErrNowTempDepart)>Bm2:
              if ErrNowTempDepart>0:
                RapCyc=RapCyc0+K1*(ErrNowTempDepart-Bm2)+K2*(ErrNowTempDepart-ErrPreviousTempDepart)+K3*(ErrNowTempDepart+ErrPrevious0TempDepart-2*ErrPreviousTempDepart)
              else:
                RapCyc=RapCyc0+K1*(ErrNowTempDepart+Bm2)+K2*(ErrNowTempDepart-ErrPreviousTempDepart)+K3*(ErrNowTempDepart+ErrPrevious0TempDepart-2*ErrPreviousTempDepart)
              #Si en asservissement on veut accélérer alors on interdit de freiner si on va trop vite et inversement.
              if RapCyc<RapCyc0 and ErrNowTempAmb>Bm1:
                RapCyc=RapCyc0
              elif RapCyc>RapCyc0 and ErrNowTempAmb<-Bm1:
                RapCyc=RapCyc0
            else:
              RapCyc=RapCyc0
          if RapCyc>RapCycMax:
            RapCyc=RapCycMax
          elif RapCyc<0.0:
            RapCyc=0.0
          ErrPrevious0TempDepart=ErrPreviousTempDepart
          ErrPreviousTempDepart=ErrNowTempDepart
        #----------------------------------------------

        #------------Pilotage chaudière---------------
        Status=DomoJson.WritePercent(IdxCommande,RapCyc)
        if Status!='OK':
          DbError.Write(__namescript__,"Erreur d'écriture dans Domoticz du rapport cyclique")
        TOn=RapCyc*Periode/100
        TOff=Periode-TOn
        if TOn!=0.0:
          Status=SCS.LightCommand(11,ScsAdress)
          if Status!='CommandSucceeded':
            DbError.Write(__namescript__,Status)
          else:
            time.sleep(TOn)
        if TOff!=0.0:
          Status=SCS.LightCommand(0,ScsAdress)
          if Status!='CommandSucceeded':
            DbError.Write(__namescript__,Status)
          else:
            time.sleep(TOff)
        #----------------------------------------------

    else:
      #-------- Mise à zéro de la commande------------
      Status=DomoJson.WritePercent(IdxCommande,RapCyc)
      if Status!='OK':
        DbError.Write(__namescript__,"Erreur d'écriture dans Domoticz du rapport cyclique")
      #----------------------------------------------

      if not StandBy:
        #-------- Mise au repos du relais--------------
        Status=SCS.LightCommand(0,ScsAdress)
        if Status!='CommandSucceeded':
          DbError.Write(__namescript__,Status)
        #----------------------------------------------

        #------Paramètres PID1--------------
        ErrPreviousTempAmb=0.0
        T0=DomoJson.Read(IdxTempAmb,0)
        Integral1=0.0
        Derivee1=0.0
        SetPointTempDepart=0.0
        #----------------------------------

        #------Paramètres PID2--------------
        ErrPreviousTempDepart=0.0
        ErrPrevious0TempDepart=0.0
        #----------------------------------

        #------Paramètres Relance----------
        BoostMode=True
        #----------------------------------
        StandBy=True
      time.sleep(Periode)
  except Exception, e:
    try:
      DbError.Write(__namescript__,str(e))
    except Exception, e:
      pass
    time.sleep(Periode)


bruch05
Messages : 43
Enregistré le : 27 févr. 2016, 21:06

Re: Régulation d'une chaudière Frisquet ECO radio System

Message par bruch05 »

Bonsoir,

As tu un change log des corrections que tu as faites, histoire de m'éviter de comparer ligne à ligne. Je sais, je suis un gros fainéant.

Merci à toi et bonne chance pour ta boite :D

Tof

bruch05
Messages : 43
Enregistré le : 27 févr. 2016, 21:06

Re: Régulation d'une chaudière Frisquet ECO radio System

Message par bruch05 »

Bonsoir AllezLeLosc,

L'hiver arrive et je souhaite mettre en production ta régulation avec tes dernières évolutions.
Je pense que tu as du développer le module Python DomoJson car mes recherches n'ont rien données.
Est-il possible de me le mettre à disposition ?

Ayant des sondes de températures dans toute la maison, j'ai consolidé une température consolidée avec des poids relatifs en fonction des pièces.
L'idée est de pouvoir modifier les poids en fonction de paramètres. Pour l'instant, j'ai mis un poids double sur les grandes pièces au "doigt mouillé". J'ai une température combinée qui semble être cohérente avec le ressenti sauf dans les petites pièces.

Mon idée est donc de donner moins de poids aux pièces ensoleillées dynamiquement afin que les petites pièces à l'ombre puisse avoir de l'eau de chauffage suffisamment chaude. Dans ce mode, tous les radiateurs sont dotées de robinets thermostatiques coupant le chauffage quand le soleil donne.

J'ai implémenté le pilotage de la chaudière depuis Domoticz en passant par un module HTTP contact sec (IPX800) avec le cordon vendu à prix d'or :(

Merci pour le module et ton avis sur l'approche que j'envisage.
Tof

allezlelosc
Messages : 49
Enregistré le : 21 oct. 2015, 21:34

Re: Régulation d'une chaudière Frisquet ECO radio System

Message par allezlelosc »

Bonjour Bruch05 et à tous,


voici le module qui permet de parser le Json de Domoticz.

Code : Tout sélectionner

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""DomoJson.py : Ensemble de fonctions pour communiquer avec Domotcz via son API Json"""

__author__= 'SSO'
__version__= '1.0'
__status__= 'Developpement'
__created__ = '8/2/16'
__modified__ = '12/2/16'

import urllib2
import ConfigParser
import json


  
def Read(Idx,IdLabel,UserVar=0):
  LabelList=['LastUpdate','Temp','Percent','Data']
  Label=LabelList[IdLabel]
  
  # Initilisation des paramètres standards
  Cfg=ConfigParser.ConfigParser()
  Cfg.read("/home/pi/domoticz/scripts/python/parametres.cfg")
  IpDomo=Cfg.get('Param_domoticz','ip') # IP serveur domoticz
  PortDomo=Cfg.get('Param_domoticz','port') # port seveur domoticz

  if UserVar==0:
    Requete="http://%s:%s/json.htm?type=devices&rid=%s" % (IpDomo,PortDomo,Idx)
  elif UserVar==1:
    Requete="http://%s:%s/json.htm?type=command&param=getuservariable&idx=%s" % (IpDomo,PortDomo,Idx)
  else:
    return 'Err. Argument UserVar'
  RawData=json.loads(urllib2.urlopen(Requete).read())
  if Label=='Percent':
    Data=RawData['result'][0]['Data']
  else:
    Data=RawData['result'][0][Label]
  if IdLabel==0:
    import time
    Data=time.mktime(time.strptime(Data,'%Y-%m-%d %H:%M:%S'))
  elif IdLabel==1:
    Data=float(Data)
  elif IdLabel==2:
    Percent=''
    for i in Data:
      if i!='%':
        Percent=Percent+i
    Data=float(Percent)
  elif IdLabel==3:
    Data=str(Data)
  return Data

def WriteUserVar(Idx,Value):
  # Initilisation des paramètres standards
  cfg=ConfigParser.ConfigParser()
  cfg.read("/home/pi/domoticz/scripts/python/parametres.cfg")
  IpDomo=cfg.get('Param_domoticz','ip') # IP serveur domoticz
  PortDomo=cfg.getint('Param_domoticz','port') # port seveur domoticz

  #Requête JSON
  Requete="http://%s:%s/json.htm?type=command&param=updateuservariable&idx=%s&vname=uservariablename&vtype=uservariabletype&vvalue=%s" % (IpDomo,PortDomo,Idx,Value)
  RawData=json.loads(urllib2.urlopen(Requete).read())
  Status=str(RawData['status'])
  return Status

def WriteTemp(Idx,Temperature):
  # Initilisation des paramètres standards
  cfg=ConfigParser.ConfigParser()
  cfg.read("/home/pi/domoticz/scripts/python/parametres.cfg")
  IpDomo=cfg.get('Param_domoticz','ip') # IP serveur domoticz
  PortDomo=cfg.getint('Param_domoticz','port') # port seveur domoticz
  
  #Requête JSON
  Requete="http://%s:%s/json.htm?type=command&param=udevice&idx=%s&nvalue=0&svalue=%s" % (IpDomo,PortDomo,Idx,Temperature)
  RawData=json.loads(urllib2.urlopen(Requete).read())
  Status=str(RawData['status'])
  return Status

def WritePercent(Idx,Value):
  # Initilisation des paramètres standards
  cfg=ConfigParser.ConfigParser()
  cfg.read("/home/pi/domoticz/scripts/python/parametres.cfg")
  IpDomo=cfg.get('Param_domoticz','ip') # IP serveur domoticz
  PortDomo=cfg.getint('Param_domoticz','port') # port seveur domoticz

  #Requête JSON
  Requete="http://%s:%s/json.htm?type=command&param=udevice&idx=%s&nvalue=0&svalue=%s" % (IpDomo,PortDomo,Idx,Value)
  RawData=json.loads(urllib2.urlopen(Requete).read())
  Status=str(RawData['status'])
  return Status

def WriteSwitch(Idx,Ordre):
  if Ordre==0:
    Ordre='Off'
  elif Ordre==1:
    Ordre='On'
  elif Ordre.upper()=='OFF':
    Ordre= 'Off'
  elif Ordre.upper()=='ON':
    Ordre= 'On'
  else:
    return 'Not a valid order'
  # Initilisation des paramètres standards
  cfg=ConfigParser.ConfigParser()
  cfg.read("/home/pi/domoticz/scripts/python/parametres.cfg")
  IpDomo=cfg.get('Param_domoticz','ip') # IP serveur domoticz
  PortDomo=cfg.getint('Param_domoticz','port') # port seveur domoticz
  
  Requete="http://%s:%s/json.htm?type=command&param=switchlight&idx=%s&switchcmd=%s" % (IpDomo,PortDomo,Idx,Ordre)
  RawData=json.loads(urllib2.urlopen(Requete).read())
  Status=str(RawData['status'])
  return Status

def WriteTempHumid(Idx,Temperature,Humidity):
  # Initilisation des paramètres standards
  cfg=ConfigParser.ConfigParser()
  cfg.read("/home/pi/domoticz/scripts/python/parametres.cfg")
  IpDomo=cfg.get('Param_domoticz','ip') # IP serveur domoticz
  PortDomo=cfg.getint('Param_domoticz','port') # port seveur domoticz
  
  #Requête JSON
  if Humidity>65:
    HumidityState='3'
  elif Humidity<40:
    HumidityState='2'
  else:
    Humidity='1'
  Requete="http://%s:%s/json.htm?type=command&param=udevice&idx=%s&nvalue=0&svalue=%f;%d;%s" % (IpDomo,PortDomo,Idx,Temperature,Humidity,HumidityState)
  RawData=json.loads(urllib2.urlopen(Requete).read())
  Status=str(RawData['status'])
  return Status

def WritePrecipIntensity(Idx,PrecipIntensity):
  # Initilisation des paramètres standards
  cfg=ConfigParser.ConfigParser()
  cfg.read("/home/pi/domoticz/scripts/python/parametres.cfg")
  IpDomo=cfg.get('Param_domoticz','ip') # IP serveur domoticz
  PortDomo=cfg.getint('Param_domoticz','port') # port seveur domoticz
  
  #Requête JSON
  Requete="http://%s:%s/json.htm?type=command&param=udevice&idx=%s&nvalue=0&svalue=??;%f" % (IpDomo,PortDomo,Idx,PrecipIntensity)
  RawData=json.loads(urllib2.urlopen(Requete).read())
  Status=str(RawData['status'])
  return Status

def WritePressure(Idx,Pressure):
  # Initilisation des paramètres standards
  cfg=ConfigParser.ConfigParser()
  cfg.read("/home/pi/domoticz/scripts/python/parametres.cfg")
  IpDomo=cfg.get('Param_domoticz','ip') # IP serveur domoticz
  PortDomo=cfg.getint('Param_domoticz','port') # port seveur domoticz
  
  #Requête JSON
  Requete="http://%s:%s/json.htm?type=command&param=udevice&idx=%s&nvalue=0&svalue=%d" % (IpDomo,PortDomo,Idx,Pressure)
  RawData=json.loads(urllib2.urlopen(Requete).read())
  Status=str(RawData['status'])
  return Status


def WriteSwitchLevel(Idx,Level):
  # Initilisation des paramètres standards
  cfg=ConfigParser.ConfigParser()
  cfg.read("/home/pi/domoticz/scripts/python/parametres.cfg")
  IpDomo=cfg.get('Param_domoticz','ip') # IP serveur domoticz
  PortDomo=cfg.getint('Param_domoticz','port') # port seveur domoticz
  Level="Set%20Level&level="+str(Level)
    
  #Requête JSON
  Requete="http://%s:%s/json.htm?type=command&param=switchlight&idx=%s&switchcmd=" % (IpDomo,PortDomo,Idx)
  Requete=Requete+Level
  print Requete
  RawData=json.loads(urllib2.urlopen(Requete).read())
  Status=str(RawData['status'])
  return Status

bruch05
Messages : 43
Enregistré le : 27 févr. 2016, 21:06

Re: Régulation d'une chaudière Frisquet ECO radio System

Message par bruch05 »

Salut,

Merci pour ton retour concernant le module DomoJson.
Je te dis chapeau sur l’algorithme de boost, il y a du jus de cerveau ! :D

Mes 1er tests m'ont montré une boucle sans tempo quand la différence entre la température de la consigne et la température courante est inférieure à Bm1, cela dans la phase de boost initiale. J'ai donc rajouté une tempo afin d'éviter une boucle "sauvage".

Tu confirmes mon analyse ?

Code : Tout sélectionner

if ErrNowTempAmb>Bm1:

xxxxx

else:
          Status=WriteDevice(IdxSetPointTempDepart,"udevice","svalue=0.0")
          if Status!='OK':
            DbError.Write(__namescript__,"Erreur d'écriture dans Domoticz de la consigne de température de départ")
          Status=WriteDevice(IdxRapCyclique,"udevice","svalue=0")          
          if Status!='OK':
            DbError.Write(__namescript__,"Erreur d'écriture dans Domoticz du rapport cyclique")
          #CBR rajout afin d'éviter une boucle sans délai
          time.sleep(Periode)

allezlelosc
Messages : 49
Enregistré le : 21 oct. 2015, 21:34

Re: Régulation d'une chaudière Frisquet ECO radio System

Message par allezlelosc »

bruch05 a écrit :Salut,

Merci pour ton retour concernant le module DomoJson.
Je te dis chapeau sur l’algorithme de boost, il y a du jus de cerveau ! :D

Mes 1er tests m'ont montré une boucle sans tempo quand la différence entre la température de la consigne et la température courante est inférieure à Bm1, cela dans la phase de boost initiale. J'ai donc rajouté une tempo afin d'éviter une boucle "sauvage".

Tu confirmes mon analyse ?

Code : Tout sélectionner

if ErrNowTempAmb>Bm1:

xxxxx

else:
          Status=WriteDevice(IdxSetPointTempDepart,"udevice","svalue=0.0")
          if Status!='OK':
            DbError.Write(__namescript__,"Erreur d'écriture dans Domoticz de la consigne de température de départ")
          Status=WriteDevice(IdxRapCyclique,"udevice","svalue=0")          
          if Status!='OK':
            DbError.Write(__namescript__,"Erreur d'écriture dans Domoticz du rapport cyclique")
          #CBR rajout afin d'éviter une boucle sans délai
          time.sleep(Periode)

Salut,

effectivement il semble manquer une tempo, mais je suis un peu perdu dans toutes ces lignes de codes :oops:

je te laisse faire le test et nous dire ou placer cette tempo. ;)

bon courage

Répondre