Ancora problemi con stringhe e la porta seriale di Arduino

Ciao a tutti ragazzi, qualche giorno fa ho creato un topic nel quale cercavo di salvare dei dati su EEPROM. Adesso mi sono accordo che per poter andare a salvare più dati (ricevuti da porta seriale) devo cercare di leggere delle stringhe per poi manipolarle ed estrarre i dati da queste.

Cercando e ricercando sul forum ho trovato qualche codice, e alla fine sono riuscito a scrivere questo

int led=13;
String stringa;                                        // stringa ricevuta

void setup() {
  pinMode(led, OUTPUT);
  Serial.begin(9600);
}

void loop() {

  stringa = "";                                     // azzera stringa

  while (Serial.available() > 0) {              // ricezione da Serial Monitor
    stringa += char(Serial.read());               // aggiungi carattere alla stringa 
  }

  stringa.trim();                                   // elimina spazi iniziali e finali
  stringa.toLowerCase();                            // converti in minuscolo

  if (stringa == "accendi") digitalWrite(led, HIGH);
  else if (stringa == "spegni") digitalWrite(led, LOW);
}

perchè non funziona??non riesco proprio a capirlo

Stampa il contenuto di stringa sulla seriale prima del confronto.

niente...ho provato a inserire

Serial.print(stringa);

subito dopo il ciclo while ma non mi scrive niente...

Appunto.

Ecco perché il test successivo fallisce.

Devi battezzare un carattere come "fine delle trasmissioni" a riempier la stringa fino a che non vedi quel byte. A quel punto puoi fare il confronto per capire che comando hai ricevuto.

se non hai un carattere di chiusura potresti usare

 while (Serial.available() > 0) {              // ricezione da Serial Monitor
    stringa += char(Serial.read());               // aggiungi carattere alla stringa 
 if string.indexof di stringa == accendi >>>  esegui ....
  }

Sì, ma in quel caso dovrebbe anche preoccuparsi di togliere il comando identificato dalla stringa di accumulo, altrimenti quella cresce fino a far resettare il micro. Nel caso "classico" del carattere di terminazione la cosa è più semplice perché basta "svuotare" la stringa di accumulo ogni volta che lo si riceve.

Comunque sarebbe meglio usare un char[], non String.

Allora ragazzi ho messo un carattere di fine stringa che io ho indicato con il punto. Quindi ogni qual volta che dovrebbe trovare questo benedetto punto la lettura dovrebbe interrompersi. Ad esempio se io mando tramite seriale la parola "accendi." appena vede il punto dovrebbe interrompere l'acquisizione. Il codice che ho scritto è questo:

int led=13;
String stringa;                                        // stringa ricevuta

void setup() {
  pinMode(led, OUTPUT);
  Serial.begin(9600);
}

void loop() {

  stringa = "";                                     // azzera stringa

  while (Serial.available() > 0 && (Serial.read() != '.')) {    // ricezione da Serial Monitor
    stringa += char(Serial.read());               // aggiungi carattere alla stringa 
  }
  //delay(4000);
  //Serial.print(stringa);

  stringa.trim();                                   // elimina spazi iniziali e finali
  stringa.toLowerCase();                            // converti in minuscolo

  if (stringa == "accendi") digitalWrite(led, HIGH);
  else if (stringa == "spegni") digitalWrite(led, LOW);
}

ma ancora non funzionaaaa :(

cmqe ritornando alla questione char[] o string ho preferito scegliere la soluzione delle string perchè innazi tutto gli operatori di stringa sono molto più semplici, cioè per catenare ho visto che basta utilzzare la sintassi stringa1 + stringa 2...ecc...

poi per quanto riguarda i char[] ho visto che questi devono essere dichiarati e dimensionati a priori e il bello è che non so quanto sarà lunga questa stringa...

almeno queste sono nozioni che ho imparato nel giro di una settimana avendo arduino davanti...se ci sono scappatoie fatemi sapere!sono qui per imparare :D

tuxduino: Sì, ma in quel caso dovrebbe anche preoccuparsi di togliere il comando identificato dalla stringa di accumulo, altrimenti quella cresce fino a far resettare il micro. Nel caso "classico" del carattere di terminazione la cosa è più semplice perché basta "svuotare" la stringa di accumulo ogni volta che lo si riceve.

Comunque sarebbe meglio usare un char[], non String.

ok allora

while (Serial.available() > 0) {              // ricezione da Serial Monitor
    stringa += char(Serial.read());               // aggiungi carattere alla stringa 
    if string.indexof di stringa == accendi >>>  
     { 
       string="";
       esegui ....
     }
  }

ma la mia soluzione con il punto nel ciclo while non va bene??

hermit274: ma la mia soluzione con il punto nel ciclo while non va bene??

No, perché chiami Serial.available() ad un ritmo rapidissimo, mentre i caratteri impiegano un tempo molto più lungo per arrivare. Devi uscire dal ciclo di ricezione quando hai ricevuto il carattere di fine riga (il punto va benissimo) oppure dopo un certo timeout, oppure quando hai ricevuto un certo numero massimo di caratteri ma il punto ancora non l'hai visto.

Poi devi mettere un tetto alla lunghezza del buffer di accumulo (cioè la String) altrimenti rischi di saturare la RAM.

Ragazzi non ci crederete ma ho risolto. Ma adesso voi dovete risolvermi questo dubbio fra questi due codici. Il primo non funziona, mentre il secondo si. Ma in sostanza sono identici!!Come mai???

void loop() {

  stringa = "";                                     // azzera stringa

  while (Serial.available() > 0) {    // ricezione da Serial Monitor  
    delay(10);
    if (char(Serial.read()) ==  '.'){
      break;
    }
    stringa += char(Serial.read());               // aggiungi carattere alla stringa 
  }

  stringa.trim();                                   // elimina spazi iniziali e finali
  stringa.toLowerCase();                            // converti in minuscolo

  if (stringa == "accendi") digitalWrite(led, HIGH);
  else if (stringa == "spegni") digitalWrite(led, LOW);
}

mentre il secondo che funziona è questo

void loop() {

  stringa = "";                                     // azzera stringa

  while (Serial.available() > 0) {    // ricezione da Serial Monitor  
    delay(10);
    char c = Serial.read();
    if (c == '.'){
      break;
    }
    stringa += c;               // aggiungi carattere alla stringa 
  }

  stringa.trim();                                   // elimina spazi iniziali e finali
  stringa.toLowerCase();                            // converti in minuscolo

  if (stringa == "accendi") digitalWrite(led, HIGH);
  else if (stringa == "spegni") digitalWrite(led, LOW);
}

?????????

Che cosa vuol dire

(char(Serial.read()) ==  '.')

Esiste forse una funzione char() ? Non capisco come possa compilare una roba del genere... ?

ok...capito.quindi era un problema di compilazione. Pensavo esistesse una funzione di quel tipo. Comunque tuxduino volevo chiederti se a questo punto come hai suggerito conviene meglio utilizzare un char[]. Per poterlo riempire sicuramente devo utilizzare un ciclo, ma poi per poterci smanettare sopra?quali funzioni posso utilizzare? Ad esempio per concatenare, cercare dei caratteri, sostituirli valgono esattamente le stesse funzioni del C? Devo importare le librerie string.h??

Stiamo parlando di C-string, cioè char[] con la convenzione che la stringa è termianta da un byte nullo. Tutte le funzioni della famiglia str* funzionano su questa convenzione. Per aggiungere caratteri tieni un contatore e accedi direttamente a stringa[cnt], per il confronto usa strcmp().