Go Down

Topic: Problema con la seriale (Read 2 times) previous topic - next topic

pelletta

May 19, 2011, 11:15 pm Last Edit: May 20, 2011, 01:10 am by Pelletta Reason: 1
Salve a tutti, ho un problema con la comunicazione seriale e forse mi sta sfuggendo qualcosa...
Devo far comunicare uno standalone provvisto di chip MAX232 con la porta seriale di un vecchio pc con sopra windows xp; sul pc per inviare i dati sulla seriale devo usare per forza uno script eseguito in un file bat che qui sotto riporto:
Code: [Select]

mode com1:9600,n,8,1
echo 0A& >com1

Premettendo che il MAX232 è collegato bene visto che l'ho usato diverse volte, non so per quale motivo la comunicazione non funziona a dovere, infatti tutto fila liscio soltanto se invio un solo carattere. Come vedete il file bat contiene solo due istruzioni, la prima riga setta i parametri per la comunicazione con la porta seriale e successivamente invia la stringa "0A&".
Qui sotto invece inserisco lo sketch che uso sull'arduino.
Quote

// variabili per la gestione del protocollo seriale
 char serialBuffer[40]; // buffer per i messaggi che arrivano dalla seriale
 int indiceBuffer = 0; // variabile per contenere l'indice dell'array
 boolean msgTrasmesso = false;// dice se il messaggio è stato trasmesso
 
void setup()
{
 delay(2000);
 Serial.begin(9600);
}

void loop()
{
 /* trasmetto un solo carattere e funziona
 if(Serial.available())
 {
   char lettera = Serial.read();
   if(lettera == 'A')
   {
     accensione();
   }
   else if(lettera == 'B')
   {
     spegnimento();
   }
 }
 */
 if(Serial.available())
 {
   char lettera = Serial.read();
   if(lettera != '&')// '&' è il carattere di fine messaggio
   { // se quello che arriva è diverso dal carattere di fine messaggio
     serialBuffer[indiceBuffer] = lettera;// popola l'array del buffer
     indiceBuffer++;//incrementa l'indice dell'array del buffer per dare la posizione al carattere successivo
   }
   else // se è arrivato il carattere di fine messaggio
   {
     indiceBuffer = 0; // l'indice ritorna a 0
     msgTrasmesso = true; // il messaggio è stato trasmesso
   }
 }
 // analizza il buffer
 if(msgTrasmesso == true)
 {
   switch(serialBuffer[0])
   {
     case '0':
     {
       switch(serialBuffer[1])
       {
         case 'A':
         {
           accensione();
         }
         break;
         case 'B':
         {
           spegnimento();
         }
         break;
       }
       memset(serialBuffer,0,sizeof(serialBuffer)); // svuota il buffer
       msgTrasmesso = false;
     }
     break;
     default: // se arriva qualcosa non previsto svuota il buffer
     {
       memset(serialBuffer,0,sizeof(serialBuffer));
       msgTrasmesso = false;
     }
   }
 }
}

