Bonsoir,
Ayant une Frisquet Prestige, je travaille sur son Pilotage sur la base du fabuleux travail de allezlelosc
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¶m=udevice&idx=mon_idx&svalue=POURCENTAGE
#WriteDevice("57","udevice","98")
def WriteDevice(domoticz_idx,param,val):
write_url_text1='/json.htm?type=command¶m='
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¶m='
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)