Hallo zusammen,
wie im Betreff geschrieben kämpfe ich gerade mit einem seltsamen Problem.
Bei einem Freund haben wir ein DOIF dass je nach Verhältnis Soll zu Ist Temperatur Lüfter hoch oder runter regelt. das ganze dafür um bei normalen Heizkörpern mit niedrigeren Vorlauf Temperaturen heizen zu können.
Es gibt vier Zweige.
1. IST ist größer oder gleich als SOLL + 0.2
2. IST ist gleich SOLL
3. IST ist 0.1 kleiner als SOLL
4. IST ist 0.2 oder mehr unter SOLL
Das ist ja im Grunde nichts kompliziertes, ich habe es in vereinfachter Form in meinem Test-System:
([OG_HK_TV:Raum] >= ([SollTemp_OG:state] + 0.2)) (set OG_HK_TV Status cmd_1)
DOELSEIF ([OG_HK_TV:Raum] == [SollTemp_OG:state]) (set OG_HK_TV Status cmd_2)
DOELSEIF ([OG_HK_TV:Raum] == ([SollTemp_OG:state] - 0.1)) (set OG_HK_TV Status cmd_3)
DOELSEIF ([OG_HK_TV:Raum] <= ([SollTemp_OG:state] - 0.2)) (set OG_HK_TV Status cmd_4)
Das seltsame ist, CMD3 geht nicht wenn die IST Temperatur auf 21.6 steht. die anderen CMD gehen problemlos.
setze ich IST auf 21.7 gehen alle CMDs.
das ist doch ein einfacher Vergleich, warum machen diese 0.1 so einen Funktionsunterschied?
List mit IST von 21.7 / SOLL 21.8 cmd3 OK:
Internals:
CFGFN
DEF ([OG_HK_TV:Raum] >= ([SollTemp_OG:state] + 0.2)) (set OG_HK_TV Status cmd_1)
DOELSEIF ([OG_HK_TV:Raum] == [SollTemp_OG:state]) (set OG_HK_TV Status cmd_2)
DOELSEIF ([OG_HK_TV:Raum] == ([SollTemp_OG:state] - 0.1)) (set OG_HK_TV Status cmd_3)
DOELSEIF ([OG_HK_TV:Raum] <= ([SollTemp_OG:state] - 0.2)) (set OG_HK_TV Status cmd_4)
FUUID 655b251a-f33f-5ef8-19c1-682d3c6675824ca8
MODEL FHEM
NAME Booster_PWM_OG
NOTIFYDEV OG_HK_TV,SollTemp_OG,global
NR 277
NTFY_ORDER 50-Booster_PWM_OG
STATE cmd_3
TYPE DOIF
VERSION 27740 2023-07-10 09:31:11
eventCount 50
Helper:
DBLOG:
cmd:
logdb:
TIME 1700475308.65061
VALUE 2
cmd_event:
logdb:
TIME 1700475308.65061
VALUE SollTemp_OG
cmd_nr:
logdb:
TIME 1700475308.65061
VALUE 2
cmd_seqnr:
logdb:
TIME 1700472268.49407
VALUE 2
mode:
logdb:
TIME 1700473102.94635
VALUE enabled
state:
logdb:
TIME 1700475308.65061
VALUE cmd_2
READINGS:
2023-11-20 12:44:28 Device SollTemp_OG
2023-11-20 12:44:28 cmd 3
2023-11-20 12:44:28 cmd_event SollTemp_OG
2023-11-20 12:44:28 cmd_nr 3
2023-11-20 12:44:23 e_OG_HK_TV_Raum 21.7
2023-11-20 12:44:28 e_SollTemp_OG_state 21.8
2023-11-20 10:38:22 mode enabled
2023-11-20 12:44:28 state cmd_3
Regex:
accu:
bar:
barAvg:
collect:
cond:
OG_HK_TV:
0:
Raum ^OG_HK_TV$:^Raum:
1:
Raum ^OG_HK_TV$:^Raum:
2:
Raum ^OG_HK_TV$:^Raum:
3:
Raum ^OG_HK_TV$:^Raum:
SollTemp_OG:
0:
state ^SollTemp_OG$:^state:
1:
state ^SollTemp_OG$:^state:
2:
state ^SollTemp_OG$:^state:
3:
state ^SollTemp_OG$:^state:
attr:
cmdState:
wait:
waitdel:
condition:
0 ::ReadingValDoIf($hash,'OG_HK_TV','Raum') >= (::ReadingValDoIf($hash,'SollTemp_OG','state') + 0.2)
1 ::ReadingValDoIf($hash,'OG_HK_TV','Raum') == ::ReadingValDoIf($hash,'SollTemp_OG','state')
2 ::ReadingValDoIf($hash,'OG_HK_TV','Raum') == (::ReadingValDoIf($hash,'SollTemp_OG','state') - 0.1)
3 ::ReadingValDoIf($hash,'OG_HK_TV','Raum') <= (::ReadingValDoIf($hash,'SollTemp_OG','state') - 0.2)
do:
0:
0 set OG_HK_TV Status cmd_1
1:
0 set OG_HK_TV Status cmd_2
2:
0 set OG_HK_TV Status cmd_3
3:
0 set OG_HK_TV Status cmd_4
4:
helper:
NOTIFYDEV OG_HK_TV,SollTemp_OG,global
event 21.8
globalinit 1
last_timer 0
sleeptimer -1
timerdev SollTemp_OG
timerevent 21.8
triggerDev SollTemp_OG
DOIF_eventa:
cmd_nr: 3
cmd: 3
cmd_event: SollTemp_OG
cmd_3
DOIF_eventas:
cmd_nr: 3
cmd: 3
cmd_event: SollTemp_OG
state: cmd_3
timerevents:
21.8
timereventsState:
state: 21.8
triggerEvents:
21.8
triggerEventsState:
state: 21.8
internals:
readings:
all OG_HK_TV:Raum SollTemp_OG:state
trigger:
uiState:
uiTable:
Attributes:
DbLogExclude .*
do always
room 000 Heiz.HK.Booster
verbose 0
List mit IST von 21.6 / SOLL 21.7 cmd3 nicht OK:
Internals:
CFGFN
DEF ([OG_HK_TV:Raum] >= ([SollTemp_OG:state] + 0.2)) (set OG_HK_TV Status cmd_1)
DOELSEIF ([OG_HK_TV:Raum] == [SollTemp_OG:state]) (set OG_HK_TV Status cmd_2)
DOELSEIF ([OG_HK_TV:Raum] == ([SollTemp_OG:state] - 0.1)) (set OG_HK_TV Status cmd_3)
DOELSEIF ([OG_HK_TV:Raum] <= ([SollTemp_OG:state] - 0.2)) (set OG_HK_TV Status cmd_4)
FUUID 655b251a-f33f-5ef8-19c1-682d3c6675824ca8
MODEL FHEM
NAME Booster_PWM_OG
NOTIFYDEV OG_HK_TV,SollTemp_OG,global
NR 277
NTFY_ORDER 50-Booster_PWM_OG
STATE cmd_4
TYPE DOIF
VERSION 27740 2023-07-10 09:31:11
eventCount 48
Helper:
DBLOG:
cmd:
logdb:
TIME 1700475308.65061
VALUE 2
cmd_event:
logdb:
TIME 1700475308.65061
VALUE SollTemp_OG
cmd_nr:
logdb:
TIME 1700475308.65061
VALUE 2
cmd_seqnr:
logdb:
TIME 1700472268.49407
VALUE 2
mode:
logdb:
TIME 1700473102.94635
VALUE enabled
state:
logdb:
TIME 1700475308.65061
VALUE cmd_2
READINGS:
2023-11-20 11:28:24 Device SollTemp_OG
2023-11-20 11:28:05 cmd 4
2023-11-20 11:28:05 cmd_event OG_HK_TV
2023-11-20 11:28:05 cmd_nr 4
2023-11-20 11:28:05 e_OG_HK_TV_Raum 21.6
2023-11-20 11:28:24 e_SollTemp_OG_state 21.7
2023-11-20 10:38:22 mode enabled
2023-11-20 11:28:05 state cmd_4
Regex:
accu:
bar:
barAvg:
collect:
cond:
OG_HK_TV:
0:
Raum ^OG_HK_TV$:^Raum:
1:
Raum ^OG_HK_TV$:^Raum:
2:
Raum ^OG_HK_TV$:^Raum:
3:
Raum ^OG_HK_TV$:^Raum:
SollTemp_OG:
0:
state ^SollTemp_OG$:^state:
1:
state ^SollTemp_OG$:^state:
2:
state ^SollTemp_OG$:^state:
3:
state ^SollTemp_OG$:^state:
attr:
cmdState:
wait:
waitdel:
condition:
0 ::ReadingValDoIf($hash,'OG_HK_TV','Raum') >= (::ReadingValDoIf($hash,'SollTemp_OG','state') + 0.2)
1 ::ReadingValDoIf($hash,'OG_HK_TV','Raum') == ::ReadingValDoIf($hash,'SollTemp_OG','state')
2 ::ReadingValDoIf($hash,'OG_HK_TV','Raum') == (::ReadingValDoIf($hash,'SollTemp_OG','state') - 0.1)
3 ::ReadingValDoIf($hash,'OG_HK_TV','Raum') <= (::ReadingValDoIf($hash,'SollTemp_OG','state') - 0.2)
do:
0:
0 set OG_HK_TV Status cmd_1
1:
0 set OG_HK_TV Status cmd_2
2:
0 set OG_HK_TV Status cmd_3
3:
0 set OG_HK_TV Status cmd_4
4:
helper:
NOTIFYDEV OG_HK_TV,SollTemp_OG,global
event 21.7
globalinit 1
last_timer 0
sleeptimer -1
timerdev OG_HK_TV
timerevent Raum: 21.6
triggerDev SollTemp_OG
timerevents:
Raum: 21.6
Status cmd_4
timereventsState:
Raum: 21.6
Status cmd_4
triggerEvents:
21.7
triggerEventsState:
state: 21.7
internals:
readings:
all OG_HK_TV:Raum SollTemp_OG:state
trigger:
uiState:
uiTable:
Attributes:
DbLogExclude .*
do always
room 000 Heiz.HK.Booster
verbose 0
zum testen habe ich wie erwähnt das DOIF vereinfacht und im meinem System nachgestellt. anstelle der ESPEasy Lüfter setze ich ein Reading im Dummy und anstelle des echten Temperaturfühlers setze ich die Temperatur ebenfalls im Dummy.
zum nachstellen kann der Dummy "OG_HK_TV", Reading "Raum" auf 21.7 gesetzt werden.
dannach einfach den Dummy "SollTemp_OG" nacheinander auf 21.7 (cmd2), 21.8 (cmd3) und 21.9 (cmd4) gesetzt werden. alles funktioniert.
Um den Fehler nachzustellen dann den Dummy "OG_HK_TV", Reading "Raum" auf 21.6 setzten.
dannach einfach den Dummy "SollTemp_OG" nacheinander auf 21.6, 21.7 und 21.8 setzen.
Er geht nicht im CMD3, er bleibt bei 21.7 in CMD2 stehen. CMD4 bei 21.8 dagegen geht wieder.
Ich kann es mir nicht erklären...
Alles zum nachstellen hier.
Dummy1:
defmod SollTemp_OG dummy
[font=Verdana, Arial, Helvetica, sans-serif]attr SollTemp_OG stateFormat state °C[/font]
Dummy2:
defmod OG_HK_TV dummy
[font=Verdana, Arial, Helvetica, sans-serif]attr OG_HK_TV readingList Raum[/font]
[font=Verdana, Arial, Helvetica, sans-serif]attr OG_HK_TV setList Raum[/font]
attr OG_HK_TV stateFormat Raum °C
DOIF:
defmod Booster_PWM_OG DOIF ([OG_HK_TV:Raum] >= ([SollTemp_OG:state] + 0.2)) (set OG_HK_TV Status cmd_1)\
DOELSEIF ([OG_HK_TV:Raum] == [SollTemp_OG:state]) (set OG_HK_TV Status cmd_2)\
DOELSEIF ([OG_HK_TV:Raum] == ([SollTemp_OG:state] - 0.1)) (set OG_HK_TV Status cmd_3)\
DOELSEIF ([OG_HK_TV:Raum] <= ([SollTemp_OG:state] - 0.2)) (set OG_HK_TV Status cmd_4)
[font=Verdana, Arial, Helvetica, sans-serif]attr Booster_PWM_OG do always[/font]
wäre schön wenn sich das jemand anschauen könnte. Ich kann mir keinen Reim daraus machen...
Habe es gerade durchgespielt und kann es nachvollziehen. Bei mir geht er auch bei OG_HK_TV Raum == 21.8 nicht durch cmd_3 durch. Schuss in's blaue: Float/Rundungsproblem? (siehe z.B. https://stackoverflow.com/questions/21587663/perl-how-to-compare-floating-numbers (https://stackoverflow.com/questions/21587663/perl-how-to-compare-floating-numbers))
Ja, uns ist es "vor Ort" bei 21.6 / 21.7 aufgefallen.
hatte auch paar Tage gedauert da drauf zu kommen. da rechnest ja nicht damit.
es gibt bestimmt noch andere Kombinationen die gehen bzw nicht gehen.
Auch wenn ich es nicht erklären kann war ich gestern erstmal from die Ursache gefunden zu haben. nach langer Suche nach dem Phantom. :-)
{if (21.6 == ( 21.7 - 0.1)) {1} else {0}}
Das Problem kann man auch direkt in Perl (Kommandozeile) nachvollziehen
Ich würde statt == mit <= arbeiten.
Zitat von: Damian am 20 November 2023, 20:23:09{if (21.6 == ( 21.7 - 0.1)) {1} else {0}}
Das Problem kann man auch direkt in Perl (Kommandozeile) nachvollziehen
Ich würde statt == mit <= arbeiten.
D. H. == sollte generell nicht zum Zahlenwerte vergleichen verwendet werden?
Und warum macht Perl das "falsch"?
Zitat von: Frank_Huber am 20 November 2023, 20:33:24D. H. == sollte generell nicht zum Zahlenwerte vergleichen verwendet werden?
Und warum macht Perl das "falsch"?
Da musst du die Perlautoren fragen. Das gehört leider zu den Unzulänglichkeiten dieser Programmiersprache und ist sehr ärgerlich.
Intern werden die Zahlen anders dargestellt und das führt zu Rundungsungenauigkeiten bei Berechnungen.
{if (21.6 == round(( 21.7 - 0.1),1)) {1} else {0}}
funktioniert dagegen korrekt.
Zitat von: Damian am 20 November 2023, 21:06:23Zitat von: Frank_Huber am 20 November 2023, 20:33:24D. H. == sollte generell nicht zum Zahlenwerte vergleichen verwendet werden?
Und warum macht Perl das "falsch"?
Da musst du die Perlautoren fragen. Das gehört leider zu den Unzulänglichkeiten dieser Programmiersprache und ist sehr ärgerlich.
Intern werden die Zahlen anders dargestellt und das führt zu Rundungsungenauigkeiten bei Berechnungen.
{if (21.6 == round(( 21.7 - 0.1),1)) {1} else {0}}
funktioniert dagegen korrekt.
Danke Damian. Dann schau ich mal wie wir das lösen. Denke aber es wird auf >= and <= herauslaufen. Ist zwar augenscheinlich Overkill für nen 0.1 Bereich, aber so ist es dann halt. 😉
Danke nochmal und nen schönen Abend!
leider funktioniert auch
{if (21.6 <= ( 21.7- 0.1)) {1} else {0}}
nicht richtig, da die Differenz intern wahrscheinlich sowas 21,5999999999999999 ist
Sowas ist wichtig zu wissen. Ich weiß zwar nicht, ob ich Probleme aufgrund dieses Verhaltens habe, aber diese Info bei Bedarf im Hinterkopf zu haben schadet nicht.
Könnte man die Probleme der Zahlendarstellung umgehen, wenn man die Werte vorab mit 10 multipliziert und dann Integer arbeitet?
Also 217 - 1 ::)
Gruß Ralf
Zitat von: RalfRog am 21 November 2023, 08:53:07Könnte man die Probleme der Zahlendarstellung umgehen, wenn man die Werte vorab mit 10 multipliziert und dann Integer arbeitet?
Also 217 - 1
Danke Ralf, Diese Idee war genau richtig. :-)
in den Dummys jeweils UserReadings erstellt die x10 rechnen. im DOIF dann auch auf ganze Zahlen umgestellt und so läuft es wie es soll. :-)
Super, das wäre auch meine Idee gewesen und so arbeite ich oft mit Temperaturen: multiplizieren so dass Ganzzahlen entstehen (i.d.R. x10), gegebenfalls erzwungen zu integer konvertieren (z.B. auf Arduinos) und ich umgehe damit die ganze Float-Problematik. Also:
if ( (int)(Temp1*10) == (int)(Temp2*10) )
Edit: bei Temperaturregelungen kann das PID20 Modul manchmal auch sehr hilfreich sein als Alternative!