Go Down

Topic: Buffer di ricezione sporco di F0 all’apertura della porta COM Su Arduino UNO R3  (Read 3535 times) previous topic - next topic

zoomx


Durante la realizzazione di un progetto mi sono accorto di un comportamento curioso che non so a cosa sia dovuto.

Quando apro la porta COM da PC senza resettare Arduino la routine che aspetta caratteri nello sketch rileva un F0 che non ho spedito io.

Succede ogni volta che apro la porta ma solo in quel momento. Se chiudo la porta da Windows e poi la riapro il problema si ripresenta.

Mi accade con macchine diverse che hanno sempre Windows. Non ho provato con Linux.


Una ricerca in rete mi ha dato come risultato utile solo questa discussione del 2013

http://forum.arduino.cc/index.php?topic=150620.5

senza alcuna soluzione.


I test sono stati effettuati con Arduino UNO R3 originale.

Se carico lo sketch in un clone Nano con CH340 il problema non si presenta. Non ho a portata di mano altri cloni per fare altre prove.

Sembrerebbe quindi che il problema stia nel chip usato da Arduino come convertitore seriale come del resto ipotizza l'autore della discussione che ho linkato.


Per vedere l'effetto bisogna usare un terminale che non cambi le linee RTS e DTR.

Usando il terminale seriale dell'IDE il problema non si presenta perché dopo l'apertura della porta viene effettuato un reset.

Se si usa Realterm bisogna prima andare nella scheda "pins" e fare il clear sia della linea RTS che DTR. A questo punto basta tornare alla scheda "display" e aprire e chiudere la porta con il pulsante open per vedere che succede.

Il programma che uso si chiama semplicemente Terminal ed è possibile scaricarlo da qui

https://sites.google.com/site/terminalbpp/
Se ogni volta che aprite la porta dopo pochi secondi vi appare la scritta "F0problem" , che viene stampata nel setup, vuol dire che è stato effettuato un reset.

Code: [Select]
/*
   F0problem
   Test program to resolve the F0 problem
   When Serial port is opened in Windows
   I found an F0 in the Serial buffer
*/

//Serial input with termination section
#define INLENGTH 6          //Max string lenght over serial. Needed for input with termination
#define INTERMINATOR 13     //GetCharFromSerial routine cycle waiting for this character. Needed for input with termination

char inString[INLENGTH + 1]; //GetCharFromSerial returns this char array. Needed for input with termination
unsigned char comm; //First character received. Needed for input with termination

//SerialInputNewline
const byte numChars = 32;
char receivedChars[numChars];  // an array to store the received data
boolean newData = false;

//***********************************************************************************************
void recvWithEndMarker() {
  static byte ndx = 0;
  char endMarker = 13;   //'\r';
  char rc;

  // if (Serial.available() > 0) {
  while (Serial.available() > 0 && newData == false) {
    rc = Serial.read();
    Serial.print("recvWithEndMarker->");
    Serial.println(rc);

    if (rc != endMarker) {
      receivedChars[ndx] = rc;
      ndx++;
      if (ndx >= numChars) {
        ndx = numChars - 1;
      }
    }
    else {
      receivedChars[ndx] = '\0'; // terminate the string
      ndx = 0;
      newData = true;
    }
  }
}

void ParseMenu(char Stringa) {
  boolean IsKnownCommand = true;
  switch (Stringa) {

    case 'p':
      break;
    case 'm':

      Serial.println("Print menu");
      break;
    case 'w':
      Serial.println("Execute w");
      break;
    default:
      IsKnownCommand = false;
  }
  if (IsKnownCommand == true)
  {
    Serial.println("OK");
    EndCommand();
  } else {
    Serial.println("ERROR!");
    Serial.println(Stringa, HEX);
  }
}

//***********************************************************************************************
void EndCommand() {
  Serial.println("End command");
}

void setup() {
  Serial.begin(115200);
  Serial.println("F0problem");
}


void loop() {

  recvWithEndMarker();
  if (newData == true) {
    comm = receivedChars[0];

    Serial.print("Command->");
    Serial.print(comm);
    Serial.print(" ");
    Serial.println(comm, HEX);

    if (comm != 0xF0) {
      ParseMenu(comm);
    }
    else
    {
      //comm = 'p';
      Serial.println("Discard F0");
      Serial.println("OK");
      EndCommand();
    }
    newData = false;
  }
}




astrobeed

Scientia potentia est

zoomx

Nelle issue non ho trovato nulla. Per adesso ho aggiunto un check per eliminare il dato errato ma non è una bella soluzione.
L'altra ipotesi è sostituire l'originale con un clone con CH340.

Curioso che abbia trovato solo un thread che ne parli ma può essere che nessuno si sia intestardito a trovarne le cause o abbia ritenuto che il problema fosse nello sketch come all'inizio avevo supposto io.

astrobeed

