Merkwürdigkeit bei der formatierten Ausgabe eines Analogwertes

Hallo zusammen:
ich grüble schon einige Stunden über folgenden Effekt:

gegeben ist ein Drehpotentiometer am Analogeingang A0, ein 2009er und ein 16x4 LC-Display,

entsprechend dem untenstehenden Code lese ich den momentanen Wert an A0 ein und gebe ihn auf der zweiten Zeile des Displays aus.
Zur besseren Lesbarkeit (und zu Fingerübungszwecken) :wink: ) bemühe ich eine Funktion "mach4", den eingelesenen Wert zwischen 0 und 1023 auf 4 Stellen zu formatieren, also mit führenden Leerzeichen aufzufüllen.
Im Ergebnis erhalte ich dieses Format (die Ausgabe endet immer unterhalb des Buchstabens "t" vom oberen Wort "Start",
aber ich bekomme nur maximal den Wert "996" bis "998" !
Alles ab 1000 wird nicht dargestellt, ich bemerke sogar einen spürbaren Leerweg bis zum Ende des Drehweges, ohne dass sich ein höherer Wert als 998 einstellt.
Für Debuggingzwecke habe ich eine weitere Ausgabeanweisung zur Ausgabe des ursprünglichen Zahlenwertes unter der eigentlichen Ausgabeanweisung eingebaut und hier auskommentiert,
daran sehe ich, dass durchaus am Ende des Drehweges der Wert bis auf 1023 steigt.

Kann sich mal jemand die Zeilen unten in der Funktion zu Gemüte führen,vielleicht sehe ich einfach das Simpelste nicht mehr.

Gruß
Manfred

/*
   LCD Ausgabeversuche / Analogwerte am Port A0
 
   Die Schaltung:
   Anschluss 1M Dreh-Potetiometer zwischen +5V und GND, 
   Mittelabgriff an Analog-Eingang AD0 (Pin AD0)
   Ausgabe des Eingangswertes (0-1023) auf LCD Zeile 2 
 */
 
// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);


int analog_pin = A0;       // Analogport 0 
int einlesewert = 0;       // Variable erhält den digitalen Wert 0 bis 1023 des Analogwertes
int ausgabewert = 0;       // Variable erhält den auszugebenden Wert
String ausgabe;            // Ausgabezeichenkette

void setup() {
  // set up the LCD's number of rows and columns: 
  lcd.begin(16, 4);
  // Startmeldung auf die erste LCD Zeile
  lcd.print("Wert am Eingang");
  
}

void loop() {
  einlesewert = analogRead(analog_pin);
//
  ausgabe = mach4(einlesewert);  // Funktion formatiert auf 4 Stellen

  lcd.setCursor(0, 1);
  lcd.print(ausgabe);
    
// lcd.print("  ");
// lcd.print(einlesewert);

  delay(250);
}


String mach4(String eingabe)  // Eingabe auf 4 Stellen formatieren
{
  eingabe = eingabe.trim();   // evtl. "white spaces" entfernen
  int l = eingabe.length();   // Variable l hält die Länge (1-4 Zeichen)
  String ergebnis;            // Rückgabevariable
  
  switch (l) 
  {
    case 1:
      ergebnis = "   " + eingabe; // plus 3 führende Leerzeichen
      break;
    case 2:
      ergebnis = "  " + eingabe;  // plus 2 führende Leerzeichen
      break;
    case 3: 
      ergebnis = " " + eingabe;   // plus 1 führende Leerzeichen
      break;
    ergebnis = eingabe;           // unverändert 4 Zeichen
   }
    return ergebnis;
 }

Hallo

womöglich hängt es nur an der 4 Stelligen Abfrage in der case- Schleife, die nicht als default: gekennzeichnet ist ?

Hallo ManfredH

womöglich hängt es nur an der 4 Stelligen Abfrage in der case- Schleife, die nicht als default: gekennzeichnet ist ?

Glaube ich auch.

Du kannst das einfacher schreiben:

switch (l) 
  {
    case 1:
      eingabe = " " + eingabe; // plus 1 führende Leerzeichen total 3
    case 2:
      eingabe = " " + eingabe;  // plus 1 führende Leerzeichen total 2
    case 3: 
      eingabe = " " + eingabe;   // plus 1 führende Leerzeichen
    } 
    ergebnis = eingabe;

Ohne "break;" werden die darauffolgenden Zeilen ausgeführt.

Grüße Uwe

Hallo Uwe, hallo Df6ih,

am fehlenden "default" liegt es nicht - default: ist auch in der Referenz als optional bezeichnet.

@Uwe
Deine Variante funktioniert auch nicht, sondern produziert noch eine weitere Merkwürdigkeit
(versetzen der Ausgabe um eine Stelle nach rechts bei Zahlen mit weniger als 4 Stellen).

Mit folgender stupiden Variante bin ich erfolgreich
(die unsichtbaren Blanks habe ich dieses Mal gegen Nullen getauscht, um eventuelle "Platz"Fehler zu erkennen):

String mach4(String eingabe)  // Eingabe auf 4 Stellen formatieren
{
  eingabe = eingabe.trim();   // evtl. "white spaces" entfernen
  int l = eingabe.length();   // Variable l hält die Länge (1-4 Zeichen)
  String ergebnis;            // Rückgabevariable
  
  if (l == 1)
  {
    eingabe = "000" + eingabe;
  }
  else if (l == 2)
  {
    eingabe = "00" + eingabe;
  }
  else if (l == 3)
  {
    eingabe = "0" + eingabe;
  }
  
  ergebnis = eingabe;
  return ergebnis;
 }

und weil danach auch die alte "case" Geschichte in gleicher Weise funktioniert

String mach4case(String eingabe)  // Eingabe auf 4 Stellen formatieren
{
  eingabe = eingabe.trim();   // evtl. "white spaces" entfernen
  int l = eingabe.length();   // Variable l hält die Länge (1-4 Zeichen)
  String ergebnis;            // Rückgabevariable
  
  switch (l)
  {
    case 1:
    eingabe = "000" + eingabe;
    break;
  
    case 2:
    eingabe = "00" + eingabe;
    break;
  
    case 3:
    eingabe = "0" + eingabe;
    break;
  }
  
  ergebnis = eingabe;
  return ergebnis;
}

kommen nur zwei Erklärungen in Frage:

1.) Nullen als Leerstellen statt Blanks
sehr unwahrscheinlich

