Hallo zusammen,
ich verwende einen Ultraschallsensor um den Füllstand der Zisterne zu ermitteln. Hierbei wird die Entfernung zum Wasser gemessen und entsprechend in einem Userreading umgerechnet (Wasserstandshöhe sowie Liter). Soweit so gut, ist die Zisterne allerdings voll und der Abstand zum Sensor beträgt somit weniger als ~20cm, dann kriege ich falsche Werte (Sensorbedingt).
Meine Idee war, jeden neuen Wert (Distance) gegen den vorherigen Wert zu prüfen, weicht er um weniger als 10% ab, dann nehme den neuen Wert, ansonsten den Alten.
Ich hab es jetzt in etlichen Konstellationen versucht, ich kriege es einfach nicht hin... Weiß jemand wo mein Denkfehler liegt?
Bisher habe ich alle neuen Werte in das Userattrb level und liter geschrieben:
level {
my $lastlevel=ReadingsNum("ESPEasy_ESP_Zisterne_DISTANCE","level",0);
my $level=150-((ReadingsNum("ESPEasy_ESP_Zisterne_DISTANCE","distance",0))-30);
return $level unless($level >= 160);
return $lastlevel },
liter {
my $level=ReadingsNum("ESPEasy_ESP_Zisterne_DISTANCE","level",0);
my $liter=47.47*($level);
use Math::Round qw/round/;
return $liter= Math::Round::nearest('10',$liter) }
Oben genannte Idee habe ich so versucht umzusetzen:
level {
my $lastlevel=ReadingsNum("ESPEasy_ESP_Zisterne_DISTANCE","lastlevel",0);
my $level=150-((ReadingsNum("ESPEasy_ESP_Zisterne_DISTANCE","distance",0))-30);
return $level unless($level <= $lastlevel*1.1);
return $lastlevel },
liter {
my $level=ReadingsNum("ESPEasy_ESP_Zisterne_DISTANCE","level",0);
my $liter=47.47*($level);
use Math::Round qw/round/;
return $liter= Math::Round::nearest('10',$liter) },
lastlevel {
my $level=ReadingsNum("ESPEasy_ESP_Zisterne_DISTANCE","level",0);
my $lastlevel=ReadingsNum("ESPEasy_ESP_Zisterne_DISTANCE","lastlevel",0);
return $level unless($level <= $lastlevel*1.1);
return $lastlevel }
Ich sehe nichts wo du irgendwas in Attribute schreibst, auch nicht wo du in Readings schreibst (denn lastLevel ist ja ein Reading laut deinem Bild)...
Es gibt das Attribut oldReadings:
Zitat von: commandref
oldreadings
Dieses Attribut enthält eine durch Kommata getrennte Liste von Readings. regex sind erlaubt. Für jedes Reading aus der Liste speichert FHEM intern den vorherigen Wert wenn sich das Reading ändert. Zum Zugriff auf die Werte gibt es die OldReadings.* Routinen.
Dadurch hast du "automatisch" den letzten Readingswert.
Ich habe zuhause auch Code, der das Attribut nutzt.
Vorher wird der ausgelesen (ReadingsVal("Devicename", "oldreading", "Ersatzwert") / evtl. besser ReadingsNum), mit dem aktuellen verglichen und dann eben der alte oder neue genommen.
Nicht als userreadings sondern in einer Sub in myUtils, sollte aber egal sein...
Kann ich mal posten, wenn ich zuhause bin...
Und: poste doch mal ein list von dem Device.
In etwa würde es so gehen (userreadings):
{OldReadingsNum("$name","ReadingsName", 0) > ReadingsNum("name","Readingsname",0) ? return OldReadingsNum("$name","ReadingsName",0) : return ReadingsNum("$name","Readingsname",0)}
ungetestet und aus dem Kopf. EDIT: eieiei, mein Kopf ;)
Ob es in userreadings "$name" gibt weiß ich nicht, könnte auch "$NAME" oder "$DEVICE" etc. sein.
Bzw. zum Test einfach mal den Devicenamen direkt angeben ;)
Gruß, Joachim
@Joachim Ich greife mal etwas korrigierend ein - die Idee ist gut!
Habe es aber auch nicht getestet, kann sein ich habe mit der "Bandbreite" noch einen Denkfehler :)
Die Bandbreite ist jetzt auch nicht 10 % sondern einfach 10 :-\
{(OldReadingsNum($name,"distance", 0) > (ReadingsNum($name,"distance",0)+10) or OldReadingsNum($name,"distance", 0) < (ReadingsNum($name,"distance",0)-10)) ? OldReadingsNum($name,"distance",0) : ReadingsNum($name,"distance",0)}
https://fhem.de/commandref_DE.html#perl
Gruß Otto
Hi Otto,
Ups!
Stimmt, war ja anders die Abfrage vom alten Reading ;)
Ich korrigiere dann auch mal nach... ;)
Danke, Joachim
Vielen Dank für eure Ideen :)
Um die Oldreadings nutzen zu können, muss der Code dann in die MyUtils oder kann der direkt im userattr genutzt werden?
Bei den Readings aus dem Screen wie level, liter, lastlevel handelt es sich tatsächlich um die Userreadings die ich dort eingetrange habe.
Der Code war für Deine userReadings - von userattr habe ich keine Ahnung. Und ich dachte es war bei Dir nur ein Falschversteher Textverdreher.
Du hast doch ein attr Devicename userReadings - oder?
Sorry, dann habe ich das glaube ich falsch verstanden. So siehts aus aktuell:
Poste doch bitte ein komplettes list...
...in code-Tags (das '#' im "Menü)...
...keine Screenshots...
list Devicename
Gruß, Joachim
Vielleicht noch zur Erklärung der Idee, dies ist vielleicht zu kurz gekommen :)
mit attr devicename oldreadings kannst Du die oldreadings aktivieren, d.h. das Gerät hebt dann immer einen Satz alte Readings auf. Damit kannst Du den Vergleich zwischen altem und aktuellen Wert machen und brauchst Dich nicht um die alten Werte kümmern.
Der Vorschlag / Konstrukt von Joachim ist ein Vergleich mit Rückgabe:
{(Bedingung) ? Rückgabe Wert für Ergebnis wahr : Rückgabe Wert für Ergebnis falsch }
Praktisches Beispiel zum Test und Spiel in der FHEM Kommandozeile
{3>2 ? "wahr":"falsch"}
Gruß Otto
Hi,
ich würde hier eher am Ultraschallsensor direkt ansetzen. Der soll vernünftige Werte liefern anstatt das FHEM hier herumdoktern muss ;)
Gegebenenfalls kannst du in meinem ESP8266 Code etwas abgucken (in sensor.cpp) :
https://github.com/tobiasfaust/ESP8266_PumpControl
Zitat von: Tobias am 12 März 2020, 09:31:29
Der soll vernünftige Werte liefern anstatt das FHEM hier herumdoktern muss ;)
Wenn die Hardware es einfach nicht kann wo ist da der Unterschied ob FHEM doktort oder irgendeine lib ?
Mein US100 will bei vollem Öltank auch nicht so recht, ist der Pegel mal ein paar Zentimeter gesunken passen die Werte perfekt.
D.h. wenn man schon die Ursache bekämpfen will statt der Symptome, dann hilft es IMHO nur den US mit z.b. einem Rohr mehr Abstand zur Oberfläche zu verschaffen.
Da hast du Recht. Verlängerung via Rohr oder ein anderer Ultraschallsensor. Zb. der HCS-04 hat nur wenige cm als Mindestmass
Hallo zusammen,
da habe ich wieder zwei neue Dinge gelernt, zum einen Oldreadings und zum anderen der Vergleich! Ich danke euch!
Den Sensor kann ich leider nicht weiter justieren, aufgrund des Schachtes. Bis zu einem Füllgrad von 100% funktioniert alles sauber, ab 101% (wenn das Wasser nicht schnell genug über den Ablauf versickert), beträgt der Abstand weniger als 20cm und der Sensor schwankt dann extrem stark bis er wieder eine Distanz über 20cm misst (100%)
Aktuell scheint es so zu funktionieren:
level {
my $level=150-((ReadingsNum("ESPEasy_ESP_Zisterne_DISTANCE","distance",0))-30);
return (OldReadingsNum("ESPEasy_ESP_Zisterne_DISTANCE","distance", 0) > (ReadingsNum("ESPEasy_ESP_Zisterne_DISTANCE","distance",0)+10) or OldReadingsNum("ESPEasy_ESP_Zisterne_DISTANCE","distance", 0) < (ReadingsNum("ESPEasy_ESP_Zisterne_DISTANCE","distance",0)-10)) ? OldReadingsNum("ESPEasy_ESP_Zisterne_DISTANCE","distance",0) : ReadingsNum("ESPEasy_ESP_Zisterne_DISTANCE","distance",0)},
liter {
my $level=ReadingsNum("ESPEasy_ESP_Zisterne_DISTANCE","level",0);
my $liter=47.47*($level);
use Math::Round qw/round/;
return $liter= Math::Round::nearest('10',$liter) },
lastdistance {
my $lastdistance=OldReadingsNum("ESPEasy_ESP_Zisterne_DISTANCE","distance",0);
return $lastdistance },
Jetzt kommt das große ABER ;) Ich vermute, dass der Sensor bei aufeinanderfolgenden falschen Werten, die in den 10% Bereich fallen, den falschen Wert übernehmen würde... Oder denke ich da zu kompliziert? Eine andere Idee wäre dann einen Durchschnitt der letzten 5 Messungen zu nehmen und davon 10%?
Anderer Ansatz (falls wirklich nicht einfach ein anderer US-Sensor geht(!)): Bau noch einen billigen Schwimmerschalter dran ;) .
Ist der oben, ist voll, ist der unten, darf der US-Sensor Werte liefern. Ist zwar in FHEM (oder gerne auch der firmware...) etwas schwieriger abzubilden, aber dafür weniger "schätzig".
(Nachtrag: bei userReading sollte man "präventiv" auch immer einen Trigger definieren, auch wenn das Device hier scheinbar nur einen "echten" Readingwert hat, der die userReadings aktualisiert).