Arduino Forum

International => Deutsch => Topic started by: TERWI on Apr 15, 2019, 12:51 pm

Title: Serial verschluckt Daten ?
Post by: TERWI on Apr 15, 2019, 12:51 pm
Szenario ist folgendes:
Auf dem PC hab ich ein selbstgebautes Proggie (Delphi), welches ein 16-Byte-Telegramm mit Start- und Endmarker an den Dino (Mega oder Uno) sendet. Je nach dem was im Telegramm steht, kann auch noch eine definierte Menge an Daten folgen.
Der Dino liest das (mit Serial.read), wertet aus und macht je nach Befehl erwas ....
Auf jeden Fall schickt er als eine Art Software-Handshake das gleiche Telegramm (leicht verändert/ergänzt) an den PC zur Kontrolle zurück.
Prinzipiell und auch tatsächlich funzt das super und ist auch recht fix & sicher, ABER.....

Problem:
Während der Testphase, als ich reichlich Serial.println zur Kontrolle drin hatte, lief das einwandfrei.
Nun hab ich das alles so weit auskommntiert, da unnötiger Transfer.
Plötzlich verschluckt der Dino/Serial einige Bytes - das Telegramm kommt zwar komplett zurück, aber nicht mit den erwarteten Werten - wie es mit Serial.println schon der Fall ist...
Es ist auch egal, mit welchem Speed initialisiert wird - bei 9600 kommen ebenso Fehler wie bei 57600.

Die Hautproutine "CMD_Check" wird jeweils in der Loop aufgerufen, sonst ist da im Moment nix weiter drin.
Nach viel Try & Error habe ich mal ein delay() in die Loop gepackt.
Mit einer Verzögerung von min. 20 klappt das dann wieder ....

Sehr eigenartig, kann ich mir nicht erklären.
Jemand eine Idee, warum ist da ein delay nötig ist ?
Title: Re: Serial verschluckt Daten ?
Post by: combie on Apr 15, 2019, 01:10 pm
Quote
Sehr eigenartig, kann ich mir nicht erklären.
Ich mir so auch nicht.


Quote
Jemand eine Idee, warum ist da ein delay nötig ist ?
Nööö...(ich nicht)

Aber ich sehe ja auch nicht, was du da falsch machst.
Title: Re: Serial verschluckt Daten ?
Post by: Tommy56 on Apr 15, 2019, 01:26 pm
Wie sollen wir ohne Deinen Sketch etwas Sinnvolles dazu sagen können?
Setze Deinen Code bitte in Codetags (</>-Button oben links im Forumseditor oder [*code] davor und [*/code] dahinter ohne *).

Gruß Tommy
Title: Re: Serial verschluckt Daten ?
Post by: TERWI on Apr 15, 2019, 02:04 pm
Denke nicht, dass ich was falsch mache.
Es funktioniert ja alles tadellos, sicher und reibungslos - Das Daten-Telegramm wird korrekt hin und zurück gesendet.
Allerdings nur, so lange ich meine Debug-Serial.println's (es müssen min.3 sein !) drinne lasse ODER ich in der Loop ein delay(20) setze.
Anderenfalls werden nur die ersten 5-8 von 16 Byte korrekt gelesen (und genau so falsch zurückgegeben)

Für mich sieht das so aus, als wenn der Dino/Serial "zu schnell für sich selbst" ist und einfach nur für irgendwas ne Pause braucht ?!
Hatte jetzt gehofft, dass hier ggf. irgendwas zeitproblematisches betreff (async Hardware-) Serial bekannt ist.

So eine Frage könnte man auch beantworten, wenn man den Code nicht kennt.
Klar, kann ich hier was posten - das ist allerdings sehr umfangreich und wenn man den (Tricky) Gesamtzusammenhang nicht kennt, wird's etwas schwierig....


Title: Re: Serial verschluckt Daten ?
Post by: Tommy56 on Apr 15, 2019, 02:12 pm
Du kannst ja alles raus lassen, was nicht mit der seriellen Kommunikation zu tun hat, also einen Minisketch bauen, der das Problem nachvollziehbar macht, aber den Rest weg lässt.
Das Problem muss natürlich noch auftreten.

Gruß Tommy
Title: Re: Serial verschluckt Daten ?
Post by: Whandall on Apr 15, 2019, 02:18 pm
Denke nicht, dass ich was falsch mache.
Ich bin ziemlich sicher dass du dich irrst.
Title: Re: Serial verschluckt Daten ?
Post by: uwefed on Apr 15, 2019, 02:45 pm
Denke nicht, dass ich was falsch mache.
Wieso fragst Du denn?

Arduino macht sicher nur das was Du programmiert hast. Ich tippe mal auf Indexüberschreitung eines Arrays.

Also zeig uns den Sketch.

Grüße Uwe
Title: Re: Serial verschluckt Daten ?
Post by: TERWI on Apr 16, 2019, 07:23 am
Muss ich leider in 2 Posts stückeln weil nir 9K reinpassen.

Definitionen:
Code: [Select]

#define DINO_VERSION    33            // "1.1" - HighNibble=Major, LowNibble=Minor
#define DINO_MODUL      1             // Modul-Number - 0=Master, 1++=Slave(s)
#define DINO_MAXCH      1             // standard is 1 - max 4 on MEGA
#define DINO_ID_STRING  "MULTI_TENS"  // string to identify

