valore numerico da un array e assegnazione a variabile intera

Buongiorno a tutti, premetto che mi sono avvicinato al mondo di arduino e alla programmazione in generale da poco quindi vorrei chiedervi qualche suggerimento per uno sketch che sto realizzando a scopo di studio.
Il programma prevede l’inserimento di un testo da seriale del tipo: “ciao arduino” e il programma restituisce un messaggio di testo: “Benvenuto inserisci un valore”.
Ecco lo sketch:

char inData[20]; 
char inChar; 
byte index = 0;
int primoValore = 0;
int secondoValore = 0;
char Comp(char* This) {
  while (Serial.available() > 0)
  {
    if (index < 19)
    {
      inChar = Serial.read(); 
      inData[index] = inChar;
      index++;
      inData[index] = '\0';
      }
    }

  if (strcmp(inData, This)  == 0) 
  {
    for (int i = 0; i < 19; i++) 
    {
      inData[i] = 0;
    }
    index = 0;
    return (0);

  }
  else 
  {
    return (1);
  }
}

void setup() {
  Serial.begin(9600);
}

void loop() {

  if (Comp("ciao arduino") == 0)
  {
    Serial.println("Benvenuto inserisci un valore");
  }
}

A questo punto per complicarmi la vita vorrei poter inserire da seriale un testo tipo: “valoreA56” e che il programma fosse in grado di “estrapolare”(scusate il termine) il valore numerico quindi in questo caso “56”, e lo assegnasse alla variabile intera “primoValore”
In caso invece scrivessi ad esempio “valoreB72” il 72 venisse assegnato alla variabile “secondoValore”.
Io ci ho messo tutto il mio buon impegno e cercato soluzioni ovunque, ma non ne vengo a capo…
Spero di essere stato abbastanza chiaro e vi ringrazio anticipatamente per i vostri consigli e suggerimenti!

Ciao, essendo il tuo primo post, ti chiederei di presentarti QUI (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto ;)) e di leggere con attenzione il REGOLAMENTO ... Grazie. :)

Guglielmo

Ciao, ci sono varie strade da poter intraprendere, esempio se il numero è composto da due cifre, prelevi le ultime due cifre e con la funzione atoi() li trasformi in numeri interi.

per quanto riguarda le strighe, valoreB34 o valoreA34, sono stringhe come tutte le altre, e quindi puoi usare strcmp() per verificare se è una o l’altra striga.

Ti posto una funzione che preleva il numero finale di una stringa, e lo restituisce come intero.

int PrelevaNumero(char *s){
    
    
    int i=0,j=0;
    char numero[10];
    for(i=0;!(s[i]>='0' && s[i]<='9');i++); // Trova inizio numero
    for(j=0;s[i]!=0;j++,i++){
        
        numero[j]=s[i];
    }    
    
    numero[j]=0;//terminatore stringa
    
    return atoi(numero);
    
}    

/* Esempio 
    
    char stringa[]="testoconnumero345";


    int valore=PrelevaNumero(stringa);

   --------------
   valore contiene 345 */

gpb01: Ciao, essendo il tuo primo post, ti chiederei di presentarti QUI (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto ;)) e di leggere con attenzione il REGOLAMENTO ... Grazie. :)

Guglielmo

Ciao Guglielmo avevo letto il regolamento cercando proprio la parte delle presentazioni ma mi deve essere sfuggita... comunque provvedo, grazie

marcbonny: Ciao Guglielmo avevo letto il regolamento cercando proprio la parte delle presentazioni ma mi deve essere sfuggita... comunque provvedo, grazie

... nessun problema ;), è nel punto 13, primo paragrafo. Grazie a te :)

Guglielmo

Intanto ringrazio torn24, sto provando ad applicare il tuo esempio al mio sketch anche se per ora con esiti deludenti...

