Falsche Ausgabe, komm nicht drauf warum

Hi,

hab hier einen von jurs umgebauten Sketch, der mir nicht das zurückgibt, was ich gerne hätte.

Wenn ich dem Sketch z.B. seriell den String "d000056" sende, bekomme ich nicht die Zahl 56 zurück.

Das Ziel ist es nämlich lediglich das 'd' und sämtliche Nuller vor der eigentlich zu extrahierenden folgenden Zahl abzuschneiden.

Leider komme ich nicht darauf, was das Problem sein könnte.

Zudem gefällt mir folgende Zeile nicht:

if (i == 9) i = 0;

Da gibt es was mit "sizeof (commandbuffer)", ich komme aber nicht mehr drauf wie es geht.

Gruß Chris

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

void loop()
{
  lesevorgang();
}

void lesevorgang()
{
  static char commandbuffer[10];
  static char c;
  static int i = 0;
  if (Serial.available())
  {
    c = Serial.read();
    commandbuffer[i] = c;
    i++;
    if (i == 9) i = 0;
    if (c == 10)  // Linefeed
    {
      Serial.println(getIntFromString (commandbuffer, 1)); // Ausgabe der ermittelten Zahl
      i = 0;
      memset(commandbuffer, 0, sizeof(commandbuffer)); // Puffer mit Nullbytes fuellen und dadurch loeschen
    }
  }
}

int getIntFromString (char *stringWithInt, byte num)

{
  char *tail;  // Zeiger
  while (num > 0)
  {
    num--; // Nicht-Zahlen überspringen
    while ((!isdigit (*stringWithInt)) && (*stringWithInt != 0)) stringWithInt++;
    tail = stringWithInt;  // Zahlen finden
    while ((isdigit(*tail)) && (*tail != 0)) tail++;
    if (num > 0) stringWithInt = tail;
  }
  return (strtol(stringWithInt, &tail, 0));
}
void setup() {
  Serial.begin(9600);
}

void loop() {
  lesevorgang();
}

void lesevorgang() {
  static char commandbuffer[10];
  static int i = 0;
  char c;
  if (Serial.available()) {
    c = Serial.read();
    commandbuffer[i] = c;
    if (c == 10) {
      commandbuffer[i] = 0;
      Serial.println(atoi(commandbuffer + 1));
      i = 0;
    } else if (c == 13) { // cr ignorieren
    } else if (++i == sizeof(commandbuffer) - 1) {
      i = 0;
    }
  }
}

Danke, doch das scheint das Problem nicht zu lösen. :confused:

Seriell senden tu ich übrigens immer mit abschließendem CR und LF.

Gruß Chris

Hast du es schonmal mit Serial.parseInt() probiert?
Das scheint mir einfacher zu sein.

void lesevorgang() {
    if (Serial.available()) {
      int val = Serial.parseInt();
      Serial.println(val);
  }
}

Ich fand einen Fehler im Lesevorgang und habe ihn behoben.

Komischerweise bekomme ich, wenn ich z.B. "d07" schicke eine 7 zurück.
Schicke ich jedoch "d08" bekomme ich eine 0 als Ergebnis.

Das verstehe ich nicht.

Gruß Chris

Hier der aktualisierte Code:

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

void loop()
{
  lesevorgang();
}

void lesevorgang()
{
  static char commandbuffer[10];
  static char c;
  static int i = 0;
  if (Serial.available())
  {
    c = Serial.read();
    commandbuffer[i] = c;
    i++;
    if (i == sizeof(commandbuffer)) i = 0;
    if (c == 10)  // Linefeed
    {
      Serial.println(getIntFromString (commandbuffer, 1)); // Ausgabe der ermittelten Zahl
      i = 0;
      memset(commandbuffer, 0, sizeof(commandbuffer)); // Puffer mit Nullbytes fuellen und dadurch loeschen
    }
  }
}

int getIntFromString (char *stringWithInt, byte num)