Curioso che abbia trovato solo un thread che ne parli ma può essere che nessuno si sia intestardito a trovarne le cause o abbia ritenuto che il problema fosse nello sketch come all'inizio avevo supposto io.
Più semplicemente non ci ha fatto caso nessuno sia perché normalmente fanno resettare Arduino quando si apre la seriale oppure non si sono accorti della cosa.
Personalmente quando apro la seriale sul pc faccio sempre un flush dopo 100 ms, questo perché non è insolito ricevere del garbage dai device, quindi non mi sono mai accorto di questo specifico problema di Arduino fino a che ieri sera non l'ho verificato dopo la tua segnalazione.
Ti conferma che è il 16u2 perché ho controllato con l'analizzatore di stati logici se il 328 invia qualcosa all'apertura della seriale, senza reset, e non lo fa.
Scientia potentia est

zoomx

Ne avevo il forte sospetto ma tu mi dai conferma. GRAZIE!

Non posso adottare la tua soluzione in quanto all'apertura della porta è Arduino che riceve la spazzatura e credo non abbia modo di sapere se la porta è aperta o no. Dal lato PC ovviamente lo so e per adesso il workaround è mandare un primo comando che non fa nulla.

paulus1969

Quindi è Windows che invia quel carattere, quando apri la porta da Windows.

Usalo a tuo vantaggio, appena arriva quel carattere, sai che hai aperto la porta  :)

zoomx

Non è Windows, è il chip 16u2. Se uso un clone con CH340 non succede.

astrobeed

Se uso un clone con CH340 non succede.
Esatto è lui, viene inviato nei due sensi, sia verso l'ATmega che verso il PC.
Scientia potentia est

zoomx

Non me ne ero accorto dell'invio anche verso il PC, Eppure lo avevi scritto prima. Rigrazie!
E' l'unico caso in cui un clone risulta superiore. Penso che anche gli altri chip di conversione USB seriale come l'FTDI e il Prolific non generino caratteri.
Il carattere generato però è sempre lo stesso, un F0.
Ne programma di test però ho aggiunto una print nella routine di ricezione e succede che il primo print è sporcato in maniera casuale.

L'Arduino non può sapere se la porta è aperta o meno poiché vede i caratteri arrivargli dal chip 16u2. Potrebbe essere quindi un problema nel firmware del 16u2?

astrobeed

L'Arduino non può sapere se la porta è aperta o meno poiché vede i caratteri arrivargli dal chip 16u2. Potrebbe essere quindi un problema nel firmware del 16u2?
Tocca andare a vedere il codice del 16u2 per capire cosa succede quando viene aperta la com virtuale, può essere sia un bug sia una cosa voluta per un qualche scopo, magari pensato in origine e mai utilizzato in pratica.
Devo verificare se avviene la stessa cosa anche sulla Mega visto che pure lei usa il 16u2.
Scientia potentia est

zoomx

Io per adesso posso dire che capita sia sugli Arduino UNO R3 di Arduino.cc che su quelli di Arduino.org.
La Mega è sepolta da qualche parte a casa.

Ho provato con il Launchpad MSP430 che ha anche lui un micro sempre Texas che svolge lo stesso compito del 16u2 con Energia e riducendo la velocità della seriale a 9600 (alrimenti non funziona!). Il bug non c'è.

Se trovo il tempo vorrei provare anche con l'HoodLoader2 che è il bootloader alternativo che consente l'uso del 16u2 in ambiente Arduino.
https://github.com/NicoHood/HoodLoader2/wiki

astrobeed

Se trovo il tempo vorrei provare anche con l'HoodLoader2 che è il bootloader alternativo che consente l'uso del 16u2 in ambiente Arduino.
Interessante, devo provarlo.
Scientia potentia est

zoomx

Dopo aver provato sul Launchpad a 9600 mi è venuto il dubbio se il bug fosse dipendente o meno dalla velocità.

Ho ricompilato quindi lo sketch per i 9600 su Arduino Uno originale e sembra che a questa velocità il bug non ci sia. Non me lo aspettavo. Non sembrerebbe però che sia una caratteristica voluta, il carattere cambia.
Idem per 57600
A 128000 il carattere è ancora un F0
A 256000 il carattere è uno zero
A 38400 è un FF

E a questo punto mi son fermato. Speravo che si presentasse da 115200 in poi. Non è così.

Edit: mi rendo conto che notarlo sarebbe stato difficile visto che ad alcune velocità non si presenta.

astrobeed

Edit: mi rendo conto che notarlo sarebbe stato difficile visto che ad alcune velocità non si presenta.
Più che altro perché nella stragrande maggioranza dei casi si lascia resettare Arduino all'apertura della seriale, oppure si utilizza un protocollo dati che ignora il carattere e non ci si fa caso, p.e. io implemento sempre un timeout sulla seriale dei micro/mcu, se il pacchetto dati non arriva completo azzero il buffer, se non aprivi questo topic quasi sicuramente non mi sarei mai accorto della cosa. :)
Scientia potentia est

speedyant

Possibile che sia un problema di "sincronia" con le frequenze per la usb.

Go Up