torn24:
Ciao, ci sono varie strade da poter intraprendere, esempio se il numero è composto da due cifre, prelevi le ultime due cifre e con la funzione atoi() li trasformi in numeri interi.

per quanto riguarda le strighe, valoreB34 o valoreA34, sono stringhe come tutte le altre, e quindi puoi usare strcmp() per verificare se è una o l’altra striga.

Ti posto una funzione che preleva il numero finale di una stringa, e lo restituisce come intero.

int PrelevaNumero(char *s){

int i=0,j=0;
    char numero[10];
    for(i=0;!(s[i]>=‘0’ && s[i]<=‘9’);i++); // Trova inizio numero
    for(j=0;s[i]!=0;j++,i++){
       
        numero[j]=s[i];
    }   
   
    numero[j]=0;//terminatore stringa
   
    return atoi(numero);
   
}

/* Esempio
   
    char stringa=“testoconnumero345”;

int valore=PrelevaNumero(stringa);

--------------
  valore contiene 345 */

Scusa torn24 ma la cosa mi sta sfuggendo di mano… non è che potresti farmi vedere esattamente come applicare il tuo esempio al mio sketch perché la confusione del principiante sta prendendo il sopravvento in me :frowning:

Ci ho perso 10 minuti, perché se non si mette un delay() la lettura della seriale non funziona…

Provato e funzionante

/*
A questo punto per complicarmi la vita vorrei poter inserire da seriale un testo tipo: "valoreA56"
 e che il programma fosse in grado di "estrapolare"(scusate il termine) il valore numerico quindi in questo caso "56", 
 e lo assegnasse alla variabile intera "primoValore"
In caso invece scrivessi ad esempio "valoreB72" il 72 venisse assegnato alla variabile "secondoValore".


*/



char inData[20]; 
char inChar; 
byte index = 0;
int primoValore = 0;
int secondoValore = 0;


void setup() {
  Serial.begin(9600);
}

void loop(){

  int i=0;
  char c; 
  while (Serial.available() > 0)//Leggo tutta la stringa trasmessa da seriale
  {
      if (index < 19)
      {
          inChar = Serial.read(); 
          inData[index] = inChar;
          index++;
          inData[index] = '\0'; 
          delay(10);
      }
       
  }//end while
  index=0;//Azzero il contatore per la stringa sucessiva
    
    
    if (strcmp(inData, "ciao arduino")  == 0) 
    {
        Serial.println("Benvenuto inserisci un valore");
        Azzera(inData);

    }
    else{// Se la stringa � diversa da "ciao arduino"
            
           
	
	    for(i=0;inData[i]!=0;i++){// Scorre tutta la striga alla ricerca di 'A' O 'B'
		 
	        if(inData[i]=='A' || inData[i]=='B'){
			
			    c=inData[i];
				break;//Esce dal for se trova A o B
			}
	    }// end for
		
		if(c=='A'){
		
		    primoValore=PrelevaNumero(inData);
                    Serial.println(primoValore);
                    Azzera(inData);
		}
		else if(c=='B'){
		    secondoValore=PrelevaNumero(inData);
                    Serial.println(secondoValore);
                    Azzera(inData);
                }
	}//end else
  
  
}


int PrelevaNumero(char *s){
    
    
    int i=0,j=0;
    char numero[10];
    for(i=0;!(s[i]>='0' && s[i]<='9');i++); // Trova inizio numero
    for(j=0;s[i]!=0;j++,i++){
        
        numero[j]=s[i];
    }    
    
    numero[j]=0;//terminatore stringa
    
    return atoi(numero);
    
}   

void Azzera(char *s){

    int i=0;
    for(i=0;i<19;i++)
        s[i]=0;
}

torn24: Ci ho perso 10 minuti, perché se non si mette un delay() la lettura della seriale non funziona..

... si, è bene che ci sia una piccola delay(), ma ... 200 mS mi sembrano veramente troppi ... ti dico che normalmente io uso 1 o 2 mS (che, a 9600 baud, sono circa 1 o 2 caratteri) ;)