// Inputs:

// Outputs:

// communication Header
const byte HEADERSIZE = 16;
byte       header[HEADERSIZE];
const byte MARKERSTART =  62;           // ">" Start-marker, transmission begins
const byte MARKERDATA  = 124;           // "|" Header ending, start data
const byte MARKEREND   =  60;           // "<" End-marker, transmisson finished
const byte IDXHEADLEN  =   0;           // real length of header - MARKERDATA should follow immedeatly !!!
const byte IDXMODNUM   =   1;           // Modul-number to talk to
const byte IDXMODCHL   =   2;           // Modul-Channel - supported (Std. 1, 2-4 MEGA only)
const byte IDXMODVOL   =   3;           // "Master-Volume" 0-100%
const byte IDXREPLY    =   4;           // - 0 = return mode info only (no DATA)
                                        // - 1 = return + modul-info
                                        // - 2 = return + sequence-data
                                        // - 3 = return + actual external pulse-data (potis - if any)
const byte IDXPLAY     =   5;           // - 0 = ... Stop everything ...
                                        // - 1 = Manually external --- Freg, Pulse, Rate & Intens (with poti ... if available)
                                        // - 2 = Manually internal --- Freg, Pulse, Rate & Intens (values by block_num[0])
                                        // - 3 = single sequence   --- ... see below ...
                                        // - 4 = sequence PlayList --- ... see below ...
const byte IDXSTATUS   =   6;           // ... to be defined
const byte IDXERROR    =   7;           // ... to be defined
const byte IDXDATATYP  =   8;           // same as IDXREPLY ???!!!
const byte IDXDATALEN  =   9;           // length of one DATA-BLOCK
const byte IDXDATABLK  =  10;           // number of DATA-BLOCKs

byte   pulserate   = 0;   // 0-200, 0 = no repetition
byte   pulsewidth  = 0;   // 0-100, 0 = no pulse
byte   pulseintens = 0;   // 0-255, 0 = no intensity


Die Schleife:
Code: [Select]

void loop()
{
  CMD_check();
  delay(20);
}


SetUp:
Code: [Select]

void setup()
{
  // Setup input-pins:
 
  // Setup output-pins:

  noInterrupts();         

  // initialize timers & ISR

  interrupts();           

  Serial.begin(57600, SERIAL_8N1);       

  while (!Serial)               // also check timeout !
  { ;                // wait for serial port to connect. Needed for native USB port only
  }
  delay(10);

  // ---------- Send Modul-Info on start
  for (int i = 0; i < HEADERSIZE; i++) header[i] = 0;  // clear header
  header[IDXREPLY]     = 1;           // send Info
  CMD_echo();                   // return DATA: INFO
}



Title: Re: Serial verschluckt Daten ?
Post by: TERWI on Apr 16, 2019, 07:24 am
Prüfe Telegramm:
Code: [Select]

void CMD_check()
{
  boolean doread   = true;
  boolean isheader = false;
  boolean isdata   = false;
  boolean doecho   = false;
  byte    rb       = 0;         // received byte by Serial.read
  byte    idx      = 0;
  byte    blk      = 0;
  byte    len      = 0;
  int     datamax  = 0;

  if (Serial.available() < 14) return;           // enough bytes in queue ?
  for (int i = 0; i < HEADERSIZE; i++) header[i] = 0;  // clear header
  // ----- evaluate incoming bytes:
  while ((Serial.available() > 0) && doread)     // ... bytes available  and NOT header/data done ?
  {
    rb = Serial.read();                        // YES, read a byte ...
    switch (rb)
    {
      case MARKERSTART:               // ">" Start-marker, transmission begins
        isheader = true;              //
//        Serial.println("CMD_CKECK - StartByte OK, read HEADER....");
        continue;                     // ignore Marker, next byte in loop
        break;
      case MARKERDATA:                // "|" Header ending, start data ?!
        if ( (idx == header[IDXHEADLEN]) || !isheader )
        {
          isheader = false;             //
          doecho   = true;
          idx      = 0;
          datamax  = header[IDXDATALEN] * header[IDXDATABLK];
          if (datamax > 0) isdata  = true;
        }
//        Serial.println("CMD_CKECK - HEADER OK, read DATA....");
        continue;                     // ignore Marker, next byte in loop
        break;
      case MARKEREND:                 // "<" End-marker, transmisson finished
        doread   = false;             
        isheader = false;           
        isdata   = false;
        doecho   = true;
//        Serial.println("CMD_CKECK -> DATA OK, finished !");
//        continue;                   // ignore Marker, next byte in loop (and stop it !)
        break;
    }

    // ---------- read Header:
    if (isheader == true)
    {
/*
      Serial.print("-> read HDR: ");
      Serial.print(ndx);
      Serial.print(" - ");
      Serial.println(rb);
*/
      if (idx < HEADERSIZE)  // ??? && (idx < header[IDXHEADLEN])
      {
        header[idx] = rb;   // store header-byte
      }
      else
      {
        isheader = false;             
        if (header[IDXMODNUM] != DINO_MODUL) // this header is for us ?
        {                                    // ... NO !
          doread = false;                    // break the loop
          doecho = false;                    // no echo !
        }
      }
      idx++;
    } // end if (isheader) ...

    // ---------- read Data: (... if any)
    if (isdata == true)
    {
/*     
      Serial.print("-> read DAT: ");
      Serial.print(len);
      Serial.print(" - ");
      Serial.print(blk);
      Serial.print(" / ");
      Serial.println(rb);
*/     
      switch (header[IDXDATATYP])
      { case 1:     // pulse manual external
          if (len == 0) pulserate   = rb;        // 0-200, 0 = no repetition
          if (len == 1) pulsewidth  = rb;        // 0-100, 0 = no pulse
          if (len == 2) pulseintens = rb;        // 0-255, 0 = no intensity
          break;
        case 2:     // set single sequence
//
        case 3:     // set Playlist section
//
          break;
        case 4:     // new Sequence-Block
          break;
        case 5:     // new Sequence-Control
          break;
        case 6:     // new Sequence-PlayList
          break;
      }   
      idx = (len + 1) * (blk + 1);
      len++;
      if (len >= header[IDXDATALEN])
      { len = 0;
        blk++;
        if (blk >= header[IDXDATABLK])
        {
          isdata = false;
        }
      }
    } // end if (isdata) ...

  } // while

  while (Serial.available() > 0) Serial.read();  // clear RX-buffer

  if (doecho == true)
  {
    CMD_echo();                   // return DATA
  }
}


