Go Down

Topic: Serial Daten empfangen in Schleife (Read 3149 times) previous topic - next topic

SkobyMobil

Hallo,
hier bin ich mir nicht sicher

Serial.print('\t');

das ist doch gesendetes ASCII, 92 und 116

muß das nicht

Serial.write('\t');

sein?
Gruß und Spaß
Andreas
die zweite Maus bekommt den Speck...

Whandall

#16
May 18, 2017, 03:23 pm Last Edit: May 18, 2017, 03:26 pm by Whandall
Ich würde an deiner Stelle den Empfang der Zeile von der Analyse der Zeile trennen.

Das macht beide Routinen einfacher und es gibt keine Notwendigkeit für whiles mehr.

Man sollte blockierende Routinen meiden, nicht neue konstruieren.
Ah, this is obviously some strange usage of the word 'safe' that I wasn't previously aware of. (D.Adams)

Hannes54

Danke!
Hab jetzt Alles rausgelöscht was die Analyse angeht.
Sender:
Code: [Select]
// Sender
#define Anz 4 // Anzahl der zu sendenden Daten
#include <SoftwareSerial.h>
SoftwareSerial TELSerial(10, 11); // RX, TX Telemetrie
int pruefsumme;
float Daten[Anz];
byte Status = 1;
union data_u {
  struct  {
    int wert[Anz];
  };
  byte bytes[10];
};
data_u data;
void setup() {
  Serial.begin(9600);
  TELSerial.begin(9600);
  data.wert[0] = 22;
  Serial.println(data.wert[0]);
}
void loop() {
  delay(1000);
  //******************Messwerte*********************************
  Daten[0] = 1;  // Testwerte
  Daten[1] = 2;
  Daten[2] = 3;
  Daten[3] = 4;
  pruefsumme = 0;
  //*********************Seriell schreiben**********************

  for (int j = 0; j < Anz  ; j++) {
    data.wert[j] = int ((Daten[j] * 10) + .5) ;
    Serial.print(data.wert[j]);
    Serial.print('\t');
    TELSerial.print(data.wert[j]);
    TELSerial.print('\t');
  }
  Serial.println(" ");
  TELSerial.println(" ");
}

Empfänger:
Code: [Select]
// Empfänger
#define PUFFERLAENGE 10
#define anz 4 // Anzahl der zu empfangenden Messwerte
char inString[PUFFERLAENGE];
int index;
void setup() {
  Serial.begin(9600);
  Serial2.begin(9600);
  Serial3.begin(9600);
}
void loop() {
  while (Serial3.available() > 0) {
    int inChar = Serial3.read();
    for (int j = 0; j < anz  ; j++) {
      inString[index] = inChar;
      if (index < 10) index++;
      if (inChar == '\t'){
        inString[index] = '\0';
      Serial.print(inString);
      index = 0;}
    }
  }
}


Ich sende : 10 20 30 40 und empfange (lt. ser. Mon.): 11110000 22220000 33330000 44440000

Gruß

Hannes

Whandall

#18
May 18, 2017, 04:17 pm Last Edit: May 18, 2017, 04:36 pm by Whandall
Wozu willst du den zweiten int Array einsetzen?

Warum druckst du die Werte nicht einfach?

Code: [Select]
//*********************Seriell schreiben**********************
  for (int j = 0; j < Anz  ; j++) {
    int value = (int) (Daten[j] * 10 + .5);
    Serial.print(value);
    TELSerial.print(value);
    if (j != Anz - 1) {
      Serial.write('\t');
      TELSerial.write('\t');
    }
  }
  Serial.println();
  TELSerial.println();
}

Hab jetzt Alles rausgelöscht was die Analyse angeht.
Empfänger:
Code: [Select]
 while (Serial3.available() > 0) {
    int inChar = Serial3.read();
    for (int j = 0; j < anz  ; j++) {
      inString[index] = inChar;
      if (index < 10) index++;
      if (inChar == '\t'){
        inString[index] = '\0';
      Serial.print(inString);
      index = 0;}
    }
  }

Das Gefummel mit den Tabs ist dann bitte was?
Und was soll das for an der Stelle?
Was hat das mit dem Empfang einer Zeile (unbekannten Inhalts) zu tun?

Und überlasse loop die Iteration, mach aus dem while ein if.
Ist einfacher, kürzer und gibt dem Rest des Programms mehr Luft.
Ah, this is obviously some strange usage of the word 'safe' that I wasn't previously aware of. (D.Adams)

Hannes54

Ich habe n x Messwerte ( float) die ich übertragen muss.
Deshalb mache ich daraus (x10) int . Auf der Empfangsseite wird ein "," eingefügt.
Eine Kommastelle reicht aus.

Der Hintergrund des Ganzen:
Ich habe einen Code, dankenswerter Weise von "Agmue", bekommen der genau mein Vorhaben umsetzt.
Es werden die Messwerte richtig übertragen und das mit den Prüfsummen funktioniert auch perfekt.

