int Array seriell versenden und verarbeiten

Hallo zusammen,

ich verwende einen Arduino Mega zusammen mit ESP8266-12E und möchte ein Array mit 10 int Werten vom Mega an den ESP senden und anschließend die Einzelwerte in einer MYSQL DB speichern, soweit ist es aber noch nicht.

Ich greife hier nochmal folgenden Thread auf
https://forum.arduino.cc/index.php?topic=603522.0 #3 letzte Variante

um die Einzelwerte im Array zu formatieren.

/*
  Anstatt jeden Wert einzeln zu übertragen, würde ich gerne alle Daten in einem Array ablegen und versenden.
  http://forum.arduino.cc/index.php?topic=603522.msg4096329#new
  beigesteuert von noiasca
*/

int payload [] = {1, 2, 3, 5, 7, 11, 13};  // was wollen wir übertragen

const char *prefixMessage = "?";           // Am Anfang einer neuen Nachricht
const char *prefixValue = "";              // vor einem neuem Wert
const char *postfixValue = ";";            // nach einem neuem Wert
const char *postfixMessage = "\n";         // Am Ende der Nachricht

void transmitPayloadVariant0()             // Einfache Übertragung
{
  for (auto &current : payload) {          // for each für arme
    Serial.print(current);
  }
}

void transmitPayloadVariant1()             // Übertragung mit prefix/postfix
{
  Serial.print(prefixMessage);
  for (auto &current : payload) {          // for each für arme
    Serial.print(prefixValue);
    Serial.print(current);
    Serial.print(postfixValue);
  }
  Serial.print(postfixMessage);
}

void transmitPayload()                      // reduzierung des ersten prefix/letzten postfix
{
  uint16_t toTransmit = sizeof(payload) / sizeof(payload[0]);
  Serial.print(prefixMessage);
  for (uint16_t current = 0; current<toTransmit; current++) { 
    if (!current) Serial.print(prefixValue);                 // first value gets no prefix
    Serial.print(current);
    if (current!=toTransmit-1) Serial.print(postfixValue);   // last value gets no postfix
  }
  Serial.print(postfixMessage);
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
}

void loop() {
  // put your main code here, to run repeatedly:
  transmitPayload();
  delay(3000); // dirty delay
}

Meine Fragen hierzu:

  1. Funktion transmitPayload() liefert mir im seriellen Monitor lediglich die Zählwerte der Schleife und nicht den Inhalt des Arrays, während die abgespeckte Variante transmitPayloadVariant1() aus current die korrekten Arraywerte liefert - warum?
  2. Wenn ich das int Array über Serial1 an den ESP übergebe, kommen dann dort int Werte an oder ASCII Werte?
  3. Wie könnte man das Einlesen wiederum in ein int Array auf dem ESP realisieren?
  1. Funktion transmitPayload() liefert mir im seriellen Monitor lediglich die Zählwerte der Schleife und nicht den Inhalt des Arrays, während die abgespeckte Variante transmitPayloadVariant1() aus current die korrekten Arraywerte liefert - warum?

Weil du das so programmiert hast.

Wenn du Arrayelemente ausgeben möchtest, dann solltest du dazu auch in das Array schauen!
transmitPayloadVariant1() tut das, transmitPayloadVariant() tut das nicht

Verwende eine dieser Varianten.
(alle gleichwertig)

Serial.print(current[payload]);

Serial.print(payload[current]);

Serial.print(*(current+payload));

Serial.print(*(payload+current));

Du hast vollkommen recht …

Kannst du mir das mal erklären

for (auto &current : payload) // for each für arme

Was ist das für eine schreibweise?

dr_nobody:
Was ist das für eine schreibweise?

Range-based for loop

Aah - wenn man den Fachausdruck dazu weiß, findet man auch was :slight_smile:

Zum Einlesen des Arrays hatte ich mal sowas versucht.

void loop()
{
if( Serial.available()) {
for(fieldIndex = 0; fieldIndex < 10; fieldIndex ++)
{
values[fieldIndex] = Serial.parseInt(); // Numerischen Wert einlesen
}
Serial.print( fieldIndex);
Serial.println(" Felder empfangen:");
for(int i=0; i < fieldIndex; i++)
{
Serial.println(values[i]);
}
fieldIndex = 0; // und von vorn anfangen
}
}

Der Mega printet testweise alle 15 sek. ein vordefiniertes Array mit int Werten, jedoch verarbeitet der ESP nur einmal und dann nicht mehr, obwohl doch die loop ständig auf neue Werte wartet?

Wie ich gestern erfahren/lesen musste, ist das überhaupt kein Problem, einen seriellen Datenstrom zu parsen.
Ich, persönlich sehe das etwas anders.

Suchworte: Parser parsen Protokoll

Der Mega printet testweise alle 15 sek. ein vordefiniertes Array mit int Werten, jedoch verarbeitet der ESP nur einmal und dann nicht mehr, obwohl doch die loop ständig auf neue Werte wartet?

Die 15 ? Sekunden könnten mit dem Timeout von Serial.parseInt() zusammenhängen. Was macht dein ESP, wenn gar nichts kommt (bzw. keine 10 Zahlen) ?