2.) die Zuweisung der verlängerten Strings in der Form "eingabe = "00" + eingabe" und erst ganz am Schluß die Zuweisung an die Variable ergebnis = eingabe

Das sieht mir sehr wahrscheinlich aus. :slight_smile:

Werde morgen mal den Kreuzversuch mit Blanks statt Nullen machen.

Gruß
Manfred

Hallo

Ja, aber wenn "optional" in der logischen Abfolge den nicht abgedeckten Fall klärt dann ist es zwar optional aber unabdingbar im Sinne der von dir gesuchten Lösung.

:wink:

Hallo ManfredH
Ich hatte den Kode nicht kontrolliert Entschuldige.
Grüße Uwe

Hallo Uwe,
kein Problem!
Ich hatte ja verstanden, dass Du mir einen verkürzten Code zeigen wolltest.

@df6ih
ist schon klar.
Ich wollte mit "optional" nur klarstellen, dass der Kompiler die Anweisung default: nicht zwingend benötigt,
sie ist sicher immer sinnvoll, wenn es neben 3 oder 4 vorhersehbaren Fällen eine unbekannte Zahl anderer Möglichkeiten gibt.

Kann man eigentlich für "case auch einen Ausdruck einsetzen oder einen Wertebereich?

Gruß
Manfred

ManfredH:
Kann man eigentlich für "case auch einen Ausdruck einsetzen oder einen Wertebereich?

Für Letzteres hilft vielleicht ein Blick ins alte Forum:

Danke Schwarzfuss!
Dafür ein <Grün> :wink:

Hier eine Alternative, typischerweise C und sehr kompakt:

char outb[8];  // vorsicht hier, wenn du mehr 'drucken' moechtest
sprintf(outb, "%04d", meinwert); // 4 stellen mit fuehrender null
lcd.print(outb);

Wenn du nun den Format String aenderst "%04d" kannst du verschiedene Darstellungen schnell hinbekommen:

"%4d" // (keine fuehrenden Nullen)
"%+5d" // positive werte haben immer ein fuehrendes +, negative ein fuehrendes -

Du kannst aber auch bequemerweise mehrere Werte gleichzeitig 'formatieren' und Text hinzufuegen:

char outb[32];
sprintf(outb, "[A0=%4d A1=%4d]", analogRead(0),analogRead(1));
lcd.print(outb);
// druckt: [A0=    2 A1= 945]

Und zur Vollstaendigkeit, prozent angabe

char outb[32];
sprintf(outb, "A0=%3d%%", (short)((long)analogRead(0)*100/1024)); // bit verlust when in short gerechnet
lcd.print(outb);
// druckt: [A0= 61%]

HTH :wink:

Danke HTH!

Das muß ich doch ein paar Mal, gaaaanz langsam, durchsehen und verstehen.
Werde es nach dem Kaffee mal umsetzen und die resultierende Codegröße betrachten...
Da mein Mini ein 168er ist, bin ich für jedes Byte weniger dankbar!

sprintf() ist eine gültige "Arduino"-Funktion?

Gruß
Manfred

@ HTH:
funktioniert!

Und das Beste ist, dass statt 5132Bytes (if- oder case-Konstruktion) nur 3924 Bytes benötigt werden!

Gruß
Manfred

@Manfred

sorry wegen des 'HTH', internet jargon, auf schlecht deutsch: Hope That Helps!

sprintf funktioniert, ABER keine floating points, eben wegen des platz mangels (mit fix point geht's ja auch dann, ist aber komplizierter).

Juergen