Nun wollte ich, zur Synchronisation, noch ein "Startzeichen" (z.B.">") mit einbauen und noch ein Statusbyte übertragen. Ich bastel da schon lange dran herum und (außer Frust) kommt da nix Gescheites bei raus. Je mehr ich im WWW suche um so weniger scheine ich zu verstehen....
Viele Programmieraufgaben konnte ich schon lösen aber diese serielle Übertragung schafft mich noch irgendwann.
Auch das "Kochbuch" was ich mittlerweile hier habe hilft mir nicht weiter.

Da ich ähnliche Fragen schon in meinem anderen Thread (Dampfschiff) gestellt habe hoffe ich sehr kein Crossposting gemacht zu haben.

Gruß

Hannes





Whandall

Ich kann mich nur widerholen.

Trenne Empfang von Verarbeitung.

Empfang passiert, sobald ein Zeichen (das ist echt selten, mach dir das klar) eintrifft.

Verarbeitung passiert, sobald eine vollständige Zeile eingetroffen ist.

So wie du das machst, hoffst du die Emfangsroutine nicht zu verlassen bis das Datagramm
vollständig übertragen wurde, sonst funktioniert es nicht.

Das könnte man jetzt mit delay() humpelnd zum Funktionieren bringen, aber warum?

Sammle Zeichen wenn welche zur Verfügung stehen.
War das emfangene Zeichen der Zeilentrenner,
ruf die Verarbeitungsroutine mit dem Null-terminierten Buffer auf.

CR und LF treten zumeist gemeinsam auf, such dir einen davon aus und ignoriere den anderen völlig.
Ah, this is obviously some strange usage of the word 'safe' that I wasn't previously aware of. (D.Adams)

jurs

Hallo Gemeinde,

ich sende 4 Messwerte über die serielle Schnittstelle von einem Nano zu einem Mega.
Die einzelnen Werte sind durch '\t' getrennt. Einzeln funktioniert das prima.
ja, der Code eines Programms funktioniert wie ein Mülltonne, und zwar so:

Wenn der Programmierer Müll reinpackt, dann kommt auch wieder Müll heraus.


Googele mal nach "GIGO-Prinzip".

Das ist das in Deinem Fall zutreffende Prinzip: garbage in - garbage out

Genau wie bei einer Mülltonne.

Du solltest Deinen Arduino vielleicht besser nicht als Mülleimer zweckentfremden und ihn mit Müll füttern.

Zum Beispiel ist diese Zeile Müll:
Code: [Select]
if (inChar = '\t')

Einerseits sieht die Zeile so aus als wenn Du eine if-Abfrage machen möchtest.

Anderrseitsteckt da eine ZUWEISUNG drin, die bei C/C++ mit dem einfachen Gleichheitszeichen gemacht wird:
inChar = '\t'
Nachdem das ausgeführt wurde, enthält die Variable inChar ein Tabulatorzeichen.

Für die Abfrage auf Gleichheit müßtest Du stattdessen das doppelte Gleichheitszeichen verwenden
Code: [Select]
if (inChar == '\t')

Machst Du aber nicht.

Im übrigen dürfte aber die while-Schleife innerhalb der loop() Funktion auch bereits Müll sein, schon das Konzept, das Du Dir ausgedacht hast, dürfte für Dein Vorhaben wohl nicht funktionieren, neben einer handwerklich schlechten Ausführung z.B. Verwechslung von Zuweisung und Prüfung auf Gleichheit, führt das ganz natürlich zu Müll.

Müll ergibt wieder Müll.


Hannes54

Danke.
Das muss ich jetzt mal verdauen.

Auf die Gefahr hin mich unbeliebt zu machen: Gibt es dazu ein Beispiel?
Gesucht habe ich wirklich reichlich aber entweder bin ich zum Suchen zu blöd oder ich konnte die Suchergebnisse nicht umsetzen.

Gruß

Hannes

combie

#23
May 18, 2017, 05:07 pm Last Edit: May 18, 2017, 05:10 pm by combie
Quote
Ich sende : 10 20 30 40 und empfange (lt. ser. Mon.): 11110000 22220000 33330000 44440000
...
Da ist noch irgendwo "der Wurm drin"
Ja!
Du ließt ein Byte/Zeichen und schreibst es dann 4 mal in den Buffer.
Warum tust du das? (wenn du das doch gar nicht willst)
Es ist offensichtlich, dass uns die Umstände alleine nicht glücklich oder unglücklich machen.
Es ist die Art unserer Reaktion darauf, die unsere Gefühle bestimmt.

Whandall

Serial für Debug mit 250000 Baud, Serial2 und Serial3 Loopback mit 9600 Baud.

Code: [Select]
// Empfänger
#define PUFFERLAENGE 32
#define anz 4

const byte TAB = 9;
const byte LF = 10;
const byte CR = 13;