Le istruzioni commentate nel loop le ho inserite per vedere se effettivamente arriva qualche dato e funzionano alla perfezione; in questo modo trasmetto un solo carattere dal file bat.
Lo sketch che non mi funziona invece prevede l'arrivo di più caratteri: il primo '0', il secondo 'A' e infine il carattere '&' che ho utilizzato come carattere di fine messaggio. Ogni volta che arriva un carattere e se questo è diverso da '&', lo vado ad inserire in un array incrementandone l'indice fino a quando non arriva il carattere di fine messaggio (l'ho spiegato da cani, ma credo che si capisca dai....).  Giusto per completare il discorso dico che entrambi gli switch che ho messo mi servono perchè devo gestire più messaggi.
Perchè non funziona questo codice? Mi sa che mi sto perdendo per una sciocchezza....
Help  

Edit:
So che la faccenda di incrementare l'indice per l'array è proprio una porcheria, avevo provato con la funzione while(Serial.available()) ma non funzionava ugualmente....

astrobeed

L'errore è nel file bat, se lo lanci da finestra dos (CMD) ti viene fornito un errore "sintassi del comando errata".
Quello che da fastidio è il carattere '&' perché è utilizzato dalla sintassi per la redirezione dell'output pertanto non è possibile usarlo come carattere da inviare.
Usa un differente carattere come terminatore d'invio, p.e. la @, ricordati che ti viene sempre aggiunto un 0x0A e un 0x0D (CR e LF) alla fine della stringa e tanti 0x20 (spazio) per ogni spazio compreso tra la fine della stringa e il simbolo di redirezione (>).


pelletta

Quote
ricordati che ti viene sempre aggiunto un 0x0A e un 0x0D (CR e LF) alla fine della stringa

Caspita che bella seccatura... mi pareva strano che dipendesse dal codice sull'arduino.
Mi sa che installerò processing su quel pc per dialogare con l'arduino, in fondo mi permette di fare molte più cose.
Grazie per l'aiuto.

contecavour

Ecco il tuo esempio è la prima cosa che si avvicina alle domande che mi facevo.
L'ho trovato per caso mettendo COMUNICAZIONE SERIALE STRING, ma in 3 pagina.

Adesso lo provo.
Ciao

contecavour

Finalmente qualcosa che mi aiuta.
Ho modificato il codice in modo che scriva lo stato e mi va

Code: [Select]
// variabili per la gestione del protocollo seriale
  char serialBuffer[40]; // buffer per i messaggi che arrivano dalla seriale
  int indiceBuffer = 0; // variabile per contenere l'indice dell'array
  boolean msgTrasmesso = false;// dice se il messaggio è stato trasmesso
 
void setup()
{
  delay(2000);
  Serial.begin(9600);
}

void loop()
{
  if(Serial.available())
  {
    char lettera = Serial.read();
    if(lettera != '&')// '&' è il carattere di fine messaggio
    { // se quello che arriva è diverso dal carattere di fine messaggio
      serialBuffer[indiceBuffer] = lettera;// popola l'array del buffer
      indiceBuffer++;//incrementa l'indice dell'array del buffer per dare la posizione al carattere successivo
    }
    else // se è arrivato il carattere di fine messaggio
    {
      indiceBuffer = 0; // l'indice ritorna a 0
      msgTrasmesso = true; // il messaggio è stato trasmesso
    }
  }
  // analizza il buffer
  if(msgTrasmesso == true)
  {
    switch(serialBuffer[0])
    {
      case '0': //zero
      {
        switch(serialBuffer[1])
        {
          case 'A':
          {
            Serial.println("Accensione");
          }
          break;
          case 'B':
          {
            Serial.println("Spengo");
          }
          break;
        }
        memset(serialBuffer,0,sizeof(serialBuffer)); // svuota il buffer
        msgTrasmesso = false;
      }
      break;
      default: // se arriva qualcosa non previsto svuota il buffer
      {
        memset(serialBuffer,0,sizeof(serialBuffer));
        msgTrasmesso = false;
      }
    }
  }
}


Grazie Pelletta


pelletta


Michele Menniti


Prego  :)

classico esempio di come il malato diventa medico XD
Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

?R

scusate se mi intrometto con una domanda che c'entra poco con l'argomento trattato, ma ho da tempo questa curiosità: cosa serve il delay di 2 secondi prima del begin della seriale? lo vedo spesso in giro, io non l'ho mai usato (non mi piace molto l'idea di aspettare 2 secondi prima che l'arduino entri in azione :smiley-sweat:), ma vorrei capire se e perchè dovrei usarlo, grazie ;)
Riccardo Ertolupi of the Vicenza Thunders Team: http://www.VicenzaThunders.com

contecavour

Da esperienze personali direi che pulisce eventuali residui o segnali dovuti al boot o allo start di Arduino, ma non so. Sto cercando anche io di capire bene i delay e i flussi. Anzi se qualcuno sa darmi consigli per capire flusso, delay e problematiche legate a questo. Ad esempio se chiamo una funzione nel loop, è sincrona o asincrona? Esiste qualcosa di asincrono a parte gli interrupt? Gli interrupt interrompono anche un delay? La seriale continua a bufferizzare tranquillamente anche se sono in un delay vero?

Chi mi sa dare consigli di dove trovare documentazione ben fatta su questa problematica con esempi?
Grazie

leo72


