[C++] IF-Anweisung verstehen

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Hi Leute,

    Ich, C++ ca.1%.

    In meinem Code werden die Werte von 3 Temperatursensoren DS18B20 abgefagt.

    Da die im selben Raum sind, möchte ich die Bauelemente- Differenzen ausgleichen.

    Sensor 0 soll der Richtwert sein.

    Erstmal der laufende Code (abgeleitet aus Beisp. im Netz):

    Zwischen float tempC... und dataMessage... (//xyz) möchte ich (für die Sensoren 1 und 2) IF- Anweisungen setzen, etwa so:

    Code
    if (i == 1){
        tempC = tempC -0.4)
        }
    if (i == 2){
        tempC = tempC -0.2)
    }

    So daß ich die Sensoren 1 und 2 an den Sensor 0 händisch anpassen kann. Nicht schick, aber so daß ich es kapiere.

    -ähem, "==" und "=" ist doch so ok?

    Mein Problem ist, daß der Code unter den IF- Anweisungen nicht mehr ausgeführt wird, ab "dataMessage =...".

    Muß ich alle unteren Anweisungen in jede IF- Abfrage extra setzen (bzw. eine Unterroutine daraus machen und jedesmal anspringen)?

    Dann müßte ich ja auch für Sensor 0 was tun, der ja sonst garnicht beachtet wird?

    Sorry für die Laienfrage. Zu IF erschlägt einen das Netz, aber verschachtelte Anweisungen... gibt es ja vielleicht nicht in C.

    -übrigens, mit IF...ELSE ist das genauso.

    Hans

  • Hallo Hans,

    Du machst es Dir viel zu kompliziert.

    Du liest die ID des Sensor aus ==> gut.

    Du liest die Temperatur zu jeder Sensor ID aus ==> gut

    Du brauchst doch bloß für jede Sensor-ID einen Offset zu definieren und direkt bei der Messung addieren / subtrahieren. ==> Lässt sich recherchieren.

    Da spart Du Dir die ganzen Zeilen mit INDEX-basierten Abfragen. Wenn da mal ein Sensor verloren geht, dann ziehst Du den Korrekturwert vom falschen Sensor ab...


    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

  • hyle:

    Klammer vergessen, ok. Hatte ich nur fix aus'm Kopf hingeschrieben.

    Sieht jetzt so aus:

    Code
    if (i == 1){
    //-- Wert per Hand
    tempC = (tempC + 0.81);
    }
    if (i == 2){
    //-- Wert per Hand
    tempC = (tempC + 0.62);
    }

    ...und läuft!!

    Das heißt, der weitere Code wird inzwischen ausgeführt, was meine eigentliche Frage beantwortet.

    Andreas:

    Meinst Du mit Sensor-ID die Device-Adresse?

    Du hast -dann- zwar recht mit der Sensor-ID, aber wenn ein Sensor ausfällt muß ich eh was unternehmen. Man kann durch Deinen Vorschlag bei Ausfall des Sensors 0 evtl. wieder auf Grundwerte umschalten.

    Aber: das bläst mir den Code zu sehr auf, und das bei Sensoren die eine Ungenauigkeit von immerhin +/-0,5°C haben. Das ist ein Grad!

    Jetzt wo das mit dem ausgleichen läuft habe ich sehen müssen, daß die 1° Abweichungen im laufenden Betrieb auftreten (also keine generelle Konstruktionsabweichung sind). Daher hilft mein Offset nicht komplett. Immerhin komme ich auf Unterschiede von ca. 0,3°C (Sensoren dicht zusammen auf'm Steckbrett).

    Zitat

    Du brauchst doch bloß für jede Sensor-ID einen Offset zu definieren und direkt bei der Messung addieren / subtrahieren. ==> Lässt sich recherchieren.


    float tempC = sensors.getTempC(tempDeviceAddress);

    ist doch die Messung??

    dann kommt ja schon das IF.

    Müßte nur nach Deinem Vorschlag

    IF (DeviceAddress = "28863975D0013CD8"...

    heißen.

    Naja. Freu. Es läuft. Mein anderes Problem, die 2 Stellen hinter dem Komma (23.47°C) wegbekommen, löse ich bei der Datenauswertung (Excel). Ha! Geben die Sensoren hundertstel Grad aus bei 1° Schwankung. Spielzeug!

    Ich mache mir jetzt mal Gedanken wie ein Sensorausfall bemerkt werden kann. Immerhim wollte ich die Sensorzahl variabel haben (beim Start).

    Danke Euch beiden:-)

    Hans

  • Hallo Hans,

    für ein Projekt habe ich mal mehrere Dutzend DS18B20 mit einem Blockkalibrator auf ihre Genauigkeit überprüft.

    Ja, die messen alle unterschiedliche Temperaturen, auch wenn sie einer auf 100 mK identischen Umgebung ausgesetzt sind. Ich hatte auch einige Sensoren, die 1,5 K abweichend gemessen haben.

    Wenn ich aber jedem Sensor seinen individuellen Offset zugeordnet habe, dann habe ich die Auflösung von 64 mK auch als Messungenauigkeit erhalten. Man kann mit den Teilen also tatsächlich genau und reproduzierbar messen, wenn man vorher einen gewissen Aufwand getrieben hat.

    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

  • Mir ist dies aufgefallen:

    1) Mit C++ hat der Quellcode nichts zu tun, das ist reiner C-Code (ist aber eine Randbemerkung).

    2) Es gibt keine if-Anweisungen sondern nur if-Abfragen (ist auch eine Randbemerkung).

    3) Ich verstehe nicht, wie der Quellcode überhaupt fehlerfrei kompiliert werden kann, da passt etwas mit der Variable dataMessage nicht. Von welchem Typ soll diese Variable denn sein? Ich wundere mich deswegen, weil die Variable mit einer Summe aus einem Integer und char-array belegt wird und das kann nicht funktionieren.

    4) Die Lösung zu dem Problem mit der verschachtelten if-Abfrage ist eine switch-Anweisung.

    5) Tipp #1 zu if-Abfragen: vermeide Abfragen wie if (sensors.getAddress(tempDeviceAddress, i)). Diese Abfrage ist zwar syntaktisch einwandfrei, vor allem für Einsteiger ist es aber besser, auf explizite Werte abzufragen. Also etwa if (0 == (sensors.getAddress(tempDeviceAddress, i)).

    6) Tipp #2 zu if-Abfragen: verwende die sogenannte Yoda-Schreibweise, benannt nach dem kleinem Knirps aus Star Wars. Yoda hat ja beim Sprechen die Reihenfolge der Wörter umgedreht und daraus leitet sich die Yoda-Schreibweise ab. Konkret bedeutet das also, dass gerade bei Vergleichen mit Konstanten die Konstante vor dem '==' steht und nicht danach. Die Yoda-Schreibweise hat den Vorteil, dass ein versehentliches '=' beim Kompilieren sofort auf einen Fehler läuft.

  • für ein Projekt habe ich mal mehrere Dutzend DS18B20 mit einem Blockkalibrator auf ihre Genauigkeit überprüft.

    Also Pärchen ausgesucht, so etwa. Na soviele hab ich nicht aber hab ja mit meinen Korrekturen doch etwas erreicht. So 0,3° (oder K) ist doch schon was. Ich möchte nur 3 Etagen in meinem Kühlschrank messen, das ist schon alles.

    Mir ist dies aufgefallen:

    Ehm...

    1) aha, 2) richtig.

    3) er läuft gerade. Such...

    Code
    String dataMessage;

    Das ist eine globale Variable die in die oben gepostete Routine kommt. Dann werden hier die Daten reingeladen und das Ganze wird ein MQTT-Payload.

    Ah, woanders steht dann das:

    Code
    dataMessage = String(dayStamp) + "," +
                  String(timeStamp) +
                  dataMessage + "\r\n";

    Wie es mit den einzelnen Datentypen funktioniert kann ich Dir nicht beantworten, nur daß es nach vielen Versuchen jetzt klappt. Die Daten landen beim Empfänger auf einer SD-Karte. Die dort abzugreifen ohne die Karte auszubauen ist ein Plan für später. Interessant finde ich auch daß der Code für eine fast beliebige Zahl Sensoren paßt. Ich glaube die Payload-Größe (128bytes?) ist die erste Grenze.

    4) Das mit der IF- Verschachtelung geht ja jetzt. Aber zu switch werde ich mal nachlesen, hab ja noch einiges vor.

    5,6) Du beziehst Dich auf den oberen Code, der aus Beispielen im Netz besteht. Wenn der original läuft baue ich ihn so zurecht wie ich ihn brauche mit der Try/Error Methode. Mir fehlt noch zuviel Wissen zu dem Thema sodaß ich selbst bei IF-Abfragen wo gegenlaufe.

    Aber das Thema ist spannend und ich lerne schon langsam dazu.

    Hans

  • Naja, der komplette Code... dann würde ich den wohl als Datei reinstellen (müssen).

    Aber ich habe ja die ganze Unterroutine "getTemperatures" gepostet. Für meine Frage zu IF halte ich das so für übersichtlicher.

    Mal sehen was ich mir als Nächstes vorknöpfe. Die geloggten Daten auf der SD-Karte möchte ich auslesen ohne die Speicherkarte zu entfernen. Ist ein Punkt.

    Hans

  • Naja, der komplette Code... dann würde ich den wohl als Datei reinstellen (müssen).

    Da mach Dir mal keine Gedanken: die Software des Forums kann das ab, dass Du hier den kompletten Quelltext postet - so viele Megabytes werden das nicht sein, oder? Falls Du doch Bedenken hast, kannst Du Dir ja eine Repository zum Beispiel bei Github anlegen und dann den Link daran hier posten.

    Ich bin nur kein Freund davon, Teile des Quellcodes zu sehen, wenn ich jemanden helfen soll.

  • colaholiker Alternative zum zeigen vom ganzen Quelltext wäre es nicht mit globalem Zustand zu arbeiten. Das macht man unter anderem aus diesem Grund nicht, weil man dann keine Funktion einzeln betrachten kann, weil irgendwelche Werte von aussen kommen und ausserhalb verändert werden, und man nicht erkennen kann was das für Werte sind.

    `tempDeviceAddress` sollte schon mal gar nicht global sein, das ist letztlich nur innerhalb der ``for``-Schleife sinnvoll. Hier ist auch der Präfix `temp` ein bisschen irreführend, denn das könnte für „Temperatur“ oder „temporär“ stehen.

    Neben `sensors` und `numberOfDevices` kann man dann einfach noch ein Array mit Korrekturwerten übergeben und sich damit ``if`` oder ``switch`` sparen. Ungetestet:

    “Dawn, n.: The time when men of reason go to bed.” — Ambrose Bierce, “The Devil's Dictionary”

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!