{
  char *tail;  // Zeiger
  while (num > 0)
  {
    num--; // Nicht-Zahlen überspringen
    while ((!isdigit (*stringWithInt)) && (*stringWithInt != 0)) stringWithInt++;
    tail = stringWithInt;  // Zahlen finden
    while ((isdigit(*tail)) && (*tail != 0)) tail++;
    if (num > 0) stringWithInt = tail;
  }
  return (strtol(stringWithInt, &tail, 0));
}

Das verstehe ich nicht.

Dann mache dich bitte mit dem Oktalsystem vertraut.

Chris72622:
Danke, doch das scheint das Problem nicht zu lösen. :confused:

Seriell senden tu ich übrigens immer mit abschließendem CR und LF.

Das ist natürlich quatsch, weil ich Kode teste, ehe ich ihn poste.

Deine Fehler liegen in dem Kode, der atoi() versucht nachzustellen.

Nimm

return strtol(stringWithInt, NULL, 10);

combie:
Dann mache dich bitte mit dem Oktalsystem vertraut.

Whandall:
Deine Fehler liegen in dem Kode, der atoi() versucht nachzustellen.

Danke für die Hinweise.

Gruß Chris

Hi,

anbei die Lösung für die Nachwelt. Danke nochmals allen geduldigen Mitlesern.

Sollte es bzgl. der Codegröße noch Einsparpotenzial geben, bitte! :slight_smile:

Gruß Chris

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

void loop()
{
  lesevorgang();
}

void lesevorgang()
{
  static char commandbuffer[10];
  static char c;
  static int i = 0;
  if (Serial.available())
  {
    c = Serial.read();
    if (c != '\r')
    {
      commandbuffer[i] = c;
      i++;
      if (i == sizeof(commandbuffer)) i = 0;
    }
    if (c == 10)  // Linefeed
    {
      // Serial.print(commandbuffer);
      Serial.println(getIntFromString (commandbuffer, 1)); // Ausgabe der ermittelten Zahl
      i = 0;
      memset(commandbuffer, 0, sizeof(commandbuffer)); // Puffer mit Nullbytes fuellen und dadurch loeschen
    }
  }
}

unsigned long getIntFromString (char *stringWithInt, byte num)

{
  char *tail;  // Zeiger
  while (num > 0)
  {
    num--; // Nicht-Zahlen überspringen
    while ((!isdigit (*stringWithInt)) && (*stringWithInt != 0)) stringWithInt++;
    tail = stringWithInt;  // Zahlen finden
    while ((isdigit(*tail)) && (*tail != 0)) tail++;
    if (num > 0) stringWithInt = tail;
  }
  return strtoul(stringWithInt, NULL, 10);
}

Also bei mir funktioniert das nicht.
(Mega2560; IDE 1.8.1; Serieller Monitor)

Wogegen das hier funktioniert:

void loop() {
  if (Serial.available()) {
    int val = Serial.parseInt();
    Serial.println(val);
  }
}

Nur so Ideen:

In getIntFromString lese ich "Nicht-Zahlen überspringen". Das könntest Du auch in lesevorgang machen (ungetestet):

void lesevorgang()
{
  static char commandbuffer[10];
  static char c;
  static int i = 0;
  if (Serial.available())
  {
    c = Serial.read();
    switch (c)
    {
      case '0' ... '9':
        commandbuffer[i] = c;
        i++;
        if (i == sizeof(commandbuffer)) i = 0;
        break;
      case '\n':
        // Serial.print(commandbuffer);
        Serial.println(getIntFromString (commandbuffer, 1)); // Ausgabe der ermittelten Zahl
        i = 0;
        memset(commandbuffer, 0, sizeof(commandbuffer)); // Puffer mit Nullbytes fuellen und dadurch loeschen
        break;
    }
  }
}

Durch die positive Abfrage kommt '\n' nicht in den Puffer.

Chris72622:
Sollte es bzgl. der Codegröße noch Einsparpotenzial geben, bitte! :slight_smile:

Dein Kode

