Go Down

Topic: Serielle Daten empfangen und umwandeln (Read 489 times) previous topic - next topic

e0mc2

Hallo

Ich versuche gerade mit einem Arduino serielle Daten von einem Messgerät einzulesen.
Am liebsten hätte ich die Daten in einer Variable, in der ich sie weiter verarbeiten kann (float?).
Irgend wie bekomme ich das aber nicht hin...

Hier fünf Beispiel-Datensätze:

-03-,   34901V,   105.71Vm/r/n
-04-,    7044V,   523.79Vm/r/n
-08-
-10-,    1417V,  2603.80Vm/r/n
-11-,    1466V,  2516.77Vm/r/n

In der dritten Zeile (-08-) gab es eine Fehlmessung.
Ich brauche immer die letzte Zahl, ohne die Einheit (Vm).

Gibts da anfängertaubliche HowTos wie ich die Daten zuerst komplett empfangen kann (vermutlich in einer char) und dann einen Teil davon weiterverarbeite?

Aktuell will ich die Werte auf einem LCD anzeigen lassen.
Später soll das alles noch auf einer SD-Karte gespeichert werden.

Gruß, e0mc2

combie

Evtl. sind diese beiden das richtige Werkzeug für dich.
strtoc()
atof()
Kluge Worte zu schreiben, ist schwer.
Schon ein einziger Buchstabendreher, kann alles urinieren.

noiasca

in diesem Tutorial geht es um den Empfang von Daten über die Serielle Schnittstelle und wie man das nicht blockierend macht.

https://forum.arduino.cc/index.php?topic=396450.0

Einfach mal die Beispiele durcharbeiten, dann noch mal 1 bis 3 ... dann klappt's


DE: Wie man Fragen postet:
1. was hat man (Sketch und Hardware)
2. was SOLL es machen
3. was macht es: IST (Fehlverhalten, Fehlermeldungen, Serial.Output ...)
4. Eine Frage stellen bzw. erklären was man erwartet

e0mc2

Hallo

Danke für die Tipps, ich werd mich da mal etwas einarbeiten und melde mich, wen ich fertig bin, oder nicht mehr weiter komme :-)

Gruß, e0mc2

agmue

#4
Jan 22, 2018, 06:51 pm Last Edit: Jan 23, 2018, 11:14 am by agmue
Ein paar Zeilen zum Ausprobieren:

Code: [Select]
// Quelle der Bibliothek: https://github.com/duinoWitchery/hd44780
#include <Wire.h>
#include <hd44780.h> // include hd44780 library header file
#include <hd44780ioClass/hd44780_I2Cexp.h> // i/o expander/backpack class
hd44780_I2Cexp lcd; // auto detect backpack and pin mappings
#define LCD_COLS 20
#define LCD_ROWS 4

const char begr[] = {","};

//char * strtok ( char * str, const char * delimiters );
const byte MESSAGE_LENGTH = 35;
char inputData[MESSAGE_LENGTH];

void setup() {
  Serial.begin(9600);
  Serial.println(F("\nAnfang"));
  Serial1.begin(9600);
  lcd.begin(LCD_COLS, LCD_ROWS);
  lcd.print("Messwert");
  for (byte j = 0; j < MESSAGE_LENGTH; j++)
  {
    inputData[j] = ' ';
  }
}

void loop() {
  if (Serial1.available() > 0)
  {
    char zeichen = Serial1.read();
    if (zeichen == '\n')
    {
      inputData[MESSAGE_LENGTH - 1] = '\0';
      Serial.println();
      Serial.println(inputData);
      Serial.print(inputData + 23);
      lcd.setCursor (0, 1);
      lcd.print(inputData + 23);
      for (byte j = 0; j < MESSAGE_LENGTH; j++)
      {
        inputData[j] = ' ';
      }
    } else {
      Serial.print(zeichen, HEX);
      Serial.print(' ');
      if (zeichen > 31)
      {
        for (byte j = 0; j < MESSAGE_LENGTH - 2; j++)
        {
          inputData[j] = inputData[j + 1];
        }
        inputData[MESSAGE_LENGTH - 2] = zeichen;
      }
    }
  }
}


e0mc2

Hallo

Ich hatte noch ein paar andere Sachen um die Ohren, deshalb hats etwas länger gedauert.
Aber hier mein Ergebniss.

Zum empfangen der Daten habe ich aus dem Link von noiasca das zweite Beispiel (Example 2 - Receive with an end-marker) verwendet.
Das klappt soweit auch super.

Beim Umwandeln hab ich etwas rumgespielt, und hab jetzt diese Lösung:

Die Daten werden vorher empfangen und in dem "char SerielleDaten[]" gespeichert.

Die "float Speed" wird auch global festgelegt.
 
Code: [Select]

void DatenUmrechnen()
{
    char Wert[9];                   // neuen Char[] erstellen
    Wert[0] = SerielleDaten[17];    // Die benötigten Buchstaben in das neue Char[] übernehmen
    Wert[1] = SerielleDaten[18];
    Wert[2] = SerielleDaten[19];
    Wert[3] = SerielleDaten[20];
    Wert[4] = SerielleDaten[21];
    Wert[5] = SerielleDaten[22];
    Wert[6] = SerielleDaten[23];
    Speed = atof(Wert);   // Wert in float Speed umwandeln
}


Das übernehmen der Buchstaben in den "char Wert[]" könnte ich noch über eine Schleife machen.
Bei mir funktioniert das so sehr gut, aber auch nur, weil meine Zahl immer genau an der gleichen Stelle in dem "char SerielleDaten[]" steht.
Wen die Zahlen weniger Stellen haben, ersetzt mein Messgerät durch führende Leerzeichen, die atof dann sauber wegschneidet.

Ich habe etwas mit strtok rumgespielt, hat aber nicht auf anhieb geklappt.

Grüße, e0mc2

michael_x

Wenn SerielleDaten[23] nicht sowieso schon das Endezeichen (0) von SerielleDaten ist, solltest du die lokale Variable durch  Wert[7] = 0; sauber abschliessen. Es ist nämlich undefiniert, was dort drin steht, und falls es zufällig ein Zeichen ist, das als Ziffer interpretiert werden kann, würde es das atof-Ergebnis verfälschen.

Ich will jetzt auch nicht gegen globale Variable schimpfen, aber wenn deine Funktion Datenumrechnen
so zu verwenden wäre:
   Speed = DatenUmrechnen(SerielleDaten+17);

könnte man gleich sehen, was es macht ;)

Go Up