char inString[PUFFERLAENGE];

int values[anz + 1] = { 91, 92, 93, 94, 95 };

byte index;

void setup() {
  Serial.begin(250000);
  Serial2.begin(9600);
  Serial3.begin(9600);
  Serial.println(F("Test"));
  Serial2.println(F("10\t20\t30\t40\t0"));
}

void loop() {
  static unsigned long lastPrint;
  if (millis() - lastPrint >= 5000) {
    lastPrint = millis();
    values[0]++;
    for (byte i = 0; i < anz + 1; i++) {
      Serial2.print(values[i]);
      if (i != anz) {
        Serial2.write(TAB);
      }
    }
    Serial2.println();
  }

  if (Serial3.available()) {
    byte inChar = Serial3.read();
    if (inChar != CR) {
      if (inChar == LF) {
        inString[index] = 0;
        processIt(inString);
        index = 0;
      } else if (index < PUFFERLAENGE - 1) {
        inString[index++] = inChar;
      }
    }
  }
}

void processIt(char * ptr) {
  for (byte i = 0; i <= anz; i++) {
    values[i] = strtol(ptr, &ptr, 10);
    if (*ptr++ != TAB) {
      break;
    }
  }
  Serial.print(F("parsed: "));
  for (byte i = 0; i <= anz; i++) {
    Serial.print(values[i]);
    if (i != anz) {
      Serial.print(F(", "));
    }
  }
  Serial.println();
}
Code: [Select]
Test
parsed: 10, 20, 30, 40, 0
parsed: 11, 20, 30, 40, 0
parsed: 12, 20, 30, 40, 0
parsed: 13, 20, 30, 40, 0
parsed: 14, 20, 30, 40, 0
parsed: 15, 20, 30, 40, 0
parsed: 16, 20, 30, 40, 0
Ah, this is obviously some strange usage of the word 'safe' that I wasn't previously aware of. (D.Adams)

jurs

#25
May 18, 2017, 06:16 pm Last Edit: May 18, 2017, 06:20 pm by jurs
Danke.
Das muss ich jetzt mal verdauen.

Auf die Gefahr hin mich unbeliebt zu machen: Gibt es dazu ein Beispiel?
Gesucht habe ich wirklich reichlich aber entweder bin ich zum Suchen zu blöd oder ich konnte die Suchergebnisse nicht umsetzen.
kennst Du Serial Input Basics?

Im internationalen Teil des Forums haben sich mal einige die Mühe gemacht, etwas zusammenzuschreiben, weil solche Fragen zum seriellen Empfangen so oft kommen.
Robin2 hat es mal zusammengefaßt.

Vielleicht siehst Du Dir insbesondere das an:
Example 2 - Receive with an end-marker





SkobyMobil

Hallo Hannes,
Du bist voll in die C&P Falle gelaufen... aber hinterher sind sie alle schlauer.
jurs und michael habe ich auch schon kennengelernt. Ich folge eigentlich Ihrem Rat.
Klobbe Deine Sende/Empfangs Sketche in die Tonne, und fange noch einmal von vorne an.
Und höre auf nach Beispielen zu fragen. Schreibe Dir selbst etwas.

In den letzten 3 Wochen ist die serielle Kommunikation hier durchgekaut worden. Selbst ich komme jetzt damit
klar. Das schaffst Du doch auch.
Einige int-Werte zu übertragen ist doch wirklich nicht so schwer.
Wenn Du das (und nicht mehr) fehlerfrei hinbekommen hast- dann kannst Du mit Prüfsumme und Bit&Byte
Schiebereien anfangen.
Gruß und Spaß
Andreas
die zweite Maus bekommt den Speck...

Hallo Andreas,

Quote
Du bist voll in die C&P Falle gelaufen... aber hinterher sind sie alle schlauer.
da hast Du Recht.

Es sah so einfach aus. Wenn ich (aktuell) 5 int übertrage und an mein Nextion schicke ist Alles bestens. Sogar mit Prüfsummen. Also dachte ich mir: Es wird einfach das um eine Startkennung zur Synchronisierung und ein separates Status-Byte zu erweitern.
Denkste ! Mittlerweile habe ich mich echt "dumm-gesucht". Brauch mal eine Pause und werde dann ganz neu anfangen.
Schade um Zeit und Nerven...


Gruß

Hannes

Hannes54

#28
May 18, 2017, 10:46 pm Last Edit: May 18, 2017, 10:49 pm by Hannes54
Scheinbar habe ich das Forum "über-beansprucht" :)

Mein Nick ist verschwunden... Ich bin jetzt ein Newbie (ist ja richtig) mit 29 Beiträgen ??

SkobyMobil

Hallo,
jurs sein Avatar ist auch wech. Wahrscheinlich ist er in die Tonne gehüpft. :smiley-kiss:
Gruß und Spaß
Andreas
die zweite Maus bekommt den Speck...

Go Up