Warmwasser Steuerung mit fallwinkel temperaturkurve u. kessel-sofortstart

Begonnen von epsrw1, 28 Mai 2014, 21:25:53

Vorheriges Thema - Nächstes Thema

epsrw1

hier ein teil eines moduls das ich gerade in arbeit habe. warmwassersteuerung mißt die temperatur und schaltet die ladepumpe ein und aus. zusätzlich kann ein boost relais definiert werden, welches die (bei mir vorhandene) analoge max.temperatur begrenzung übergeht.
weiter wird die temperaturkurve erfaßt, und ein fallender winkel von 1 grad pro minute erkannt, um die pumpe sofort zu starten und einen start-befehl für den kesselbrenner zu triggern.
so kann ich die wasserspeicher-temp auf absolutem minimum einstellen und habe trotzdem genug warmwasser für ausgiebige dusche ohne daß das nachströmende kaltwasser während der entnahme mich einfriert.
alle parameter sind über attr. einstellbar.


sub WarmWasserRegler($){
my $hash = $_[0];
my $name = $hash->{NAME};
#desired-temp aus dummy, based on time schedule
#kurve stark fallend => sofortiger brenner-start
my $now = gettimeofday();
my $zhkWwSollTemp = ReadingsVal($name, "zhkWwSollTemp", 30); #user setting
my $zhkWwTempSensorFhemDev = AttrVal($name, "zhkWwTempSensorFhemDev", "5_15_WarmWasser_EB6F98050000");
my $zhkWwTempSensorReading = AttrVal($name, "zhkWwTempSensorReading", "temperature");
#sensor ignorieren wenn state-age > x seconds
my $zhkWwTempSensorMaxAge = AttrVal($name, "zhkWwTempSensorMaxAge", 30);
my $zhkWwTempSensorDefaultOnFailure = AttrVal($name, "zhkWwTempSensorDefaultOnFailure", "70");
#get sensor reading or fallback to Age-default
my $zhkWwIstTempVal = ReadingsVal($zhkWwTempSensorFhemDev, $zhkWwTempSensorReading, $zhkWwTempSensorDefaultOnFailure);
my $zhkWwIstTempTimestamp = ReadingsTimestamp($zhkWwTempSensorFhemDev,$zhkWwTempSensorReading,0);
$zhkWwIstTempTimestamp = time_str2num($zhkWwIstTempTimestamp);
if($zhkWwIstTempTimestamp<($now-$zhkWwTempSensorMaxAge)){
$zhkWwIstTempVal = $zhkWwTempSensorDefaultOnFailure;
#bogus reading may appear: ToDo...
}
#relais um analoge temperaturbegrenzug zu übergehen, zB für monatliches kochen
my $zhkWwBoostStartTemp = AttrVal($name, "zhkWwBoostStartTemp", 45);
if($zhkWwSollTemp>$zhkWwBoostStartTemp){ WwBoostStopStart($hash,1); }else{ WwBoostStopStart($hash,0) }
#alpha der $zhkWwIstTempVal errechnen falls letzter wert im cache existiert
#seconds age actual reading
my $newAge = $now-$zhkWwIstTempTimestamp;
my ($zhkWwIstLastReading,$zhkWwIstLastReadingTimestamp) = split(/=/,ReadingsVal($name, "zhkWwIstLastReading", "0=1401111111"));
#seconds age last reading olther than new one
my $oldAgeDiffToNew = $now-$zhkWwIstLastReadingTimestamp-$newAge;
#change $zhkWwIstLastReading, calc linear for 1 minute before new
if($oldAgeDiffToNew==0){ return; } #nothing more to to if no temp.reading present
$zhkWwIstLastReading = $zhkWwIstTempVal+($zhkWwIstLastReading-$zhkWwIstTempVal)/$oldAgeDiffToNew*60;
#get the temp diff for past 1 minute
my $zhkWwAlphaActualVal = $zhkWwIstTempVal-$zhkWwIstLastReading; #minus=fallend, plus=steigend
readingsSingleUpdate($hash, "zhkWwAlphaActualVal", $zhkWwAlphaActualVal, 1); #update temp-reading-cache
readingsSingleUpdate($hash, "zhkWwIstLastReading", $zhkWwIstTempVal."=".$zhkWwIstTempTimestamp, 1); #update temp-reading-cache


#debug alpha here
#readingsSingleUpdate($hash, "zhkWwIstLastReading", ($zhkWwIstTempVal+1)."=".$zhkWwIstTempTimestamp, 1); #update temp-reading-cache
#debug alpha here

my $zhkWwAlphaDownAlarmDiffDeg = AttrVal($name, "zhkWwAlphaDownAlarmDiffDeg",0.8);
my $zhkWwAlphaUpAlarmDiffDeg = AttrVal($name, "zhkWwAlphaUpAlarmDiffDeg", 5);
#minus=fallend, plus=steigend
my $tempIsFalling = ((abs($zhkWwAlphaActualVal)==$zhkWwAlphaActualVal)?0:1);
$zhkWwAlphaActualVal=abs($zhkWwAlphaActualVal);
if($tempIsFalling and ($zhkWwAlphaActualVal>$zhkWwAlphaDownAlarmDiffDeg)){
#falling and diff already over limit
#trigger immediate burn start, begin of warmWater use
BrennerStopStart($hash,0); #will remain on for 5min ($zhkBrennerTaktMinOnSec)
readingsSingleUpdate($hash, "zhkWwPriorityOn", "1", 0); #update priority-active-reading
#}elsif(!$tempIsFalling and ($zhkWwAlphaActualVal>$zhkWwAlphaUpAlarmDiffDeg)){
##raising and diff already over limit ->do nothing
}
#classic pump on/off handling
my $zhkWwAlphaThreshold = AttrVal($name, "zhkWwAlphaThreshold", 1);
if(ReadingsVal($name, "zhkWwPriorityOn", 0) or abs($zhkWwIstTempVal-$zhkWwSollTemp)>$zhkWwAlphaThreshold){
WwPumpStopStart($hash,0);
}elsif(abs($zhkWwIstTempVal-$zhkWwSollTemp)<$zhkWwAlphaThreshold){
#untergrenze erreicht, priority wieder abschalten
readingsSingleUpdate($hash, "zhkWwPriorityOn", "0", 0); #update priority-active-reading
}elsif($zhkWwIstTempVal>$zhkWwSollTemp){
WwPumpStopStart($hash,1);
}
#Log3($name, 3, "ZHK $name abnachrechts: zhkWwAlphaActualVal: $zhkWwAlphaActualVal :\n");
#readingsSingleUpdate($hash, "now", $now, 1);
#Log3($name, 3, "ZHK $name abnachrechts: zhkWwIstTempVal: $zhkWwIstTempVal :");
#Log3($name, 3, "ZHK $name abnachrechts: zhkWwIstLastReading: $zhkWwIstLastReading :C end of sub");
#return;
return;
}

