snprintf Problem

Hi ich wollte Sensordaten auslesen und habe folgendes Beispiel ausprobiert und das klappt wunderbar, doch sobald ich noch die SensorID nehme klappt es nicht,
das Problem ist, da die sensordaten von dreistellug bis 6stellig mit sonderzeichen ( negativwerte) varieren, variiert auch die größe des Arrays. ich habe notfalls das Array bzw. Buffer für snprintf geählt und sobald die Anzahl der stellen nicht voll ausgenutzt wird, werden willkürlich Zahlen bei der Ausgabe hinzugefügt, wisst ihr wie ich das umgehen kann?

das ist der folgende Beispielcode:

#include <CoreSensors.h>

void setup() {
 // Led.
 pinMode(10, OUTPUT);
 pinMode(11, OUTPUT);
 pinMode(12, OUTPUT);
 pinMode(13, OUTPUT);
 
 // Initialize serial for output.
 Serial.begin(115200);
 coresensors.begin();
}


void loop() {
 char report[27];
 float humidity, temperature;
 int32_t accelerometers[3];
 int SensorID = 1; 
 int32_t MagnitudeGesamt;
 
 coresensors.getAccelerometer(accelerometers);
 
 MagnitudeGesamt = sqrt(pow(accelerometers[0], 2) + pow(accelerometers[1], 2)

 Serial.print("| Hum[%]: ");
 Serial.print(humidity);
 Serial.print(" | Temp[C]: ");
 Serial.print(temperature);
 Serial.print(" ");
 
 snprintf(report, sizeof(report),"%d,%ld, %ld, %ld, %6ld ", SensorID, accelerometers[0], accelerometers[1], accelerometers[2]);
 
 Serial.println(report);
 Serial.println();

Habe ein Bild hinzugefügt. In der ersten Zeile auf dem angehängten Bild ist es zu sehen.

output.PNG

Du hast 5 Zahlen angeben und übergibst nur 4. Das passt schon mal nicht

Hi sorry stimmt, das habe ich verbessert ist aber immer noch vorhanden :frowning: so ist es richtig:

#include <CoreSensors.h>

void setup() {
 // Led.
 pinMode(10, OUTPUT);
 pinMode(11, OUTPUT);
 pinMode(12, OUTPUT);
 pinMode(13, OUTPUT);
 
 // Initialize serial for output.
 Serial.begin(115200);
 coresensors.begin();
}


void loop() {
 char report[27];
 float humidity, temperature;
 int32_t accelerometers[3];
 int SensorID = 1;
 int32_t MagnitudeGesamt;
 
 coresensors.getAccelerometer(accelerometers);
 
 MagnitudeGesamt = sqrt(pow(accelerometers[0], 2) + pow(accelerometers[1], 2)

 Serial.print("| Hum[%]: ");
 Serial.print(humidity);
 Serial.print(" | Temp[C]: ");
 Serial.print(temperature);
 Serial.print(" ");
 
 snprintf(report, sizeof(report),"%d,%ld, %ld, %ld, %6ld ", SensorID, MagnitudeGesamt, accelerometers[0], accelerometers[1], accelerometers[2]);
 
 Serial.println(report);
 Serial.println();

Das problem ist wieterhin vorhanden

Gib für jedes Formatelement die Länge an, die Du maximal hast / haben willst. Der Puffer (report) muss 1 größer sein, als die gesamte Länge.

Gruß Tommy

Tommy56:
Gib für jedes Formatelement die Länge an, die Du maximal hast / haben willst.

Was man da angibt ist nicht die maximale, sondern die minimale Länge. Die Differenz wird dann aufgefüllt. Aber mehr kann es trotzdem sein.

Wobei das eigentlich einer der wenigen Gründe ist printf() hier überhaupt zu verwenden. Wenn man Strings nur hintereinander ausgeben möchte kann man auch mehrmals Serial.print() aufrufen

Danke sehr,
mein Ziel ist es die ID und die verschiedenen Sensorwerte in einem String zu verpacken und diese dann über BLE zu senden, deshalb benutze ich snprintf. Die Sache ist, dass die ID ein int ist und die anderen Werte will ich von INT32 zu float convertieren. Was könntet ihr mir empfehlen?

Verstehe ich es richtig die minimale Größe angeben?

Etwas unbedingt in einem String zu senden ist ein anderer Grund für sprintf(). Es gibt ein paar Libraries die das benötigen (z.B VirtualWire). Rein mit Serial ist es überflüssig.

die anderen Werte will ich von INT32 zu float convertieren

Float kannst du auf dem AVR standardmäßig nicht mit printf() bearbeiten.

Ansonsten kommt es darauf an was du genau hast. Wenn z.B. 20.5 als 205 dargestellt ist musst du einfach durch 10.0 dividieren

Serenifly:
Was man da angibt ist nicht die maximale, sondern die minimale Länge. Die Differenz wird dann aufgefüllt. Aber mehr kann es trotzdem sein.

Ich hatte den Eindruck, dass er feste Positionen seiner Inhalte in der Zeichenkette haben will.
Deshalb habe ich die maximale Länge angegeben, damit es keine Verschiebungen gibt und jeder Bestandteil jeweils bis zu dieser Länge aufgefüllt wird.

Gruß Tommy

Ok , das ist kein AVR, ich verwende die Arduin Primo Cores.

also ist das snprintf angebracht dafür ?
Weil bei sprintf ist doch ein unterscheid mit dem Überladen des Buffer so weit ich mich erinnern kann?

Tommy56:
Deshalb habe ich die maximale Länge angegeben, damit es keine Verschiebungen gibt und jeder Bestandteil jeweils bis zu dieser Länge aufgefüllt wird.

Ja, aber das ist trotzdem nicht die maximale Länge. Wenn der formatierte String größer als angegeben ist wird er nicht abgeschnitten. Man muss den Wert halt groß genug wählen damit das nicht passiert

Tommy56:
Ich hatte den Eindruck, dass er feste Positionen seiner Inhalte in der Zeichenkette haben will.
Deshalb habe ich die maximale Länge angegeben, damit es keine Verschiebungen gibt und jeder Bestandteil jeweils bis zu dieser Länge aufgefüllt wird.

Gruß Tommy

Ja genau es sollen feste Positionen sein, doch ob der Wert dreistellig oder vierstellig ist bzw. vorzeichenbehaftet oder nicht, dass kann ich nicht wissen, deshalb hatte ich die Maximalgröße angegeben und es funktioniert nicht irgendwie kommen immer Zusatzzahlen hinten dazu. Eine Verstädnisfrage, in snprintf bestimme ich das Ausgabeformat und ich habe folgendes : "%d,%ld, %ld, %ld, %6ld "-->Werden die Kommas mitgezählt als plathalter in dem Array report bzw. muss ich diese dazurechnen. ich hatte z.B als max.Länge 6 stellen und habe dies folgendemaßen festgelegt gehabt, %d,%6ld, %6ld, %6ld, %6ld, doch da die Zhalen vierstellig oder dreistellig sind hatte ich immer Leerzeichen vor den Zahlen. Mache ich da etwas falsch?

Das ist ja das Ziel, dass die Zahl linksbündig mit Leerzeichen aufgefüllt werden, damit sich die Positionen nicht ändern.
Wie groß die einzelnen Werte maximal werden, solltest Du schon wissen. Es sind ja Deine Zahlen.

Gruß Tommy

%6ld bedeutet dass die Zahl rechtsbündig auf 6 Zeichen Breite formatiert wird. Wenn die Zahl kleiner ist wird mit Leerzeichen aufgefüllt. Also 111 wird zu " 111"

Wenn du im Format-String zusätzlich Leerzeichen angibst kommen die noch extra dazu

z.B.:

void setup()
{
  Serial.begin(9600);

  long value1 = 111;
  long value2 = 2222;

  char buffer[20];
  snprintf(buffer, sizeof(buffer), "%6ld,%6ld", value1, value2);
  Serial.println(buffer);
  snprintf(buffer, sizeof(buffer), "%-6ld, %-6ld,", value1, value2);
  Serial.println(buffer);
}

void loop()
{
}

Ausgabe:

   111,  2222
111   , 2222  ,

Ok danke für die Erklärung,

d.h. wenn ich für meine beiden zahlen 6 stellen reserviere, hätte ich 12 + 1mal das komma = 13 stellen richtig verstanden?
EIne andere Frage ist, da diese in Char umgewandelt wird hätte ja jedes Zeichen 1 Byte größe oder ? ->
123456, 777589 = 13 Byte groß oder?

123456, 777589

Das sind 15 Bytes. 6 + 1 (Komma) + 1 (Leerzeichen) + 6 + 1. Null-Terminator nicht vergessen!

Stimmt in deinem Fall mit dem Leerzeichen sind es 15.

Danke sehr für eure Erklärung. Der Grund warum ich euch frage ist, da ich diesen String via Bluetooth senden will und in BLE ist das DataPackage max 20Byte . Ich habe die Daten extra auf mehrere Charachteristics aufgesplittet gehabt, doch der Central Node kann sich nicht gleichzeigt von mehreren Characteristics die erhalten, zumindestens habe ich es nicht hinbekommen. Kennt ihr da eventuell einen Ausweg?

Wir kennen Deienen Central Node nicht. Brauchst Du wirklich 6 Nachkommastellen oder sind die nur Zierrat? Nach dem Komma (zur elektronischen Weiterverarbeitung wäre ein . besser) sollte kein Leerzeichen kommen, wenn es eine Fließkommazahl darstellen soll.

Irgendwie komme ich bei Dir mit float und nichtfloat nicht klar.

Gruß Tommy

Hi Tommy56, nein ich brauche keine 6 Nachkommastellen ich bräuchte 2 Nachkommastellen bei den Sensorwerten und bei der ID muss das nur eine Ganzzahl sein.

D.h. ID(Integer),Mag(float),Sensorx(float),Sensory(float),Sensorz(float). Die Werte müssten mit einem Komma getrennt werden

printf() ist sehr gut dokumentiert:
http://www.cplusplus.com/reference/cstdio/printf/

http://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html#gaa3b98c0d17b35642c0f3e4649092b9f1

%.2f ist zwei Nachkommastellen
%6.2f ist Mindestbreite von 6 Zeichen und zwei Nachkommastellen

Und auf größeren Prozessoren geht auch %f (auf den AVRs auch, ist aber deaktiviert um Speicher zu sparen). Teste es erst mal ohne die Sensoren mit festen Werten.