Der Sketch verwendet 2.770 Bytes (1%) des Programmspeicherplatzes. Das Maximum sind 253.952 Bytes.
Globale Variablen verwenden 201 Bytes (2%) des dynamischen Speichers, 7.991 Bytes für lokale Variablen verbleiben. Das Maximum sind 8.192 Bytes.

mein Kode

Der Sketch verwendet 2.170 Bytes (0%) des Programmspeicherplatzes. Das Maximum sind 253.952 Bytes.
Globale Variablen verwenden 198 Bytes (2%) des dynamischen Speichers, 7.994 Bytes für lokale Variablen verbleiben. Das Maximum sind 8.192 Bytes.

Meinst Du mit "mein Kode" das hier?

void lesevorgang()
{
  static char commandbuffer[10];
  static int i = 0;
  char c;
  if (Serial.available()) {
    c = Serial.read();
    commandbuffer[i] = c;
    if (c == 10) {
      commandbuffer[i] = 0;
      Serial.println(getIntFromString (atoi(commandbuffer + 1), 1));
      i = 0;
    } else if (c == 13) { // cr ignorieren
    } else if (++i == sizeof(commandbuffer) - 1) {
      i = 0;
    }
  }
}

Falls ja funktioniert das bei mir so nicht.

Gruß Chris

Bei mir schon.

P.S.

Chris72622:
Falls ja funktioniert das bei mir so nicht.

[SARCASM]

Tolle und unglaublich detailierte Fehlerbeschreibung.

[/SARCASM]

Die serielle Eingabe meinerseits führt bei dem von mir angegebenen Code nicht zur gewünschten Ausgabe.

Gruß Chris

Chris72622:
Die serielle Eingabe meinerseits führt bei dem von mir angegebenen Code nicht zur gewünschten Ausgabe.

Das ist genauso nichtssagend.

Wenn ich die Eingabe d000056 (Zeilenende: Sowohl NL als auch CR, 9600 Baud) mit dem Knopf Senden sende,
gibt das Programm wunschgemäß 56 aus.

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

void loop() {
  lesevorgang();
}

void lesevorgang() {
  static char commandbuffer[10];
  static int i = 0;
  char c;
  if (Serial.available()) {
    c = Serial.read();
    commandbuffer[i] = c;
    if (c == 10) {
      commandbuffer[i] = 0;
      Serial.println(atoi(commandbuffer + 1));
      i = 0;
    } else if (c == 13) { // cr ignorieren
    } else if (++i == sizeof(commandbuffer) - 1) {
      i = 0;
    }
  }
}
56

Ich glaube, ich hab das Problem gefunden. Atoi funktioniert nur mit Integer, oder?

Ich benötige in diesem Fall die Rückgabe (noch) größerer Zahlen.

Gruß Chris

Atoi funktioniert nur mit Integer, oder?

Es kann doch nicht sein, dass du nach weit über 1000 Postings immer noch nicht in die Doku schaust...
Wie kann ich dir dabei helfen, dir solche Fragen selber zu beantworten?

Ich benötige in diesem Fall die Rückgabe (noch) größerer Zahlen

Es kann doch nicht sein, dass du nach weit über 1000 Postings immer noch nicht in die Doku schaust...
Wie kann ich dir dabei helfen, dir solche Fragen selber zu beantworten?

Immer noch keine konkrete Angabe.

So sollte es auch mit großen Zahlen (bis ca 2100000000) gehen.

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

void loop() {
  lesevorgang();
}

void lesevorgang() {
  static char commandbuffer[20];
  static int i = 0;
  char c;
  if (Serial.available()) {
    c = Serial.read();
    commandbuffer[i] = c;
    if (c == 10) {
      commandbuffer[i] = 0;
      Serial.println(strtol(commandbuffer + 1, NULL, 10));
      i = 0;
    } else if (c == 13) { // cr ignorieren
    } else if (++i == sizeof(commandbuffer) - 1) {
      i = 0;
    }
  }
}

Eingabe von d0001234567899 ergibt

1234567899