sub WwPumpStopStart($$){
my ($hash, $startstop) = @_;
my $name = $hash->{NAME};
my $zhkWwPumpLaststart = ReadingsVal($name, "zhkWwPumpLaststart", 0);
my $zhkWwTaktMinOnSec = AttrVal($name, "zhkWwTaktMinOnSec", 60);
#laststart: min takt before off/on
if($startstop==0 and ($zhkWwPumpLaststart+$zhkWwTaktMinOnSec)<gettimeofday()){
#turn on without delay
}elsif($startstop==1 and ($zhkWwPumpLaststart+$zhkWwTaktMinOnSec)<gettimeofday()){
return; #delay before turning off
}
my $zhkWwPumpFhemDev = AttrVal($name, "zhkWwPumpFhemDev", "P7_WwStop");
#set on/off if state-change desired (refuse to set same state again)
if(ReadingsVal($zhkWwPumpFhemDev,"state",2) eq $startstop){return;}
# fhem("set ".$zhkWwPumpFhemDev." ".$startstop);
readingsSingleUpdate($hash, "zhkWwPumpStopStatus", ($startstop==0?"off":"on") , 1); #update reading for frontend
Log3($name, 3, "ZHK $name: WwPumpStopStart:".$startstop);
return;
}
sub WwBoostStopStart($$){
my ($hash, $startstop) = @_;
my $name = $hash->{NAME};
my $zhkWwPumpLaststart = ReadingsVal($name, "zhkWwPumpLaststart", 0);
my $zhkWwTaktMinOnSec = AttrVal($name, "zhkWwTaktMinOnSec", 60);
#laststart: min takt before off/on
my $zhkWwBoostFhemDev = AttrVal($name, "zhkWwBoostFhemDev", "P2_WwBoost");
#set on/off if state-change desired (refuse to set same state again)
if(ReadingsVal($zhkWwBoostFhemDev,"state",2) eq $startstop){return;}
# fhem("set ".$zhkWwBoostFhemDev." ".$startstop);
readingsSingleUpdate($hash, "zhkWwBoostStatus", ($startstop==0?"off":"on") , 1); #update reading for frontend
Log3($name, 3, "ZHK $name: WwPumpStopStart:".$startstop);
return;
}