Guglielmo

Modificato delay() da 200 a 10, per stare sul sicuro, grazie dell'informazione :)

torn24:
Ci ho perso 10 minuti, perché se non si mette un delay() la lettura della seriale non funziona…

Provato e funzionante

/*

A questo punto per complicarmi la vita vorrei poter inserire da seriale un testo tipo: “valoreA56”
e che il programma fosse in grado di “estrapolare”(scusate il termine) il valore numerico quindi in questo caso “56”,
e lo assegnasse alla variabile intera “primoValore”
In caso invece scrivessi ad esempio “valoreB72” il 72 venisse assegnato alla variabile “secondoValore”.

*/

char inData[20];
char inChar;
byte index = 0;
int primoValore = 0;
int secondoValore = 0;

void setup() {
  Serial.begin(9600);
}

void loop(){

int i=0;
  char c;
  while (Serial.available() > 0)//Leggo tutta la stringa trasmessa da seriale
  {
      if (index < 19)
      {
          inChar = Serial.read();
          inData[index] = inChar;
          index++;
          inData[index] = ‘\0’;
          delay(10);
      }
     
  }//end while
  index=0;//Azzero il contatore per la stringa sucessiva
   
   
    if (strcmp(inData, “ciao arduino”)  == 0)
    {
        Serial.println(“Benvenuto inserisci un valore”);
        Azzera(inData);

}
    else{// Se la stringa � diversa da “ciao arduino”

    for(i=0;inData[i]!=0;i++){// Scorre tutta la striga alla ricerca di 'A' O 'B'
	 
        if(inData[i]=='A' || inData[i]=='B'){
		
		    c=inData[i];
			break;//Esce dal for se trova A o B
		}
    }// end for
	
	if(c=='A'){
	
	    primoValore=PrelevaNumero(inData);

Serial.println(primoValore);
                    Azzera(inData);
}
else if(c==‘B’){
    secondoValore=PrelevaNumero(inData);
                    Serial.println(secondoValore);
                    Azzera(inData);
                }
}//end else
 
 
}

int PrelevaNumero(char *s){
   
   
    int i=0,j=0;
    char numero[10];
    for(i=0;!(s[i]>=‘0’ && s[i]<=‘9’);i++); // Trova inizio numero
    for(j=0;s[i]!=0;j++,i++){
       
        numero[j]=s[i];
    }   
   
    numero[j]=0;//terminatore stringa
   
    return atoi(numero);
   
}

void Azzera(char *s){

int i=0;
    for(i=0;i<19;i++)
        s[i]=0;
}

Torn24 e Gpb01 intanto vi ringrazio molto per la pazienza e l’impegno speso a modificare questo sketch, c’è però un problema… ho provato a caricare il programma ma la seriale non mi restituisce più nulla nemmeno l’unica parte che ero riuscito a far funzionare (ciao arduino → Benvenuto inserisci un valore). Torn24 hai detto di averlo testato, e allora non capisco quale sia il mio problema…
Ho provato nel setup ad inserire:
Serial.write(“avvio”);
tanto per verificare se qualcosa venisse stampato, ma all’apertura del monitor seriale vengo inondato da una sequenza di 5 e ogni tanto 7, 0, 9. (Premetto che la seriale è impostata correttamente a 9600 baud)

non si fa certo così a leggere un stringa....

do
{
    while( !Serial.available());
    buffer[i] = Serial.read();
}while( buffer[i++] != '\n');
buffer[i] = '\0';

e da Serial monitor ti assicuri che venga inviato l'enter in basso a destra vicino al baud rate.

Infine per chi inizia, forse, sarebbe meglio utilizzare gli strumenti creati appositamente per loro. In questo caso Serial.readStringUntil()

Torn24 hai detto di averlo testato,