Sende Telegramm:
Code: [Select]

void CMD_echo()
{
  header[IDXHEADLEN]   = 11;          // idx = 0 - .... following data only
  header[IDXMODNUM]    = DINO_MODUL;  // idx = 1 - Modul-number to talk to
  header[IDXMODCHL]    = DINO_MAXCH;  // idx = 2 - Modul-Channel - supported (Std. 1, 2-4 MEGA only)
  header[IDXMODVOL]    = 100;         // idx = 3 - "Master-Volume" 0-100%
  header[IDXPLAY]      = 0;           // idx = 5 - STOP
  header[IDXSTATUS]    = 99;          // idx = 6 - ... to be defined
  header[IDXERROR]     = 88;          // idx = 7 - ... to be defined
  switch (header[IDXREPLY])           // idx = 4
  { case 1:                                        // - 1 = return + modul-info
      header[IDXDATATYP] = 1;
      header[IDXDATALEN] = 2 + sizeof(DINO_ID_STRING)-1;  // b2f - num of extra-bytes following
      header[IDXDATABLK] = 1;      // only 1 data-block of size = len
      break;
    case 2:                                        // - 2 = return + sequence-data
      header[IDXDATATYP] = 2;     
      header[IDXDATALEN] = 0;      // not yet defined
      header[IDXDATABLK] = 0;      // not yet defined
      break;
    case 3:                                        // - 2 = return + sequence-data
      header[IDXDATATYP] = 3;     
      header[IDXDATALEN] = 3;      // Puls-Rate, -Width, -Val
      header[IDXDATABLK] = 1;      // only 1 data-block of size = len
      break;
  }
  // ---------- send Header
  Serial.write(">>");                         // Marker HEADER BEGIN
  Serial.write(header, header[IDXHEADLEN]);   // the header itself
  Serial.write("||");                         // Marker HEADER END - DATA BEGIN
  // ---------- send Data
  switch (header[IDXREPLY])
  { case 1:                                        // - 1 = return + modul-info
      Serial.write(DINO_VERSION);                  // Version byte - HighNibble=Major, LowNibble=Minor
      Serial.write(DINO_MODUL);                    // Modul-Number - 0=Master, 1++=Slave(s)
      Serial.write(DINO_ID_STRING);                // DINO_ID_STRING for compare
      break;
    case 2:                                        // - 2 = return + sequence-data
/*
*/
      break;
    case 3:                                        // - 3 = return + actual external data (potis - if any)
      Serial.write(pulserate);                 
      Serial.write(pulsewidth);               
      Serial.write(pulseintens);               
      break;
    default:                                       // - 0 = return mode info only 
      break;
  }   
  Serial.write("<<");                         // Marker TRANSMISSION END
  Serial.flush();
}


