Pages: [1] 2 3   Go Down
Author Topic: Problema con la seriale  (Read 2668 times)
0 Members and 1 Guest are viewing this topic.
Marche
Offline Offline
Edison Member
*
Karma: 34
Posts: 2276
azioni semplici per risultati complessi
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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....
« Last Edit: May 19, 2011, 06:10:36 pm by Pelletta » Logged

Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 137
Posts: 9752
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 (>).

Logged

Marche
Offline Offline
Edison Member
*
Karma: 34
Posts: 2276
azioni semplici per risultati complessi
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Milan
Offline Offline
Sr. Member
****
Karma: 0
Posts: 375
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Milan
Offline Offline
Sr. Member
****
Karma: 0
Posts: 375
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
// 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

Logged

Marche
Offline Offline
Edison Member
*
Karma: 34
Posts: 2276
azioni semplici per risultati complessi
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Prego  smiley
Logged

Lamezia Terme
Offline Offline
Shannon Member
****
Karma: 574
Posts: 12661
Le domande di chi vuol imparare rappresentano la sua sete di sapere
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Prego  smiley
classico esempio di come il malato diventa medico smiley-lol
Logged


Camisano Vicentino (VI), Italy
Offline Offline
God Member
*****
Karma: 5
Posts: 956
ƎR like no other.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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 smiley-wink
Logged

Riccardo Ertolupi of the Vicenza Thunders Team: http://www.VicenzaThunders.com

Milan
Offline Offline
Sr. Member
****
Karma: 0
Posts: 375
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Global Moderator
Italy
Online Online
Brattain Member
*****
Karma: 333
Posts: 22975
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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 smiley-wink
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.
Logged


Camisano Vicentino (VI), Italy
Offline Offline
God Member
*****
Karma: 5
Posts: 956
ƎR like no other.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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 smiley-wink
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! smiley-wink

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
Logged

Riccardo Ertolupi of the Vicenza Thunders Team: http://www.VicenzaThunders.com

Milan
Offline Offline
Sr. Member
****
Karma: 0
Posts: 375
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Camisano Vicentino (VI), Italy
Offline Offline
God Member
*****
Karma: 5
Posts: 956
ƎR like no other.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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....
Logged

Riccardo Ertolupi of the Vicenza Thunders Team: http://www.VicenzaThunders.com

Lamezia Terme
Offline Offline
Shannon Member
****
Karma: 574
Posts: 12661
Le domande di chi vuol imparare rappresentano la sua sete di sapere
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged


Camisano Vicentino (VI), Italy
Offline Offline
God Member
*****
Karma: 5
Posts: 956
ƎR like no other.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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...
Logged

Riccardo Ertolupi of the Vicenza Thunders Team: http://www.VicenzaThunders.com

Pages: [1] 2 3   Go Up
Jump to: