Float Zahl im LCD an der richtigen Stelle darstellen

Hallo Arduino Gemeinde,

ich verzweifel seit Tagen an meinem Sketch. Ich habe eine float zahl die sich von -50 bis +30 ändert. Diese möchte ich im LCD anzeigen. Dazu mache ich einen String den ich an das LCD schicke.

Nun habe ich aber das Problem das beim Wechsel von -10 auf -9, von -0,5 auf 0,0 usw die ganze Zahl nach links springt und den Rest meines Strings dann auch mit nach links zieht.

Kurzum: Das optische Erlebnis ist bescheiden.

sprintf funktioniert mit float in Arduino leider nicht. Einer Zerlegung in zwei Integer (vor und nach dem Komma) löst das dezimalstellen und Vorzeichenproblem auch nicht richtig. dtostrf klappt zwar grundsätzlich aber auch da kann ich nicht beeinflussen wie die float in einen String umgewandelt wird.

Kennt ihr eine Möglichkeit wie ich die float immer: a) rechtsbündig b) mit 5 Zeichen c) einer Nachkommastelle

in einen String umwandeln kann?

Wieso passt dtostrf() nicht? Da kannst du die Anzahl der Nachkommastellen und die Ausrichtung angeben

Auf 5 Zeichen Breite

-50.0
 -5.0
  0.0
  3.0
 30.0

Wenn man Dinge wie führende Nullen möchte kann man noch mal über den String drüber gehen und ihn etwas ändern

Oh… ich habs wohl nich geschnallt…

char z1[6]; //Ich definiere einen Puffer

dtostrf(pegel,2,1,z1); // Ich wandel meine float Variable “Pegel” in einen Char um - weil er String nicht akzeptiert

char dispmsg [16]; // ich mache mir ein 16 teiliges Ausgabefeld

sprintf(dispmsg, “Pegel: %s db”, z1); //füge alles hinzu

zeile2 = String (dispmsg); // mache daraus einen String, den ich dann an das LCD schicke

Es sieht…echt umständlich aus… wie kann ich denn die Ausrichtung in dtostrf angeben? Wo kann ich das nachlesen? Wenn ich die Funktion google dann finde ich alles mögliche, nur nichts was in arduino fiunktioniert ;-(

Kann ich nicht direkt damit in den String?

Nicht ganz. Die Breite ist die Mindestbreite des gesamten Strings, inklusive Vorzeichen und Punkt! Nicht die Anzahl der Vorkommastellen.

dtostrf() ist nicht ISO C. Die Funktion existiert in der AVR libc genau will printf() normal nicht mit floats geht. Da ist sie auch dokumentiert:
http://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html#ga060c998e77fb5fc0d3168b3ce8771d42
Auch gut hier erklärt:
https://www.mikrocontroller.net/topic/86391

Aber wieso verpackst du das dann nochmal ein ein String Objekt? Es sei denn deine Lib frisst nur String Objekte ist das Schwachsinn hoch zehn.

Du braucht hier auch nicht unbedingt printf(). Wenn du eine angenehme Syntax zur Ausgabe von Sachen willst, dann nimm das:
http://arduiniana.org/libraries/streaming/

Damit hast du den Output Stream Operator aus C++. Wenn deine LCD Klasse von Print erbt (was z.B. die normalen LiquidCrystal Libraries tun, aber TFT Libs evtl. nicht), kannst du das machen:

lcd << "Pegel: " << buffer << " db"

Der Code dahinter ist genau der gleiche wie man man mehrmals hintereinander lcd.print() aufruft.

Aber so ziemlich die einzige Stelle wo es sinnvoll sein kann den Ausgabe-String wirklich in einem String stehen zu haben sind manche Grafik LCD/TFT Libraries. Aber einem 16x2 Display z.B. ist es vollkommen egal ob das in einem String steht oder ob du mehrmals lcd.print() machst

Serenifly:

lcd << "Pegel: " << buffer << " db"

Fehlt da nicht noch ein Semikolon?

BTW: Wie sieht es mit iomanip.h aus? Ist das auch zu haben?

Gruß

Gregor

Fehlt da nicht noch ein Semikolon?

Ja

Wie sieht es mit iomanip.h aus? Ist das auch zu haben?

Sowas wie iomanip gibt es in der SdFat Library. Siehe das "formatting" Beispiel

Serenifly: Sowas wie iomanip gibt es in der SdFat Library. Siehe das "formatting" Beispiel

Prima. Demnach lohnt sich ein näherer Blick darauf. Danke!

Gregor

Danke für die vielen Tips. Warum packe ich das in ein Stringelement?

Nun ich habe einen Anzeige Arduino der über IIC ein Datenpaket bekommen soll, Zeile 1 und Zeile 2. In meinem Hauptarduino erstelle ich diese Strings. Warum strings? Weil ich es nicht hinbekomme Arrays vernünftig zu befüllen und zu formatieren. Ich denke ich muss dazu noch etwas Grundlagen pauken wobei mir auch hier die Literatur ausgeht. Warum definiert man Arrays über Pointer? Und wieso kann ich nicht einfach ein Array in ein anderes Array übergeben ( zeile2 = pegelarray) ... ich würde es gerne verstehen - habt ihr da einen Lesetipp? (Die letzte Onlineressource schrieb: When it comes to arrays it might be a litte esoterik but just write down the asterix... äh ja- ne! ) Habt ihr vielleicht einen Buchtipp der C++ aus Sicht von Arduino wirklich gut erklärt? Meine Skills stammen aus einem C Kurs - von vor über 20 Jahren- ich bin da ein wenig "aus der Übung".

Warum definiert man Arrays über Pointer?

In erster Linie weil C recht alt ist und weil die Hardware damals nicht sonderlich schnell war. C sollte sehr effizient sein. Eine Hochsprache die nahe an die Geschwindigkeit von Assembler kommt. Deshalb der direkte Speicherzugriff.

arr int[5] ist erst mal kein Zeiger. Das ist der Grund weshalb z.B. sizeof(arr) die korrekte Größe liefert. Man kann der Variable auch kein anderes Array oder anderen Speicher zuweisen.

Die Variable kann aber mit Zeiger-Arithmetik angesprochen werden und zerfällt bei bestimmten Operationen in einen Zeiger.

Und wieso kann ich nicht einfach ein Array in ein anderes Array übergeben ( zeile2 = pegelarray)

Siehe oben. Das ist in C einfach keine komplexe Datenstruktur, sondern die Variable ist nicht viel mehr als ein Zeiger auf das erste Element im Speicher. Mit = weißt man nur den Zeiger zu und mit == vergleicht man nur den Zeiger.

Wenn man Arrays wirklich kopieren muss gibt memcpy() dafür. Bzw. strcpy() für C Strings (beachte dabei, dass du da auch Speicher anlegen musst und nicht einfach nur einen Zeiger als Ziel deklarieren kannst). Für Vergleiche gibt es Funktionen wie memcmp() und strcmp().

Aber wie gesagt, du brauchst nicht unbedingt einen ganzen String, egal ob String Klasse oder C String. Ausgaben kann man einfach Stückeln:

LCD.print("var: ");
LCD.print(var);
LCD.print(" V");

Also wenn du einen neuen Wert hast einfach direkt ausgeben ohne die Zeile irgendwo zwischenzuspeichern.

Ganze Zeilen zu speichern braucht man eigentlich nur wenn man mehrere Seiten auf dem Display hat und diese z.B. zeitgesteuert im Wechsel anzeigt. Und selbst da wäre es möglich das anders zu machen.

Du musst dich halt mal entscheiden was du machen willst. Wenn du sowieso String Objekte verwendest, dann brauchst du auch kein printf() um erst mal einen C String zu basteln, sondern kannst Teil-Strings gleich mit + konkatenieren (was mit C Strings mit strcat() geht). Wobei die String Klasse den Nachteil hat dass wichtige Formatierungs- und Konvertierungsfunktionen fehlen. Deshalb kommt man um C Strings nicht herum.

Ahhhhhhhhhchso! Jetzt ergibts auch Sinn warum ich nach Arraydefinition nur noch mit dem Zeiger arbeite..

DANKE!

Ich spiele gerade mit der Streamausgabe- voll toll.

Was ich aber nicht hinbekomme, auch mit der dtostrf nicht, ist rechtsbündige Ausgabe der float.

Die springt beim wechsel von + nach minus und von 1 auf zweistellig immer um eine Stelle weg und zerhagelt mir damit die Ausgabezeile

Was ich aber nicht hinbekomme, auch mit der dtostrf nicht, ist rechtsbündige Ausgabe der float.

Statt:

dtostrf(pegel,2,1,z1);

So:

dtostrf(pegel,5,1,z1);

Wie gesagt, width ist die Mindestbreite des gesamten Strings ohne Terminator. Wenn du also 5 angibst und dein String eigentlich nur “3.3” ist wird links mit zwei Leerzeichen aufgefüllt.

Krass. Jetzt gehts! Super, dankeschön!