scusate se mi intrometto con una domanda che c'entra poco con l'argomento trattato, ma ho da tempo questa curiosità: cosa serve il delay di 2 secondi prima del begin della seriale? lo vedo spesso in giro, io non l'ho mai usato (non mi piace molto l'idea di aspettare 2 secondi prima che l'arduino entri in azione :smiley-sweat:), ma vorrei capire se e perchè dovrei usarlo, grazie ;)

Serve se devi collegare l'Arduino al PC, altrimenti puoi toglierlo.
In pratica inserisce un ritardo nell'inizio della trasmissione permettendo all'utente di uploadare una versione aggiornata dello sketch. Se avessi un codice che inizia a trasmettere una grossa mole di dati, non avresti materialmente il tempo di aprire il terminale seriale e ti ritroveresti con il buffer di trasmissione intasato (classico led RX acceso fisso) con l'impossibilità di spedire alla scheda un nuovo sketch perché l'8U2 non riesce a comunicare con il bootloader del 328.

?R



scusate se mi intrometto con una domanda che c'entra poco con l'argomento trattato, ma ho da tempo questa curiosità: cosa serve il delay di 2 secondi prima del begin della seriale? lo vedo spesso in giro, io non l'ho mai usato (non mi piace molto l'idea di aspettare 2 secondi prima che l'arduino entri in azione :smiley-sweat:), ma vorrei capire se e perchè dovrei usarlo, grazie ;)

Serve se devi collegare l'Arduino al PC, altrimenti puoi toglierlo.
In pratica inserisce un ritardo nell'inizio della trasmissione permettendo all'utente di uploadare una versione aggiornata dello sketch. Se avessi un codice che inizia a trasmettere una grossa mole di dati, non avresti materialmente il tempo di aprire il terminale seriale e ti ritroveresti con il buffer di trasmissione intasato (classico led RX acceso fisso) con l'impossibilità di spedire alla scheda un nuovo sketch perché l'8U2 non riesce a comunicare con il bootloader del 328.

ahn ok, grazie per la spiegazione! ;)


Gli interrupt interrompono anche un delay? La seriale continua a bufferizzare tranquillamente anche se sono in un delay vero?

da quel che so io gli interrupt interropono i delay mentre la seriale continua a bufferizzare durante un delay
Riccardo Ertolupi of the Vicenza Thunders Team: http://www.VicenzaThunders.com

contecavour

Grazie.

Negli test che avevo fatto a giugno mi succedevano cose strane, ma son sempre piu convinto che fosse dovuto alla saturazione della memoria con l'UNO con tutte le librerie. Da quando uso il MEGA mi sembra tutto piu lineare.

?R

io con l'arduino mega avevo avuto problemi sugli interrupt 2,3,4 e 5 che non andavano come previsto (http://arduino.cc/forum/index.php/topic,98312.msg755517.html#msg755517) però non li ho mai risolti perchè non ho avuto tempo....
Riccardo Ertolupi of the Vicenza Thunders Team: http://www.VicenzaThunders.com

Michele Menniti

Per quanto ne so l'interrupt ha priorità sulle normali attività del processore ma non sul delay che è un "blocco a tmpo" del processore, durante il quale esso non reagisce a nessun tipo di attività esterna. Per dare efficacia assoluta all'interrupt è decisamente preferibile ricorrere a millis piuttosto che a delay.
Guida alla programmazione ISP e seriale dei micro ATMEL (Caricare bootloader e sketch):
http://www.michelemenniti.it/Arduino_burn_bootloader.php
Guida alla Programmazione ATmega328 noP:
http://www.michelemenniti.it/atmega328nop.html
Articoli su Elettronica In:
http://www.michelemenniti.it/elettronica_in.html

?R


Per quanto ne so l'interrupt ha priorità sulle normali attività del processore ma non sul delay che è un "blocco a tmpo" del processore, durante il quale esso non reagisce a nessun tipo di attività esterna. Per dare efficacia assoluta all'interrupt è decisamente preferibile ricorrere a millis piuttosto che a delay.

adesso mi viene il dubbio :smiley-red:, se non ricordo male tempo fa mi era stato detto che un interrupt hardware interrompeva anche la funzione pulseIn oltre che alla funzione delay, forse proprio in quel topic che ho linkato prima, ma penso che leo ne sappia qualcosa di più a riguardo...
Riccardo Ertolupi of the Vicenza Thunders Team: http://www.VicenzaThunders.com

Go Up