Ich lese mit sensor.read() den aktuellen Wert vom Lasersensor aus, dividiere durch 10 auf cm und schreibe den Wert in sens_read_neu.
laser_minmax ist der Toleranzwert: +/- 5cm.
Wenn der aktuelle Wert sens_read_neu außerhalb vom alten Wert (sens_read) +/- 5cm (laser_minmax) liegt, ist die Bedingung wahr, write_laser wird auf true gesetzt und ein Datensatz wird geschrieben. Am Ende vom Code wird dann sens_read mit sens_read_neu gleichgesetzt.
Ich habe schon etliche Varianten getestet und bin an dem Punkt, wo ich schon so verwirrt bin, dass ich überhaupt nicht mehr durchblicke. Es wäre sehr hilfreich, wenn ihr die Formel mal durchchecken könntet.
Danke schon mal im voraus.
Kann es sein, das Du + und - vertauscht hast?
Und dann das ganze als ODER.
Dann muss eine Bedingung (nicht) stimmen und damit wird das übersichtlicher.
Im Übrigen ist Deine
ausserhalb der Prüfung, was zu eigenartigen Effekten führt.
Meine "five cents":
Deine Variablen sind alle int (nicht float). OK, du dividierst mit 10: dabei verlierst Du ein ganzes Digit (ist ja int, nicht float), also alles ist schon gerunded auf +/-10. Deine Toleranze mit 5 wuerde also 50 cm draus machen (vielleicht viel zu gross als was Du willst). Das Dividieren mit 10 gibt Dir schon einen Tolleranzbereich mit +/-9 (da brauchst Du die 5 gar nicht mehr, das Runden kommt schon mit dem Dividieren).
Kannst doch "Fix Floating" machen:
Lasse alles in mm (nicht mit 10 teilen). Nur wissen, dass jetzt alles in mm, also in Bezug auf cm bleibt alles im Bereich wie "mal 10" (alle Werte sind um *10 erhoeht).
Nun passt vielleicht Dein laser_minmax mit 5 besser dazu (ist ja offensichtlich in mm und nicht in cm).
Das mit dem ABS und nur minus ist korrekt, denke ich:
Du vergleichst doch, ob der Betrag groesser ist: das ABS wandelt es nur in einen positiven Betrag um (wenn es negativ ist). Minus reicht aus fuer die untere Grenze, die positive ist doch schon erfuellt, sobald Dein sens_read_neu groesser wird, wenn positiv.
Ansonsten kannst Du auch testen, ob (abs(sens_read_neu - sens_read) < laser_minmax) ODER (abs(sens_read_neu + sens_read) > laser_minmax) wird: Das baut eine Hysteresis ein: im Zwischenbereich wuerdest Du gar nichts machen (nicht den Zustand aendern). Das ist dann wie ein Schmitt-Trigger: Level minus untere Tolleranz oder Level plus obere Tolleranz als Kriterium.
(abs(sens_read_neu - sens_read) > laser_minmax) scheint mir schon richtig, wenn der Schaltpunkt bei "genau" send_read_neu liegen soll, aber mit einem +/- Tolerranzbereich.
Das gibt Dir dann den Rest der int-Division, e.g. -3 bzw. 3, oder -7 bzw. 7, das Du nun mit dem "maximalen Error" vergleichst (angenommen die 5 meinen mm und alles ist in mm).
Das macht auch "genau herum" bei sens_read_neu aber mit +/-5 for Tolleranz.
Hinweis: beim Konvertieren aller Werte von mm in cm, mit diesem "divide by 10", bedenken, dass Du ja schon rundest und die Aufloesung verlierst. Besser, immer in dem genaueren Wertebereich (hier mm) bleiben (wenn Du alles in km unwandeln wuerdest, waeren alle Werte immer 0 und Deine Tolleranz 999 meter )
"Fix Point" koennte es sogar genauer machen: wenn Du alles mit 10 multiplizierst und im Wertebereich als "basierend auf" 0.1mm behandelts, dann koennte Deine 5 als Tolleranz auch +/-0.5mm bedeuten.
Ich weiß deine Erklärungen wirklich sehr zu schätzen, aber ich muss gestehen, dass ich nur Bahnhof verstehe.
Wenn sich der Abstand vom Objekt von (z.B.) 192cm auf 198cm ändert (+6cm), dann ist die Bedingung wahr, weil der Toleranzwert um 1cm überschritten wurde. Der alte Wert sens_read wird dann mit dem Neuen sens_read_neu überschrieben.
Das Ganze soll dazu dienen, dass nicht bei jeder Zentimeter-Änderung ein Datensatz geschrieben wird.
OK, also alles in cm. Dann ist Dein "divide by 10" fuer "alles in cm" und die 5 meint cm.
Dann sollte doch das von Tommy56 genannte if (abs(sens_read_neu - sens_read) > laser_minmax) genau das tuen.
Sind denn Deine cm-Werte wirklich auch negative?
Wenn alles von 0cm (z.B. ein Anschlag unten) und alles ist positive, dann brauchst Du auch das ABS nicht (aber ich wuerde dann eher unsigned int als Typ verwenden).
Meine Erklaerungen waren sehr detailliert - sorry.
Um das ganze in "logische Gedankenschritte" zu zerlegen, eine Liste von Fragen, die vor dem Kodieren beantworten:
sind die Werte immer nur positive - oder koennen die auch neagtiv sein?
in welchem Werte-Bereich kommen die Werte - z.B. als mm?
ist es OK, diese in cm, mit divide by 10, umzuwandeln und dabei schon eine Rundung, einen
Verlust an Genauigkeit "in Kauf zu nehmen"?
waere das "divide by 10" nicht schon eine Rundung? Brauche ich dann noch zusaetzlich die +/- 5 cm?
wenn ich nicht separat fuer negative oder positive Werte behandeln will: ABS ist das Hilfsmittel alles im positiven Bereich zu vergleichen
will ich um den "genauen" Wert herum ein +/- haben (um den Fehlerbereich "auszublenden") oder will ich zwei Schwellwerte haben? (wie ein Schmitt-Trigger: einen unteren Bereich, einen Mittel-Bereich wo gar nichts passiert, einen oberen Bereich)
das waere zu bedenken, wenn denn die Werte immer "hindurch fahren" sollten, von unten nach oben, von oben nach unten: eine Hystersis. Ansonsten kann es passieren, dass Dein Wert genau an der Fehler-Tolleranz-Grenze immer hin und schwer schwankt.
Bedenken von meiner Seite:
wenn Du das mit dem +/- Error immer mit dem letzten Wert machst, den lezten mit dem aktuellen ueberschreibst, dann ziehst Du diese Fehlertolleranz immer mit: die wandert mit "nach oben". Nehmen wir an, die erreichst das Maximum, das Ende, wie kommst Du dann wieder runter, wenn die Bewegung nach unten langsam ist?
Wenn Du immer diese +/-5 "mit ziehst", und zwischen jedem Schritt von letztem zu neuem weniger als 5 liegen - dann bekommst Du keinen Trigger mehr.
Ich denke: die Groesse des erlaubten Fehlers (hier die +/-5) haengt nicht nur von einer Mechanik ab, oder wie oft Du Werte schreiben willst (nicht immer, nur in Abstaenden) - sondern auch von der (minimalen) Geschwindgkeit der Aenderungen: wenn das Ding ganz langsam so vor sich hin kraucht und Du immer den gleichen Vergleich machst, ob ausserhalb der Tolleranz - dann machst Du vielleicht irgendwann mal gar nichts mehr.
BTW: warum nicht alle 1..5 sec. einen Log-Entry schreiben?
OK, dann bekommst Du zwar auch alle nasenlang den gleichen Wert (wenn sich nichts bewegt hat), oder Du kannst auch keine langsamen Aenderungen sehen...
Ich denken, dieser Tolleranz-Fehler sollte "nur" auf der Ungenauigkeit der Mechanik notwendig sein (oder wenn Du float als Werte benutzen wuerdest, um die "Ungenauigkeiten" bei float "zu handeln".
Zu entscheiden, ob Du eine Bewegung erkannt hast, um einen Log-Entry zu schreiben wird bei kleinen Aenderungen zu "nichts geschrieben" fuehren. Und dennoch ist Dein "Ding" irgendwo am Anschlag, ohne dass Du irgendwas als geschrieben siehst.
irgendwas && true == irgendwas
Es könnte sonst ja jemand glauben, was Du schreibst, deshalb muss ich es korrigieren.
Aber ansonsten mach, was Du willst, wenn Du meinst es besser zu wissen.
Die habe ich in #2 gepostet. Wenn Du sie nicht verstehst, ist das Dein Problem.
Wenn Du das Geben der Lösung und Hinweise auf Fehler als "wichtig machen" siehst, bin ich aus Deinen Themen raus.
Man, was fuer ein Ton! Ich bin im deutschen und im englischen Forum unterwegs, aber der Ton ist im deutschen Forum um so viel schlimmer. Warum seid ihr nur so verbissen (und hart, unfreundlich zu einander)?
Was Tommy56 gepostet hat als: if (abs(sens_read_neu - sens_read) > laser_minmax) scheint total korrekt fuer mich. Wenn es nicht funktioniert hat, dann war es etwas anderes. Ihn nun "raus zu schmeissen" wenn nichts falsch war, zudem nicht mal als Moderator - was soll das?
Um das nochmal genauer zu beleuchten:
Wenn Du einen int value hast (positiv UND negativ) und Du will das mit einem Tolleranz-Bereich entscheiden: dann ist MINUS die Tolleranz nach ABS() richtig!
Damit ist Dein Wert fuer IF "true", wenn die untere Grenze, als Wert MINUS Tolleranz, erfuellt ist.
Die obere Grenze interessiert hier nicht mehr, da ja die untere Grenze schon "true" liefert. Dann muss auch Wert PLUS Tolleranz ebenso war sein, was ja immer erfuellt ist, wenn Wert MINUS Tolleranz bereits wahr war (also ein viel kleinerer Wert bereits "umschalten" wuerde).
Und warum man ABS() nicht mit dem Ergebnis einer Funktion nutzen kann?
Das Statement bei Arduino ist so ein Nonsense: die meinen: wenn Du ABS(a++) machst, kann das "falsch" sein, da ja a um eins erhoeht wird, danach. So, ABS(a) sollte a sein, wenn es positiv ist, aber ABS(a++) liefert "ungleich" a, weil ja a nun a = a + 1 ist.
Die meinen "nur": normalerweise ist ABS(a) = a , wenn a positiv ist. Aber ABS(a++) is ungleich a. Darauf sollst "Du" aufpassen (und nicht, ob Du eine Funktion in ABS() benutzt).
Sie wollen auch nicht dafür garantieren, dass beim Aufruf von ABS(f(x)) die Funktion f(x) nur einmal aufgerufen wird. #define kann böse sein. Funktionen mit Nebenwirkungen auch.
"Das Statement bei Arduino" ist kein Nonsense, aber auch Mist, weil nicht Arduino-gerecht, wie man hier sieht.
ABS(a++) könnte auch a um zwei erhöhen, und zwischendurch Unsinn machen
Und/oder je nach Compileroptimierungseinstellungen unterschiedliche Ergebnisse liefern.
Wie oft wird (x) ausgeführt bei: #define ABS(x) ((x)>0)?(x):-(x))
Oh, das ist wahr. Guter Punkt. Wenn ABS() wirklich so ein Macro ist, dann sind x++ und auch Funktionsaufrufe zwar moeglich, aber mit Seiteneffekten.
Vielen Dank.