Datentyp Overflow mit Stringbuffer

Hallo,

long value;
long Kanal_1;
char AD_Channel_1[8]; // Buffer

Die LCD Ausgabe von “AD_Channel_1” zeigt immer von -32768 bis +32767 an, obwohl es durch +32768 dann 0 bis 65535 sein sollte.

Wenn ich den Code umbaue und zu value 32768 addiere, sodass value einen Wertebereich von 0 bis 65535 sieht und dann value wieder einer String Formatierung zuführe, bleibt es jedoch bei einer Anzeige von -32768 bis +32767.
snprintf(AD_Channel_1,8,"%6d", value);

Gibt es einen Überlauf wie bei int?
Wenn ich value als long Variable einfach mit lcd.print(value); anzeigen lassen, sehe den Wertebereich von 0 bis 65535.

Bin ratlos … :roll_eyes:

       case 1 : snprintf(AD_Channel_1,8,"%6d", value); 
                lcd.setCursor(0,0); lcd.print(AD_Channel_1); lcd.print("  ");
                value = value+32768;
                //snprintf(AD_Channel_1,8,"%6d", value); 
                //lcd.setCursor(1,1); lcd.print(AD_Channel_1); lcd.print("  ");
                lcd.setCursor(1,1); lcd.print(value); lcd.print("  ");
                Kanal_1 = (float)(value + Kanal_1 * 8) / 9.0;
                lcd.setCursor(1,2); lcd.print(Kanal_1); lcd.print("  ");
                activ_Channel = 2;
                break;

MCP3428_008.ino (6 KB)

Hast du mal "%6ld" als Format-String probiert?

Da gibt es noch Optionen für die Datentypen:
http://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html#gaa3b98c0d17b35642c0f3e4649092b9f1

An optional l or h length modifier, that specifies that the argument for the d, i, o, u, x, or X conversion is a "long int" rather than int. The h is ignored, as "short int" is equivalent to int.

Hallo,

mit "%6ld" zeigt er nichts an, also leer.

mit "%6lld" und mit "%6Ld" zeigt er nur stur GA an.

Laut dem Beitrag kann das wohl der Compiler nicht. long ausgabe mit printf - Mikrocontroller.net

Ist dem wirklich so?

Ich sehe das die Anzeige wirklich überläuft, der springt ins negative und wird wieder positiver. Als wenn die Stringformatierung wirklich nur mit int arbeitet.

Edit:
mit u gehts.
Also "%6u"

Weil das d steht für dezimal integer und das u für dezimal unsigned integer. Man oh man .... :wink:

Was auch noch funktioniert ist "%f" für floating point wenn man eine float Variable zuführt.

Danke für den Denkanstoß. :wink:

Dass %lld nicht geht steht auch dort. Das wäre long long, was es nicht gibt:

But the ll length modifier will to abort the output, as this realization does not operate long long arguments.

Ich hätte halt angenommen, dass %ld geht wenn es in der Doku steht.

Bei mir geht es auch was ich so sehen kann:

  unsigned long value = 100000;
  char buffer[20];
  snprintf(buffer, sizeof(buffer), "%6ld", value);
  Serial.println(buffer);

Und bei 10000 füllt er dann Leerzeichen auf um auf Breite 6 zu kommen

Was auch noch funktioniert ist "%f" für floating point wenn man eine float Variable zuführt.

?
Float ist auf dem Arduino nicht implementiert. Dazu braucht man gepatchte Core Files:
http://forum.arduino.cc/index.php/topic,124809.msg940922.html#msg940922

was bedeutet die Zeile

err = adc.read(value, status);

Grüße Uwe

nicht %6ld sondern %6d!

die 6 steht bereits für das l !

analog für floats:

%5.2f = 5 Stellen, davon 2 Nachkommastellen (Komma zählt mit).

den float-patch hab ich übrigens auch gemacht, funktioniert bestens! :sunglasses:

Hallo,

@ Serenifly:
stimmt, float geht nicht. Nur mit dem Patch. Das wollte ich eigentlich vermeiden. Also funktioniert die Stringformatierung nur mit unsigned int bis eben maximal 65535 ? Kann man sich das so merken? Ansonsten muß man patchen. Ich werde wohl den float Wert vorher zerlegen in 2 Ganzzahlen.

@ Uwe:
Diese Zeile kommt von der MCP342x Library, damit wird nach der Conversion Time der AD Wert ausgelesen. Da blick ich jedoch selber kaum durch. Hatte mir Serenifly geholfen. Ich habe das Bsp. ohne delay ausgebaut damit ich alle 4 Kanäle verwenden kann. Du warst doch in Mailand. Wird es bald eine neue Arduino IDE Version geben mit aktuellsten Compiler, worin auch zum Bsp. das hier ohne Patch mit float funktioniert?

@ HaWe:
die 6 steht für 6 reservierte Anzeigefelder. Damit kann man die Anzeige wunderbar rechtsbündig formatieren. Weswegen ich den Aufwand auch betreibe ohne dahinter noch aufwändiger leere LCD Felder löschen zu müssen.

Doc_Arduino:
stimmt, float geht nicht. Nur mit dem Patch. Das wollte ich eigentlich vermeiden.

Oder dtostrf() verwenden. Das reicht manchmal

Also funktioniert die Stringformatierung nur mit unsigned int bis eben maximal 65535 ? Kann man sich das so merken?