dr_nobody:
jedoch verarbeitet der ESP nur einmal und dann nicht mehr,

falsche Lese Strategie.

Der ESP soll im loop nur die Daten in einen Buffer zusammensammeln, erst wenn das Zeilen-Ende Zeichen kommt, soll er den gelesenen Input vearbeiten.

arbeite mal das hier durch Serial Input Basic: Serial Input Basics - updated - Introductory Tutorials - Arduino Forum

Danke schonmal für die Tipps.

Immer noch unklar: Kommen jetzt die Werte aus dem int Array beim ESP als int oder ASCII Werte an? In einschlägiger Literatur behauptet man, dass die int Werte ankommen.

michael_x:
Die 15 ? Sekunden könnten mit dem Timeout von Serial.parseInt() zusammenhängen. Was macht dein ESP, wenn gar nichts kommt (bzw. keine 10 Zahlen) ?

Der macht in der Zeit gar nichts. parseInt wird doch beim Eingang neuer Daten auch neu angestossen, oder? Wie kann es da zu einem timeout kommen?

Wann wird Serial.available() true?
Bei schon 1 Zeichen!

Wieviel Zeichen wird parseInt() benötigen?
bzw. wann endet parseInt()?

combie:
Wann wird Serial.available() true?
Bei schon 1 Zeichen!

Wieviel Zeichen wird parseInt() benötigen?
bzw. wann endet parseInt()?

Welchen Schluss soll ich daraus ziehen?

Welchen Schluss soll ich daraus ziehen?

Dass deine bisherige Methode, den seriellen Datenstrom zu parsen, unzureichend ist.

dr_nobody:
Der macht in der Zeit gar nichts. parseInt wird doch beim Eingang neuer Daten auch neu angestossen, oder? Wie kann es da zu einem timeout kommen?

parseInt() blockiert solange bis die Timeout Zeit abgelaufen ist oder ein Zeichen kommt das keine Ziffer ist

Das geht unter gewissen Umständen für sehr einfache Sachen. Aber generell ist es besser man hat ein Endzeichen und liest Zeichen für Zeichen an. Dann kann man dazwischen noch anderen Dinge tun

Außerdem ist man generell viel flexibler wenn man Einlesen und Parsen voneinander trennt

noiasca:
falsche Lese Strategie.

Der ESP soll im loop nur die Daten in einen Buffer zusammensammeln, erst wenn das Zeilen-Ende Zeichen kommt, soll er den gelesenen Input vearbeiten.

arbeite mal das hier durch Serial Input Basic: Serial Input Basics - updated - Introductory Tutorials - Arduino Forum

Der Beitrag Serial Input Basic ist sehr interessant, jedoch findet sich auch hier kein Beispiel um ein reines int Array zu parsen. Leider hilft mir auch Bsp 5 da nicht weiter, dazu sind meine Fähigkeiten zu eingeschränkt.

Nach intensiver Suche nach einer Lösung und erfolglosen Selbstversuchen komme ich leider nicht weiter. Vielmehr musste ich feststellen, dass es zig Beiträge und Fragen zu diesem Problem gibt, jedoch niemand jemals eine Lösung zu diesem Problem gepostet hat (egal, ob jetzt mit Hilfe oder in Eigenarbeit).

Sollte jemand doch noch irgend einen Link zur Lösung dieses Problems haben oder selbst einen hilfreichen Beitrag beisteuern können, der mein Problem löst, spendiere ich eine Kiste Bier, nicht virtuell, sondern real.

jedoch niemand jemals eine Lösung zu diesem Problem gepostet hat (egal, ob jetzt mit Hilfe oder in Eigenarbeit).

Ach, ich denke, die meisten schämen sich hinterher, weil es so einfach war, ins Handbuch zu schauen, sscanf() oder strtok() und atoi() zu finden, und dann anzuwenden.

Aber es gibt auch viele, schätze ich mal, die sind sich zu fein, um in die Dokumentationen zu schauen, die Sprache zu lernen, welche sie verwenden, usw...

Ich weiß es ja auch nicht... wieso das so ist.... wundere mich nur darüber....

Selbst das händisch zu bauen, mit aller primitivsten Mitteln?
Ein jeder(?) Parser ist ein endlicher Automat!
Und die Automatentheorie, die könnte man sich schon so mal zwischendurch anschauen. Die braucht man sowieso dauernd.

dr_nobody:
Der Beitrag Serial Input Basic ist sehr interessant, jedoch findet sich auch hier kein Beispiel um ein reines int Array zu parsen. Leider hilft mir auch Bsp 5 da nicht weiter, dazu sind meine Fähigkeiten zu eingeschränkt.

dann sollst du an deinen Fähigkeiten arbeiten. das verlinkte HowTo ist stufenweise aufgebaut. Mach wirklich jedes Beispiel durch. Damit lernt man.

Soweit ich das sehe empfängt #5 auf der seriellen eingehende Daten und in der Funktion parseData() werden diese dann zerteilt. du willst offenbar keine Strings, schön, dann nimmst halt das Muster für integers:

strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
integerFromPC = atoi(strtokIndx); // convert this part to an integer