Dann schaut mal durch. Hab nur das nötigste drin gelassen.
Basiert übrigends auf dieser Idee (https://forum.arduino.cc/index.php?topic=288234.0).
Problem ist wie gesagt, dass hier z.B. im zurückgsendeten Telegramm im Header offensichtlich "switch (header[IDXREPLY])" nicht richtig ausgewertet wird (alles 0 ?!).

Interessanterweise passiert das nicht regelmäßig, sondern sporadisch.
Vor allem wenn in CMD_Check auch nur eines der "Serial.println("CMD_CKECK" oder das delay(20) in der Loop weggelassen wird.
Title: Re: Serial verschluckt Daten ?
Post by: combie on Apr 16, 2019, 07:37 am
Quote
Problem ist wie gesagt, dass hier z.B. im zurückgsendeten Telegramm im Header offensichtlich "switch (header[IDXREPLY])" nicht richtig ausgewertet wird (alles 0 ?!).
Dann steht da nicht das richtige drin.


------------


Ein kleines wenig, fühle ich mich *******...

Da mache ich mir schon die Arbeit, erzeuge eine neues Projekt, und dann:
Der Code ist nicht testbar

Nirgendwo ist zu sehen, wo header[IDXREPLY] gefüllt wird.

Ich gebe auf....

Title: Re: Serial verschluckt Daten ?
Post by: Whandall on Apr 16, 2019, 07:38 am
Basiert übrigends auf dieser Idee (https://forum.arduino.cc/index.php?topic=288234.0).
Das ist nicht so, es sei denn die Idee wird auf Start- und Endmarker reduziert.

Robin2s Kode enthält keine delays, Tests auf Tiefe des RX-Buffers und keine whiles.
Title: Re: Serial verschluckt Daten ?
Post by: TERWI on Apr 16, 2019, 07:49 am
@ combie
.... das meinte ich mit der Komplexität.
Der zu empfangende Header wird vom PC aus gesendet und auch jeweils richtig gefüllt.
Wenn ich in CMD_Check nach " if (isheader == true)" die Ausmarkierung weglasse, sehe ich die Header-Daten die kommen und die sind dann richtig.

@ Whandall
Ich sagte ja auch "basiert".....
Und ein while hat der Robin sehr wohl darin - siehe Code #1.
Und betreff delay schau mal ab #36.

Hier geht es um die Frage:
Warum gehts das mit delay / div Serial.print und warum nicht ohne ?
Title: Re: Serial verschluckt Daten ?
Post by: Whandall on Apr 16, 2019, 08:08 am
Robin2 wartet vorher nicht auf dem Empfang der vollständigen Nachricht,
die Verwendung eines while statt eines ifs halte ich an der Stelle für didaktisch falsch,
dich hat es jedenfalls auf den Holzweg geführt.
Ein delay findet Firefox auf der ersten Seite des verlinkten Beitrags nicht.

Delays gehören nicht in ein Programm das asynchron kommunizieren soll.
Warte nicht auf einen Füllstand im RX-Puffer, verarbeite jedes Zeichen wenn es empfangen wird.

Den Array vor einem Empfang zu löschen ist völlig überflüssig, wenn du einen Terminator brauchst,
hänge den nach der Nachricht an.
Auch das Löschen des Puffers nach einer Nachricht erscheint mir kontraproduktiv,
ich denke da verschluckst du die Daten.

[OT] Ich empfinde Start- und Endmaker als unnötig kompliziert, ein Endmarker reicht (mir) völlig. [/OT]
Title: Re: Serial verschluckt Daten ?
Post by: TERWI on Apr 16, 2019, 08:25 am
@ Whandall
Mal richtig lesen: while in Post #1 auf Seite 1 und delay in/ab Post #36 auf Seite 4.
Mir scheint, meinen Code hast du auch noch nicht wirklich gelesen.

Ich lese byte für byte so bald etwas vorhanden ist. while ... Serial.read ....
Das löschen des Header-Arrays hat den Sinn, definierte Daten zu haben, wenn z.B. eine unvollständige Nachricht ankommt.
In Kombination eben mit einen Start- und End-Marker (hier zusätzlich ein Marker, welcher das Ende des Headers angibt) soll zusätzlich definiert den Begin und das Ende von erwünschten Daten anzeigen - egal was da ggf. für ein Datensalat ankommt.

Das Löschen des RX-Puffers ist nur "safety" und optional. Könnte man auch weglassen ....
Mir ist Anfangs nach einem Fehler aufgefallen, dass wenn z.B. der Endmarker nicht richtig gelesen (und gelöscht) wurde, dieser ja im Puffer verbleibt und dann beim nächsten Schwung Daten (> 14 Bytes !) für "Verwirrung" sorgt.
Das verschluckt hier m.E.n. keinerlei Daten, da schon alle (insbesondere Header) gelesen wurden.

Recht gebe ich dir, dass ein delay in Ser.-Kommunikation normalerweise nix zu suchen hat.
Deshalb frage ich ja auch nach einem eventuellem Grund für das eigenartige Verhalten - ohne delay.....

PS: Alle Marker-Werte können logo auch in möglichen Daten vorkommen. Die Prüfung, ob ein Endmarker auch an der erwarteten Position kommt, fehlt noch.
Zu dem haben die Marker (hier) den Sinn, zu prüfen ob die Übertragung auch wirklich korrekt ist.
Böse Zungen behaupten, ein CRC täte es auch .... :-)
Title: Re: Serial verschluckt Daten ?
Post by: Whandall on Apr 16, 2019, 08:29 am
Ich finde imer toll dass andere besser wissen was ich gelesen und verstanden habe.

Das verschluckt hier m.E.n. keinerlei Daten, da schon alle (insbesondere Header) gelesen wurden.
Code: [Select]
  while (Serial.available() > 0) Serial.read();  // clear RX-buffer

Da du ja alles besser weisst wünsche ich dir viel Erfolg bei deinem Projekt,
dafür ist mir meine Zeit zu schade.
Title: Re: Serial verschluckt Daten ?
Post by: TERWI on Apr 16, 2019, 09:37 am
Warum so garstig ?
Diese Zeile steht am Ende der Leseroutine.
Und sie ist optional und nur zur Sicherheit, wie ich schrieb.
Sei sicher: Ich habe diese Zeile auch schon auskommentiert und das Verhalten ist das gleiche.
Daran liegt es offensichtlich nicht.
Title: Re: Serial verschluckt Daten ?
Post by: dsyleixa on Apr 16, 2019, 09:47 am
hallo,
so einen riesigen langen Code wird kaum jemand debuggen können/wollen.

Kürze doch bitte schrittweise alles zurück bis auf die minimalste kompilier- und lauffähige Version, wo nur die fragliche Serial-Ausgabe drin ist und alles andere rausgeschmissen wurde (Variablen, Hilfsroutinen, if-Blöcke, switch/breaks, auskommentierte Programmzeilen), was nicht unbedingt relevant ist, aber dann immer noch den Fehler reproduziert (sog. MCVE Code Version).
50-80 Programmzeilen müssten dafür ausreichen.
Title: Re: Serial verschluckt Daten ?
Post by: TERWI on Apr 16, 2019, 01:51 pm
@ dsyleixa
Na ... sooo lang ist der Code ja nun auch nicht. Sind ja letztendlich nur 2 Funktionen.
Sei versichert, das habe ich schon mehr als 2x gemacht - auch die ganze Struktur (wieder) umgestellt wie im zuvor beschriebenen "Basisbeispiel".
Es bleibt bei diesem Problem...

Und: Eben grade beim ausdünnen (Raus mit den Debug-Prints u.a.) ist mir das erst aufgefallen, dass da irgendwie bytes verschwinden !
Mit (oder eben mit delay in der Loop) läuft das tadellos.

Title: Re: Serial verschluckt Daten ?
Post by: uwefed on Apr 16, 2019, 02:32 pm
Quote
Mit (oder eben mit delay in der Loop) läuft das tadellos.
Genau das ist der Gedankenfehler.

Die Bits trudeln so langsam ein und Du erwartest sie alle sofort vollzählig im Eingangsbuffer der Schnittstelle.
Mit einem langsamen Programm (durch die delays) funktioniert das dann schon.

Der Sketch muß die Bytes holen wenn sie ankommen und sofort analysieren. Wenn keine ankommen dann kontrolliert er halt solange bis wieder was da ist.

Grüße Uwe 
Title: Re: Serial verschluckt Daten ?
Post by: Serenifly on Apr 16, 2019, 02:46 pm
Ein Byte braucht 1 / Baudrate * 10 Sekunden (1 Startbit, 8 Datenbits, 1 Stopbit). Das sind bei 9600 Baud ca. 1ms. Selbst bei sehr hohen Baudraten ist die serielle Schnittstelle noch deutlich langsamer als der Prozessor
Title: Re: Serial verschluckt Daten ?
Post by: dsyleixa on Apr 16, 2019, 03:12 pm
@ dsyleixa
Na ... sooo lang ist der Code ja nun auch nicht. Sind ja letztendlich nur 2 Funktionen.
Sei versichert, das habe ich schon mehr als 2x gemacht - auch die ganze Struktur (wieder) umgestellt wie im zuvor beschriebenen "Basisbeispiel".
Es bleibt bei diesem Problem...
Und: Eben grade beim ausdünnen (Raus mit den Debug-Prints u.a.) ist mir das erst aufgefallen, dass da irgendwie bytes verschwinden !
Mit (oder eben mit delay in der Loop) läuft das tadellos.
es geht nicht um das, was du selber alles ausprobiert hast, sondern um einen nachvollziehbaren, minimalen, aber kompletten und sofort kompilierbaren Code, der den Fehler sofort reproduziert, und  den wir uns hier ansehen und ggf. auch downloaden und selber austesten können. Ohne alles dafür nicht unbedingt notwendige Zeugs. Höchstens (!) minimal (!) länger als 50 Zeilen.
Also poste bitte mal diese MCVE Code Version.
Title: Re: Serial verschluckt Daten ?
Post by: TERWI on Apr 16, 2019, 03:38 pm
@ Serenifly
Ich nutze i.d.R. 57600 - nur Testweise hatte ich mal auf 9600 gestellt. Gleiches Prob.
Als "delay" sind zwar die Serial.pint's in der Leseroutine, aber das delay() selbst steht in der Loop.
Anmerkung dazu siehe unten.

@ Uwe
Ich warte ja schon auf z.Zt. min. 14 Zeichen im Puffer (11x Header, 3x Marker).
Das liest die Routine ja auch anständig aus - ggf auch mit angehängten Daten-bytes.

@ dsyleixa
Hier ist eben das Prob, dass das nicht ein 0815-Ding ist, sondern eben etwas komplexer und eigentlich auch nur mit einem "Master" arbeitet, welcher eine Telegramm (Header mit Markern) sendet, diese wieder empfängt und auch wieder prüft.
Wer das richtig testen will, braucht schon meine kleines "DINO-CCOM-Tool" für den PC.
Wenn das anwenderfreundlicher geworden ist, poste ich das hier auch noch.
Hier ist etwas mehr Vorstellungskraft nötig ...

Zum möglichen Gedankenfehler:
Mich beschleicht eher mehr das Gefühl, das CMD_Check ( & CMD_Echo) in der Loop viel zu schnell wieder aufgerufen wird.
D.h., Serial macht alles asynchron und blockt nichts (?!), Routine ist fertig und der nächste Aufruf kommt, bevor der Puffer richtig leer ist ???
Mit delay(20) klappt das gut - mit weniger (<= 10) verhaspelt sich das wieder.
Title: Re: Serial verschluckt Daten ?
Post by: Serenifly on Apr 16, 2019, 03:41 pm
Ich nutze i.d.R. 57600 - nur Testweise hatte ich mal auf 9600 gestellt. Gleiches Prob.
Dann dauert ein Byte immer noch ca. 170µs!
Title: Re: Serial verschluckt Daten ?
Post by: combie on Apr 16, 2019, 03:43 pm
Quote
und blockt nichts (?!)
Die FiFos der Seriellen, eines UNO, sind 64 Byte groß.
Danach blockiert das senden.
Das lesen verliert dann Bytes

Aber das kannst du auch alles selber herausfinden.
Denn schließlich liegt der Quellcode auf deinem PC.
Title: Re: Serial verschluckt Daten ?
Post by: TERWI on Apr 19, 2019, 08:52 am
Das mit den Puffer-Limits ist mir bekannt.
Aktuell sendet der PC jedoch nur 11 Header-, 3 Daten- und 3 Marker-bytes. Also ges. 17. Da läuft nix über.
Z. Zt. werden zurück gesendet 11 Header- und 6 Marker-bytes zzgl bei
- bei IDXREPLY=1: 12 bytes (2 Werte, DINO_ID_STRING) als Kennung bei SetUp/Reset
- bei IDXREPLY=3: 3 bytes wie empfangen zur Kontrolle
Ges. 17 bzw 29 bytes. Auch da läuft nix über.

Da PC-Proggie wartet nach jeder Übertragung auf Antwort und verifiziert diese.
Erneutes senden wird mit einem Timeout von 3 Sek. geblockt, so das der Dino nicht gestresst wird.
An zu viel Daten und/oder zeitkritischen Aufrufen sollte es also nicht liegen.

CMD_Echo scheint einwandfrei zu sein.
Nur CMD_Check hat nach wie vor offensichtlich ein Problem, Daten richtig zu lesen.
Bisher keine Anhung warum. Immer wenn ich das mit Serial.print irgendwie/-wo debugge, ist alles OK - wie eben mit dem zusätzlichen delay.

Zugegebener Weise ässt sich das in dieser Form schlecht test ....
... aber hat denn niemand in ähnlicher Form schon mal so einen Effekt gehabt ?
Title: Re: Serial verschluckt Daten ?
Post by: uwefed on Apr 19, 2019, 09:11 am
Quote
... aber hat denn niemand in ähnlicher Form schon mal so einen Effekt gehabt ?
Ja, hatte ich, bei einem Indexüberlauf eine Arrays.
Grüße Uwe
Title: Re: Serial verschluckt Daten ?
Post by: ElEspanol on Apr 19, 2019, 11:18 am
Die Bytefolge ließe sich aus jedem Terminalprogramm heraus senden und empfangen.
Wenn du deinen Sketch auf das Minimum schrumpfst, was das Verhalten noch produziert, springt einen (vielleicht nicht dich) der Fehler oft förmlich an.
Wenn du weiter eindampfst, das der Fehler nicht mehr auftritt, hast du einen Ansatz zum suchen.
Title: Re: Serial verschluckt Daten ?
Post by: dsyleixa on Apr 19, 2019, 12:06 pm

Quote
... aber hat denn niemand in ähnlicher Form schon mal so einen Effekt gehabt ?
ich verschicke bis zu 1024 Bytes lange messages zwischen Arduino und PC (Borland C++ Builder) über Serial und das Borland-COMM-Widget hin und her und habe nie Probleme mit verschluckten Daten.
UART-clock: Serial.begin(115200).
Ich schreibe (sende) am Arduino verschieden lange cstring-Arrays ( char cbuf[1024], wird aber nicht immer maximal gefüllt ) per Serial.println (Abschluss erfolgt dadurch immer per  Message-Ende-Marker  '\n'  );
lesen  (empfangen) von unterschiedlich langen Messages (<1024 bytes) immer byte-weise  (vor Weiterverarbeiting am Arduino zunächst per String = String class, am PC als C++ AnsiString) bis  Message-Ende-Marker '\n' erreicht ist (Messages werden auch vom PC-Programm damit abgeschlossen).
Weiterverarbeitung der empfangenen (Roh-) strings dann nach Umwandlung in cstrings (ebenfalls char cbuf[1024]).
Lesen/schreiben ist hier auch nicht durch Serial()-Puffer-Limits eingeschränkt.
Title: Re: Serial verschluckt Daten ?
Post by: combie on Apr 19, 2019, 12:58 pm
Ach Leute...
Jetzt lasst unseren TERWI doch noch ein bisschen gären....

Im Moment ist er (scheinbar?) noch nicht bereit das Problem ernsthaft anzugehen.
Er möchte lieber noch etwas jammern.
Bisher agiert er eher Problem orientiert, als Lösungsorientiert.

Als wenn versucht wird ein technisches Problem mit sozialen Lösungsstrategien anzugehen.
Und das wird bekanntlich nichts.
Denn die Technik kann ihre Einstellung nicht ändern.
Und es macht auch wenig Sinn sie zu besprechen.


Quote
ich verschicke ..
Ich schreibe ...
Ja, du bist schon ein toller Hecht!
Ohne jeden Zweifel....

Ich möchte dein Glück/Erfolg nicht schmälern, aber wie soll dein Sieg hier helfen?
Title: Re: Serial verschluckt Daten ?
Post by: dsyleixa on Apr 19, 2019, 12:59 pm
Jetzt lasst unseren TERWI doch noch ein bisschen gären....
Er möchte lieber noch etwas jammern.
...
Ja, du bist schon ein toller Hecht!
Ohne jeden Zweifel....
und du bist schon ein toller Troll (aber das kenne ich ja schon von früheren posts von dir, z.B. im Topic C++ für Anfänger und dem zum Wii Nunchuk)!
Hauptsache, die Leute runtermachen, gell?

edit,
ok, jetzt hast du nacheditiert...
es geht auch nicht um einen von dir  ironisch-hochnäsig titulierten "Sieg", sondern um die Frage des TO, ob noch jemand sonst derartige Probleme beobachtet hat, und mein Rezept, wie ich sogar deutlich längere Messages zwischen PC und Arduino hin- und herschicken konnte, ohne dass Daten "verschluckt" werden oder wurden, entgegen dem Statement
Quote
Die FiFos der Seriellen, eines UNO, sind 64 Byte groß. Danach blockiert das senden. Das lesen verliert dann Bytes.
Title: Re: Serial verschluckt Daten ?
Post by: combie on Apr 19, 2019, 01:49 pm
Haben wir bis jetzt testbaren Code gesehen?
Die Chance, den Fehler zu reproduzieren?

Überhaupt den winzigsten Ansatz, wo es klemmt?
Nein!


Und wir sind jetzt bei 30 Beiträgen.

Entweder setzt jetzt langsam mal eine andere Denkrichtung ein, oder das wird hier gar nichts mehr!



----------------


Quote
und du bist schon ein toller Troll (aber das kenne ich ja schon von früheren posts von dir, z.B. im Topic C++ für Anfänger und dem zum Wii Nunchuk)!
Hauptsache, die Leute runtermachen, gell?
Es gibt Leute, die verklemmen sich irgendwie mit ihren Gedanken.

Und wenn erst ein Troll kommen muss, um ihnen das zu sagen, ja, dann bin ich wohl ein Troll.
Dann bin ich auch gerne ein Troll.
Und es ist mir gelinge gesagt vollkommen egal, was die Zielperson davon hält.
Die hat sowieso die Kröte zu schlucken, dass Sie auf einem völlig falschen Ast sitzt.
Auf der falschen Baustelle buddelt.

Und dann gibts da noch die Leute, welche lieber sauer, auf andere sind, als die eigene Einstellung zu prüfen.
Die sollen ja schließlich auch ihren Spaß haben!
Matthäus 7 (https://bibeltext.com/matthew/7-5.htm)

Übrigens:
Sind es nicht meistens eher die Trolle, welche in allem und jedem erst mal einen Troll erkennen?
Title: Re: Serial verschluckt Daten ?
Post by: dsyleixa on Apr 19, 2019, 02:47 pm
Code: [Select]
Sind es nicht meistens eher die Trolle, welche in allem und jedem erst mal einen Troll erkennen?
weiß ich nicht, ich zumindest trolle schließlich nicht rum und mache keine Leute und auch nicht ihre Ideen, ihre Fragen oder ihren Kenntnisstand mies.
Title: Re: Serial verschluckt Daten ?
Post by: combie on Apr 19, 2019, 03:13 pm
Quote
ich zumindest trolle schließlich nicht rum
:smiley-twist: Darüber kann man durchaus geteilter Meinung sein!  :smiley-twist:
Title: Re: Serial verschluckt Daten ?
Post by: TERWI on Apr 19, 2019, 04:29 pm
@ combie
Wenn du hier nicht (mangels Vorstellungskraft wegen fehlendem Komplett-Code inkl. Sende-Tool) nicht sinvoll beitragen kannst oder möchtest, dann spar dir bitte deine nutzlosen Kommentare. Danke.

@ ElEspanol
Ich habe schon so weit möglich abgespeckt, so dass der Sinn & Funktion erhalten bleibt.
Ich muss mich wiederholen:
Das funktioniert ja so weit 1A, so lange ich ein (paar) Serial.print's als Debug drin lasse oder eben ein delay(x) in die Loop packe, was ja nicht sonderlich sinnig ist...
Kommentiere ich alles Debug-ähnliche raus, verschwinden irgendwie bytes. Mir völlig unerklärlich. Es lässt sich ohne Debug auch nicht wirklich nachvollziehen, wo. (.... und wenn drin, dann geht's ja ...)

@ dsyleixa
Ich schicke das vom PC aus via Borland Delphi. Das Tool/die Routinen darin sind anderweitig getest und laufen sicher.
Auf dem Dino wollte ich keinen großen Empangspuffer bauen, weil ich den kleinen Speicher später noch für andere Programmsachen brauche - also  minimalst dirket lesen und sofort in Aktion umsetzen.

Vielleicht noch mal zum Sinn dieser Aktion:
Ich möchte in einer Routine möglichst verschieden lange Telegramme (der Header) zur allgemeinen Steuerung schicken und dazu dann auch. verschieden lange Datenpakete.
Das ganze sollte möglichst sicher sein, auch wenn die Daten durch Übertragungstörungen (soll auch mal OTA angewendet werden) die Form/Anzahl verlieren/verändern.
Deshalb eben ein MARKER-Start, der den Anfang des Headers definiert. Ein MARKER-Daten, der definiert das Ende des Headers und Begin der Daten anzeigt. Und ein MARKER-End, welcher Das Ende der Übermittlung anzeigt.
Passt alles geht das gleiche Telegramm (nicht immer mit allen/gleichen oder angeforderten Daten) zur Kontrolle zurück.
Passt irgendwie ein Marker nicht an seiner erwarteten Position, ist die ganze Nachricht hinfällig und es findet keine Aktion im DINO statt.
Und/oder wenn der Header ggf. ungültig und kommt kein ECHO, sendet der Master nochmal.
Title: Re: Serial verschluckt Daten ?
Post by: TERWI on Apr 19, 2019, 04:30 pm
Mittlerweile habe ich den Code ein wenig umgebaut.
Zunächst hatte ich mich auf Aussagen im Forum verlassen, keine blockenden Serial-Funktionen zu nutzen und mich an Robin2's Beispiel gehalten.
Nun hab ich eben diese "bösen" und vermeintlich nicht so doll funzen Blockierfunktionen genommen - macht den Code etwas schlanker und (was am wichtigsten ist !!!) :
ES FUNKTIONIERT endlich.
Auch ohne irgendwelche Debugs oder delay()'s. und mit weniger Globalen.
Für "wie es geht" hab ich entsprechende Kommentare eingefügt.
Hier mal nur die Lese-routine neu:

Code: [Select]

void CMD_check()
{
  if (Serial.available() < 15) return;    // minimum telegram-size

  int num      = 0;
  int ofs      = 0;
  for (int i = 0; i < HEADERSIZE; i++) header[i] = 0;  // clear header

  if (!Serial.find(MARKERSTART))                            // MARKER found ?
    Serial.println("CMD_CKECK - MARKER-Start NOT found !"); // NO
  else                                                      // YES
  {
    header[IDXHEADLEN] = Serial.read();                    // read real Header-length
    num = Serial.readBytes(header + 1, header[IDXHEADLEN] - 1);  // read rest of Header at header[1] !!!
    if (num != (header[IDXHEADLEN] - 1))                  // did we read the wanted number of bytes ?
      Serial.println("CMD_CKECK - HEADER-Size doesn't match !");   // NO
    else                                                           // YES
    {
      if (!Serial.find(MARKERDATA))                             // MARKER found ?
        Serial.println("CMD_CKECK - MARKER-Data NOT found !");  // NO
      else                                                      // YES
      {
        for (int i = 1; i <= header[IDXDATABLK]; i++)   // read all data-blocks
        {
          num = Serial.readBytes(data + ofs, header[IDXDATALEN]);  // read 1 data-block
          if (num != header[IDXDATALEN])   // did we read the wanted number of bytes ?
          {                                // NO
            header[IDXDATALEN] = 0;        // set val in Header to 0 / no length
            header[IDXDATABLK] = 0;        // set val in Header to 0 / no blocks
            break;                         // stop the loop
          }
          ofs = ofs + header[IDXDATABLK];  // increment adress to write to
        }
        if (!Serial.find(MARKEREND))                             // MARKER found ?
          Serial.println("CMD_CKECK - MARKER-End NOT found !");  // NO
        else                                                     // YES
        {
          CMD_eval();  // evaluate the command and/or data
          CMD_echo();  // send echo to master
        }
      }
    }
  }
  while (Serial.available() > 0) Serial.read();  // clear RX-buffer for safety
}
Title: Re: Serial verschluckt Daten ?
Post by: dsyleixa on Apr 19, 2019, 04:37 pm
@ dsyleixa
Ich schicke das vom PC aus via Borland Delphi. Das Tool/die Routinen darin sind anderweitig getest und laufen sicher.
Auf dem Dino wollte ich keinen großen Empangspuffer bauen, weil ich den kleinen Speicher später noch für andere Programmsachen brauche - also  minimalst dirket lesen und sofort in Aktion umsetzen.

Vielleicht noch mal zum Sinn dieser Aktion:
Ich möchte in einer Routine möglichst verschieden lange Telegramme (der Header) zur allgemeinen Steuerung schicken und dazu dann auch. verschieden lange Datenpakete.
Das ganze sollte möglichst sicher sein, auch wenn die Daten durch Übertragungstörungen (soll auch mal OTA angewendet werden) die Form/Anzahl verlieren/verändern.
Deshalb eben ein MARKER-Start, der den Anfang des Headers definiert. Ein MARKER-Daten, der definiert das Ende des Headers und Begin der Daten anzeigt. Und ein MARKER-End, welcher Das Ende der Übermittlung anzeigt.
Passt alles geht das gleiche Telegramm (nicht immer mit allen/gleichen oder angeforderten Daten) zur Kontrolle zurück.
Passt irgendwie ein Marker nicht an seiner erwarteten Position, ist die ganze Nachricht hinfällig und es findet keine Aktion im DINO statt.
Und/oder wenn der Header ggf. ungültig und kommt eine ECHO, sendet der Master nochmal.

Genau aus diesem Grunde mache ich es ja auch, nur offenbar mir einem anderen Puffer, anderen Daten und einem anderen Protokoll und ohne dass Daten verlorengehen.

Aber jetzt gerade las ich ja, dass es endlich funktioniert.
Glückwunsch! 8)