sprintf komisches Verhalten

Hallo zusammen,
ich verwende mehrere NodeMCUs mit esp8266 und Arduino IDE. Am Wochenende habe ich ein Display über i2c an das esp Board angeschlossen und über MQTT einige Daten vom nächsten Broker geladen.
Ziel war es die Akuelle- & Tagesleisung der PV Anlage anzuzeigen. Soweit funkioniert auch alles ganz gut bis zu dem Punkt wo die Tagesleistung vierstellig wird. Dann wird der Sting der aktuellen Leistung an die Tagesleistung angehängt. Hat jemand eine Idee warum das so ist? Stehe ein wenig auf dem Schlauch…

Soll Ausgabe:
Leistung: 728W
Tag: 1012W

Ist Ausgabe:
Leistung: 728W
Tag: 1012728W

#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>

LiquidCrystal_I2C  lcd(0x27, 2, 1, 0, 4, 5, 6, 7); // 0x27 is the I2C bus address for an unmodified backpack
WiFiClient espClient;
PubSubClient client(espClient);


const char* ssid = "****";
const char* password = "****";
const char* mqtt_server = "****";

bool new_data = true;
char work_buffer[21] = "";
long aktuelle_leistung;
long tagesleistung;
long wasserstand;
int wasserstand_in_prozent = 0;

void LCD_progress_bar (int row, int var, int minVal, int maxVal)
{
  int block = map(var, minVal, maxVal, 0, 16);   // Block represent the current LCD space (modify the map setting to fit your LCD)
  int line = map(var, minVal, maxVal, 0, 80);     // Line represent the theoretical lines that should be printed
  int bar = (line - (block * 5));                         // Bar represent the actual lines that will be printed

  /* LCD Progress Bar Characters, create your custom bars */

  byte bar1[8] = { 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10};
  byte bar2[8] = { 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18};
  byte bar3[8] = { 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C};
  byte bar4[8] = { 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E};
  byte bar5[8] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F};
  lcd.createChar(1, bar1);
  lcd.createChar(2, bar2);
  lcd.createChar(3, bar3);
  lcd.createChar(4, bar4);
  lcd.createChar(5, bar5);

  for (int x = 0; x < block; x++)                        // Print all the filled blocks
  {
    lcd.setCursor (x, row);
    lcd.write (1023);
  }

  lcd.setCursor (block, row);                            // Set the cursor at the current block and print the numbers of line needed
  if (bar != 0) lcd.write (bar);
  if (block == 0 && line == 0) lcd.write (1022);   // Unless there is nothing to print, in this case show blank

  for (int x = 16; x > block; x--)                       // Print all the blank blocks
  {
    lcd.setCursor (x, row);
    lcd.write (1022);
  }
}

void setup_wifi() {
  delay(10);
  WiFi.begin(ssid, password);
  lcd.clear();
  lcd.home();
  lcd.print("Connecting to Wifi:");
  lcd.setCursor (0, 1);
  lcd.print(ssid);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
  lcd.setCursor (0, 2);
  lcd.print("Wifi Connected");
  delay(1000);
  randomSeed(micros());
}


void callback(char* topic, byte* payload, unsigned int length) {
  String inStr = (char *)payload;
  payload[length] = '\0';

  if (strcmp(topic, "garage/aktuelle_leistung") == 0) {
    aktuelle_leistung = (inStr.toInt());
    //string_aktuelle_leistung = (char *)payload;
  }

  if (strcmp(topic, "garage/tagesleistung") == 0) {
    tagesleistung = (inStr.toInt());
  }

  if (strcmp(topic, "garten/wasserstand") == 0) {
    wasserstand = (inStr.toInt());
  }
  inStr = "";
  new_data = true;
}

void reconnect() {
  lcd.setCursor (0, 3);
  lcd.print("MQTT:");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    lcd.print(".");
  }
  while (!client.connected()) {
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str())) {
      client.subscribe("garage/aktuelle_leistung");
      client.subscribe("garage/tagesleistung");
      client.subscribe("garten/wasserstand");
    }
    else {
      delay(5000);
    }
  }
}

void setup()
{
  lcd.begin (20, 4); // for 16 x 2 LCD module
  lcd.setBacklightPin(3, POSITIVE);
  lcd.setBacklight(HIGH);

  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  Serial.begin(115200);
}

void loop()
{
  if (!client.connected()) {
    reconnect();
    delay(1);
  }

  if (new_data == true) {
    lcd.clear();
    lcd.home();

    lcd.setCursor (0, 0);
    sprintf(work_buffer, "Leistung:%5d W\0", aktuelle_leistung);
    lcd.print(work_buffer);

    delay(20);

    lcd.setCursor (0, 1);
    sprintf(work_buffer, "Tag:     %5d W\0", tagesleistung);
    lcd.print(work_buffer);

    delay(20);

    lcd.setCursor (0, 2);
    sprintf(work_buffer, "Wasser:  %5d l\0", wasserstand);
    lcd.print(work_buffer);

    LCD_progress_bar (4, wasserstand, 0, 100);
    new_data = false;
  }
  client.loop();
  delay(100);
}

Vielleicht solltest du mal schauen, ob in tagesleistung wirklich das drin steht, was du erwartest.

Die Tagesleistung wird auf dem Raspberry korrekt im Dashboard ausgegeben. :cry:

Ich meine die Variable "tagesleistung" in deinem Programm, welches du hier gezeigt hast.
:smiling_imp: Nicht die Aufschrift einer Gießkanne in Australien. :smiling_imp:

Es gibt doch nur 2 Möglichkeiten!

  1. Entweder ist sprintf() kaputt
    2 oder in tagesleistung steht Schrott

Aber ok, wenn dir das zuviel Arbeit ist.....
(dann glaube ich nicht, dass du daran interessiert bist den Fehler zu finden)

Für was überhaupt der Umweg?
Mit dem Esp geht "lcd.prinf".

lcd.setCursor (0, 1);
    sprintf(work_buffer, "Tag:     %5d W\0", tagesleistung);
    lcd.print(work_buffer);


lcd.setCursor (0, 1);
lcd.printf("Tag:     %5d W", tagesleistung);

Gruß Fips

Das \0 ist da auch flüssiger als Wasser.
Überflüssig

combie:
Das \0 ist da auch flüssiger als Wasser.
Überflüssig

Stimmt!

Gruß Fips

combie:
Es gibt doch nur 2 Möglichkeiten!

  1. Entweder ist sprintf() kaputt
    2 oder in tagesleistung steht Schrott

Kann ich erst heute Abend an der richigen Hardware prüfen. Auf den Raspberry hatte ich aktuell Zugriff...

Derfips:
Für was überhaupt der Umweg?
Mit dem Esp geht "lcd.prinf".

lcd.setCursor (0, 1);

sprintf(work_buffer, "Tag:     %5d W\0", tagesleistung);
   lcd.print(work_buffer);

lcd.setCursor (0, 1);
lcd.printf("Tag:     %5d W", tagesleistung);

Wird heute Abend direkt getestet :slight_smile:

So, ich habe mal ein wenig getestet.

Sobald die Tagesleistung vierstellig wird kommt hier Mist raus:

if (strcmp(topic, "garage/tagesleistung") == 0) {
    tagesleistung = (inStr.toInt());
Serial.println(tagesleistung);
  }

hier wird dann der String von aktuelle_leistung an die Tagesleistung gehängt.... Nun die Frage warum das so ist, und warum ab vierstelligen werten?

Tja...

Kontrollausgaben kannst du ja machen...
Dann mache weiter so!

Jetzt schaue dir doch bitte den Datenfluss an...
Und laufe ihn rückwärts ab, irgendwo wird sich der Fehler ja wohl eingeschlichen haben.

x20011:
So, ich habe mal ein wenig getestet.

Sobald die Tagesleistung vierstellig wird kommt hier Mist raus:

if (strcmp(topic, "garage/tagesleistung") == 0) {

tagesleistung = (inStr.toInt());
Serial.println(tagesleistung);
  }



hier wird dann der String von aktuelle_leistung an die Tagesleistung gehängt.... **Nun die Frage warum das so ist**, und warum ab vierstelligen werten?

Weil in inStr Scheibenhonigzahlen stehen?

Oder ist dein nächster Thread "String::toInt() funktioniert nicht!"?

Siehe gigo.

Wenn man jedem Topic einen eigenen String spendiert funkioniert es....

void callback(char* topic, byte* payload, unsigned int length) {

  payload[length] = '\0';

  if (strcmp(topic, "garage/aktuelle_leistung") == 0) {
    String inStr_aktuelle_leistung = (char *)payload;
    aktuelle_leistung = (inStr_aktuelle_leistung.toInt());
  }

  if (strcmp(topic, "garage/tagesleistung") == 0) {
    String inStr_tagesleistung = (char *)payload;
    tagesleistung = (inStr_tagesleistung.toInt());
  }

  if (strcmp(topic, "garten/wasserstand") == 0) {
    String inStr_wasserstand = (char *)payload;
    wasserstand = (inStr_wasserstand.toInt());
  }
  new_data = true;
}