Ciao, di solito non posso provare il programma perché non ho l'elettronica o non ho voglia di fare il circuito :)

Ma nel tuo caso non c'è nessun circuito, e quindi ho voluto testare per darti una soluzione funzionante, io ho caricato e provato, e a me funziona correttamente.

Comunque, l'unico problema che potrebbe esserci è appunto la lettura da seriale, puoi provare due strade, aumenta il valore di delay(70), usa la versione di vbexstreme per la lettura da seriale.

Ma come detto, a me funziona correttamente, se da seriale invio "ciao arduino" mi risponde, se invio da seriale "valoreA344" mi ritorna il numero e cosi anche per "valoreB234", nella stringa con numero, ci deve essere una A maiuscola o una B maiuscola, come da tuo esempio...

vbextreme: Infine per chi inizia, forse, sarebbe meglio utilizzare gli strumenti creati appositamente per loro. In questo caso Serial.readStringUntil()

Premesso che NON sono mai d'accordo nell'uso di quei metodi ampiamente diseducativi (... e quando impareranno mai qualche cosa se usano quelle cose), in questo caso sono ancora meno d'accordo visto che marcbonny sta già a buon punto nell'utilizzo dei "corretti" strumenti per la lettura della seriale e per la comprensione di come si fa !

Inoltre, nel suo caso, probabilmente il problema è un altro (collegamenti) visto che il programma di torn24 funziona ... ::)

Guglielmo

@gbp01 io invece penso che questa è la strada diseducativa. La prima cosa da imparare nella comunicazione seriale è che si necessità di un carattere per terminare l'input. Questo meccanismo viene subito appreso dalla funzione precedentemente linkata.

Un'altra parte fondamentale è che se il codice funziona non è detto che funzioni. Per avere un codice realmente funzionante deve essere stabile, solido e funzionare in tutti i contesti. In questo caso funzionerà solo a caso perché non vi è alcuna logica nell'algoritmo. Si usano metodi poco ortodossi e ci si dimentica delle più classiche funzioni C quali ad esempio strtol.

Non sono d'accordo con Vbexstreme, anche se ha pianamente ragione :)

I motivi sono, non tutte le persone che usano e voglio imparare ad usare arduino, sono o saranno, programmatori o elettronici, chi partecipa a questo forum dovrebbe sapere come è nato e per quale scopo arduino, è da ritenersi fuori previsione, che i professionisti siano entrati in questo mondo, nato "per i non addetti ai lavori" e non viceversa.

Un altro motivo, come viene richiesto negli esercizi di linguaggio C di implementare funzioni tipo, strlen, strcat ecc.. dovrebbe essere più educativo, crearsi una propria funzione che utilizzarne una di libreria.

Concludo, ricordiamoci in che comunità siamo, ricordiamoci lo spirito del mondo arduino, perché risposte o commenti, dati in forum di programmazione sono pertinenti, dati qui, mi sembrano che non combaciano con le idee dei fondatori :) "non penso che pretendessero la conoscenza della libreria standar C :)"

la logica, secondo me c'è, abbiamo bisogno di un terminatore per sapere quando è terminata la trasmissione, ma usando Serial.available()>0, sappiamo se ci sono o sono terminati i byte o caratteri, quindi possiamo evitare il terminatore.

vbextreme: @gbp01 io invece penso che questa è la strada diseducativa. La prima cosa da imparare nella comunicazione seriale è che si necessità di un carattere per terminare l'input ....

Su questo sono sono pienamente d'accordo, difatti il codice di torn24 [u]è un punto di partenza, non di arrivo[/u] ... ... il mio commento era riferito a quei metodi a cui ti riferivi (le "pappe pronte" della classe Serial) e sai bene quanto per primo io spinga l'uso della AVR libc e di tutte le funzioni che contiene ;)

Guglielmo