zhkWwAlphaDownAlarmDiffDeg attr float 0.8 zhk Ww Alpha DownAlarm DiffDeg mindest-temp-diff für sofort-aufheizung
zhkWwAlphaUpAlarmDiffDeg attr float 5 zhk Ww Alpha UpAlarm DiffDeg min.diff zu abschaltung hot für AlphaUp
zhkWwAlphaThreshold attr float 1 zhk Ww Alpha Threshold Meßtoleranz ww-temp °C
zhkWwAlphaActualVal cache float zhk Ww Alpha Actual Val zuletzt berechneter wert für alpha
zhkWwIstLastReading cache string zhk Ww Ist LastReading cached last OW temp for alpha-calc
zhkWwIstLastReading2 cache string zhk Ww Ist LastReading2 cached last OW temp for alpha-calc
zhkWwPumpStopStatus cache string off zhk Ww Pump StopStatus
zhkWwBoostStatus cache string off zhk Ww Boost Status
zhkWwTaktMinOnSec attr int 60 zhk Ww Takt MinOnSec delay before off when WwPump started
zhkWwPumpLaststart cache int zhk Ww Pump Laststart
zhkWwSollTemp set-reading float 30 zhk Ww Soll Temp einstellung User (zeitplan mit at möglich)
zhkWwPriorityOn reading int 0 sub kessel? zhk Ww Priority On wenn 1, dann brenner sofort starten
zhkWwPumpFhemDev attr string P7_WwStop zhk Ww Pump FhemDev WW pumpe, 0=on / 1=off
zhkWwBoostFhemDev attr string P2_WwBoost zhk Ww Boost FhemDev relais um analoge temperaturbegrenzug zu übergehen
zhkWwBoostStartTemp attr int 45 zhk Ww Boost StartTemp temp. ab der die umgehung notwendig ist
zhkWwTempSensorFhemDev attr string 5_15_WarmWasser_EB6F98050000 zhk Ww TempSensor FhemDev
zhkWwTempSensorReading attr string temperature zhk Ww TempSensor Reading
zhkWwTempSensorMaxAge attr int 300 5min zhk Ww TempSensor MaxAge sensor ignorieren wenn state-age > x seconds
zhkWwTempSensorDefaultOnFailure attr int 70 zhk Ww TempSensor DefaultOnFailure
zhkWwIstTempVal cache float OW value zhk Ww Ist Temp Val OW lesen, wenn fehler dann default MAX
zhkWwIstTempTimestamp cache string 35 OW value zhk Ww Ist Temp Timestamp timestamp last OW update





Internals:
   CFGFN
   DEF        autocontrol
   NAME       zhk4
   NOTIFYDEV  global
   NR         352
   NTFY_ORDER 50-zhk4
   STATE      active
   TYPE       ZHK
   Readings:
     2014-05-29 09:07:07   autocontrol     autocontrol
     2014-05-29 09:46:12   state           active
     2014-05-29 09:46:02   zhkWwAlphaActualVal 0.375
     2014-05-29 09:46:12   zhkWwIstLastReading 42.375=1401349565
     2014-05-29 09:46:12   zhkWwPriorityOn 0
     2014-05-29 09:10:55   zhkWwSollTemp   32
Attributes:
   zhkBrennerFhemDev P3_BrennerStop
   zhkBrennerTaktMinOffSec 30
   zhkBrennerTaktMinOnSec 300
   zhkGlobalIncludeAussentemp 1
   zhkGlobalIncludeHolzofen 1
   zhkGlobalIncludeKessel 1
   zhkGlobalIncludeValvePositions 1
   zhkGlobalIncludeVorlauf 1
   zhkGlobalIncludeWarmwasser 1
   zhkINTpollInterval 10
   zhkWwAlphaDownAlarmDiffDeg 0.8
   zhkWwAlphaThreshold 1
   zhkWwAlphaUpAlarmDiffDeg 5
   zhkWwBoostFhemDev P2_WwBoost
   zhkWwBoostStartTemp 45
   zhkWwPumpFhemDev P7_WwStop
   zhkWwTaktMinOnSec 60
   zhkWwTempSensorDefaultOnFailure 70
   zhkWwTempSensorFhemDev 5_15_WarmWasser_EB6F98050000
   zhkWwTempSensorMaxAge 300
   zhkWwTempSensorReading temperature
Ich habe keine Ahnung, aber davon wenigstens ganz viel

epsrw1

hier noch ein plot dazu, die temp. geht noch weit herunter da die neue warmwassersteuerung derzeit nur einen dummy steuert. die kurve fallwinkel reagiert frühzeitig auf die entnahme gegen 07:28h.
(http://scellius.de/admin/tmp/2014-05-29_alpha.png)
(http://scellius.de/admin/tmp/2014-05-29_temp.png)
gruß, florian
Ich habe keine Ahnung, aber davon wenigstens ganz viel