Bei mir geht es auch mit unsigned long. Ich habe es aber nicht ausführlich getestet.

Doc_Arduino:
@ Uwe:
Diese Zeile kommt von der MCP342x Library, damit wird nach der Conversion Time der AD Wert ausgelesen. Da blick ich jedoch selber kaum durch. Hatte mir Serenifly geholfen. Ich habe das Bsp. ohne delay ausgebaut damit ich alle 4 Kanäle verwenden kann. Du warst doch in Mailand. Wird es bald eine neue Arduino IDE Version geben mit aktuellsten Compiler, worin auch zum Bsp. das hier ohne Patch mit float funktioniert?

Ich war nicht in Mailand sondern in Turin :wink: :wink: :wink:
Ich habe mit einem Entwickler über das für und wider der automatischen Updats von Dritt-Biblioteken die im IDE geliefert werden gesprochen, aber nicht über Zeiten wann die nächste Version des IDE herauskommt.
Aus Erfahrung sind Zeitagaben für die Verfügbarkeit zukünftiger Arduino-Modelle sehr mit Vorsicht zu geniesen und ich übernehme das auch für die IDE.

Wenn die in x Wochen gesagt hätten, werden es sicher x+y Wochen sein ( wobei y >> x ist) :wink: :wink: :wink: Darum ist es mir gar nicht in den Sinn gekommen zu fragen 8) 8) 8) 8)

Grüße Uwe

Es wäre zwar mal dringendst notwendig die antiken Version von avr gcc und der avr libc in der Arduino IDE upzudaten, aber das alleine bringt noch keine Float Unterstützung für printf() und scanf()

Dazu muss man das Projekt mit bestimmten Compiler Optionen compilieren (und die sind von der IDE vorgegeben):

-Wl,-u,vfprintf -lprintf_flt -lm

Hier wäre es nötig, dass es in der IDE einen Haken gibt um die Float Option ein- und auszuschalten. Machbar wäre das wohl.

Hallo,

Danke Euch zu später Stunde, nebenbei lief die Fussball WM. :slight_smile: Morgen, ach ne heute, wird's wieder wichtig

@ Uwe:
okay, habs verwechselt, Hauptsache Italien. :wink:

@ Serenifly:
irgendwie hatten wir über dtostrf() schon mal gequatscht. Irgendwas gefiel mir daran nicht. unsigned long funktionierte vorhin bei mir nicht. Werde das nochmal in Ruhe probieren.

Möchte nur noch zeigen wie man eine float Variable ohne "float Patch" zerlegt und anzeigt.

// global definiert

char AD_Channel_1[8];            // Buffer zum Zwischenspeichern
char AD_Channel_G[9];            // Buffer zum Zwischenspeichern
float Kanal_1;
long value;
  
long Ganzzahl;
int vorK;
int nachK;

// --------------------------------------------------------

value = value+32768;
snprintf(AD_Channel_1,8,"%6u", value); 
lcd.setCursor(0,0); lcd.print(AD_Channel_1);
Kanal_1 = (float)(value + Kanal_1 * 8) / 9.0;        // Fließkommazahl
lcd.setCursor(0,1); lcd.print(Kanal_1);
// Fließkommazahl wird in Ganzzahlen zerlegt, in Vorkomma und Nachkomma
Ganzzahl = (long) (Kanal_1*100);      // 38772.48 >>> 3877248   ( *100 für 2 Nachkommastellen)
vorK = Ganzzahl/100;                  // 3877248  >>> 38772     ( /100 für 2 Nachkommastellen)
nachK = Ganzzahl-(vorK*100);          // 3877248 - 3877200 = 48
snprintf(AD_Channel_G,9,"%5u,%02d", vorK, nachK);  // Anzeige  38772,48
lcd.setCursor(0,2); lcd.print(AD_Channel_G);

Hallo,

habs nochmal getestet

char AD_Channel_1[9]; // Buffer
long value;

value = value*4;     // value kommt rein zwischen -32768 und +32767

// long - funktioniert (Anzeige von -131072 bis +131068
snprintf(AD_Channel_1,9,"%7ld", value); 
lcd.setCursor(0,0); lcd.print(AD_Channel_1);

// unsigned int - funktioniert, läuft aber int bedingt über wenn value größer 65535 wird
snprintf(AD_Channel_1,9,"%7u", value); 
lcd.setCursor(0,1); lcd.print(AD_Channel_1);

// soll long sein - funktioniert nicht
snprintf(AD_Channel_1,9,"%7L", value); 
lcd.setCursor(0,2); lcd.print(AD_Channel_1);

// soll long sein - funktioniert nicht
snprintf(AD_Channel_1,9,"%7Ld", value);

Edit:
mit Atmel Studio + Visual Micro Plugin hat man das gleiche Ergebnis. Auch float funktioniert nicht.

Edit:

habe nochmal dtostrf probiert, klappt diesmal wunderbar, ist auch rechtsbündig, da hatte ich wohl letztens die Parameter falsch gesetzt. Da muß man sehr aufpassen, weil der erste Parameter die gesamte Länge vorgibt, wenn die zu klein ist, kommt es durcheinander. Sorry. Alles bestens.

Kanal_1 = (float)(value + Kanal_1 * 8) / 9.0;
dtostrf(Kanal_1, 10, 2,AD_Channel_1);
lcd.setCursor(0,2); lcd.print(AD_Channel_1);