x Torn24: Ciao non intendevo assolutamente mettere in dubbio che tu avessi testato lo sketch, ci mancherebbe...anzi grazie di nuovo per averci perso 10 minuti, volevo solo dire che trovo strano che a me non funzioni e sto cercando ancora di capire il perché. Ho provato anche con un'altra scheda Arduino per escludere che il malfunzionamento non fosse proprio dovuto alla scheda, ma niente da fare.

xgpb01: In che senso ho sbagliato i collegamenti? sulla scheda non ho collegato niente a parte l'usb :-) oltre a fare il classico copia e incolla del programma di Torn24 non ho fatto altro...

x vbextreme: ho provato anche il tuo esempio ma se provo ad inviare ad esempio A ottengo in risposta A se poi invio B ottengo AB se poi invio C ricevo ABC e così via, insomma i valori si accumulano

marcbonny: xgpb01: In che senso ho sbagliato i collegamenti? sulla scheda non ho collegato niente a parte l'usb :-) oltre a fare il classico copia e incolla del programma di Torn24 non ho fatto altro...

... pedona, mia confusione ... ero convinto che usassi un adattatore seriale ... :)

Allora la cosa è strana ... ... ma stai digitando tutti e i 19 caratteri richiesti ? ... perché, come si diceva con VB, quello è un inizio, non un punto di arrivo, manca appunto la gestione del terminatore, che VB a messo a CR, mente il programma di torn24 vuole tutta la stringa che gli hai detto ...

Per provare bene quello di VB ... dei fare si che l'emulatore di terminale trasmetta il CR a fine stringa (che è un po' lo standard).

Guglielmo

La lettura con terminatore newline, che devi selezionare sulla finestra della seriale, in basso a destra selezioni, nessun terminatore o newline o cr e newline, devi selezionare solo nuova riga e non cr.

L’esempio di vbexstreme adattato al tuo codice "aggiunta di dalay() e eliminazione del carattere ‘\n’ "… anche questo funzionante.

Ma penso che non hai problema di programmi, il tuo problema è sicuramente altro, se hai arduino uno o clone, una volta testato su una scheda di solito va su tutte :slight_smile:

char inData[20]; 
char inChar; 
byte index = 0;
int primoValore = 0;
int secondoValore = 0;


void setup() {
  Serial.begin(9600);
}

void loop(){

  int i=0;
  char c; 
 
     do
    {
        while( !Serial.available());
        inData[index] = Serial.read();
        delay(10);
        
    }while( inData[index++] != '\n');

    inData[--index] = '\0';//sovrascrivo il \n

    index=0;
    
    if (strcmp(inData, "ciao arduino")  == 0) 
    {
        Serial.println("Benvenuto inserisci un valore");
        Azzera(inData);

    }
    else{// Se la stringa ? diversa da "ciao arduino"
            
           
	
	    for(i=0;inData[i]!=0;i++){// Scorre tutta la striga alla ricerca di 'A' O 'B'
		 
	        if(inData[i]=='A' || inData[i]=='B'){
			
			    c=inData[i];
				break;//Esce dal for se trova A o B
			}
	    }// end for
		
		if(c=='A'){
		
		    primoValore=PrelevaNumero(inData);
                    Serial.println(primoValore);
                    Azzera(inData);
		}
		else if(c=='B'){
		    secondoValore=PrelevaNumero(inData);
                    Serial.println(secondoValore);
                    Azzera(inData);
                }
	}//end else
  
  
}


int PrelevaNumero(char *s){
    
    
    int i=0,j=0;
    char numero[10];
    for(i=0;!(s[i]>='0' && s[i]<='9');i++); // Trova inizio numero
    for(j=0;s[i]!=0;j++,i++){
        
        numero[j]=s[i];
    }    
    
    numero[j]=0;//terminatore stringa
    
    return atoi(numero);
    
}   

void Azzera(char *s){

    int i=0;
    for(i=0;i<19;i++)
        s[i]=0;
}