Rientro in forum dopo anni scusate sto facendo delle prove per ambientarmi di nuovo

Come no? I tuoi comandi V0 V1 ecc li fai (ad esempio) precedere da un '#' e seguire da un '*' che rappresentano inizio e fine. In ricezione ti trovi l'array con dentro esattamente le tue stringhe, e in formato standard C, quindi testabili con la funzione strcmp:

if (strcmp(buffer, "V0") == 0) { ...... }

che funzione è???.......lo fai per confondermi ancora di più??? :thinking: :thinking: :grinning: :grinning: :grinning:

Si ma tu dovresti svuotare la stringa solo dopo aver riconosciuto un comando (quindi dentro a tutte le if) oppure quantomeno se il buffer, dopo le if, contiene esattamente 2 caratteri.

Se invece lo fai in quel punto, indipendentemente da cosa ricevi, potresti svuotare il buffer quando hai ricevuto ancora solo uno dei due caratteri (ed ecco perché coi delay sembri risolvere, semplicemente dai tempo di ricevere i due caratteri -comunque metodo non sicuro al 100%-).

Quando si devono fare comunicazioni di questo tipo, sempre meglio implementare un minimo di "protocollino" come suggerito. Quantomeno un carattere inziale come "*" (il terminatore non serve se i comandi sono sempre composti da 2 caratteri).

Ma inizia a studiare un poco le stringhe del C (al posto di "String") perché ti sarà utilissimo per imparare a programmare in modo più efficiente, e per evitare che in futuro i programmi possano darti seri malfunzionamenti o bloccarsi (questi sono gli "effetti" dell'uso di String purtroppo).

Ad esempio confrontare due stringhe si fa con la funzione strcmp() che già ti hanno indicato, invece di "==", ma una volta iniziato a comprendere come funzionano le stringhe C e come si gesticono, è tutto abbastanza facile.

Grazie a tutti ragazzi per i consigli.

void USA_BLUETOOTH()
{
 if(Serial2.available())        /*Se la seriale è attiva Bluetooth HC-08 Trasmette o Riceve*/
   { 
         
    while(Serial2.available()) /*Finchè è attiva*/
         { 
                    
          rx_2=Serial2.read();  /*"rx_2" assume il CARATTERE che riceve*/
          RX_2.concat(rx_2);    /*"RX_2" assume tutti i CARATTERI da "rx_2" in un unica STRINGA*/
          if(RX_2=="V0"){Velocita=0, RX_2="";} /*FERMO*/  
          if(RX_2=="V1"){Velocita=1, RX_2="";} /*LENTO*/    
          if(RX_2=="V2"){Velocita=2, RX_2="";} /*VELOCE*/  
          if(RX_2=="Av"){Direzione=1, RX_2="";}/*AVANTI*/
          if(RX_2=="In"){Direzione=2, RX_2="";}/*INDIETRO*/ 
          if(RX_2=="Dx"){Direzione=3, RX_2="";}/*DESTRA*/ 
          if(RX_2=="Sx"){Direzione=4, RX_2="";}/*SINISTRA*/
         } 
    }                            
} 
Grazie a tutti i consigli per il momento l'ho risolta cosi, secondo voi può andare??

Comunque non tornando al discorso Stringhe, effettivamente sono alle prime armi, ho fatto qualke prova documentandomi ma sono ancora indietro. 

Eh, meglio, ma non del tutto (ma scusa, che chiedi a fare, non puoi provarlo tu direttamente? :wink: ).

La cosa principale è che devi separare le istruzioni con ";" e non ",", quindi cambialo dentro ogni if() e dovrebbe andare.

Poi per semplificare e permetterti di gestire meglio questo "protocollino" ti vorrei consigliare di limitare i comandi ad UN carattere, perché ti basta, e puoi evitare anchele stringhe (in attesa che tu faccia esperienza anche con le stringhe C). Ossia non "V0" ma solo il carattere '0', non "Av" ma solo 'A', non "In" ma solo 'I' e così via. In pratica butta quella "String", e con un solo carattere ti basta usare come buffer la variabile "char rx_2", non devi concatenare nulla e quindi neanche "azzerare" il buffer perché lo leggi ogni volta.
Per riconoscere il comando quindi ti basta usare una istruzione "switch..case", tipo:

...
  
  switch(rx_2) {
    case '0':
      Velocita = 0;
      break;
    case '1':
      Velocita = 1;
      break;
    case '2':
      Velocita = 2;
      break;
    case 'A':
      Direzione = 1;
      break;
... eccetera

Per finire, qualche nota "stilistica" (ma non solo) che penso ti potranno essere utili.

Evita di chiamare variabili diverse distinguendole solo per le maiuscole (in quato caso "RX_2" e "rx_2") tanto più se poi sono persino di due tipi diversi (es. in futuro potresti identificare le stringhe con un prefisso tipo "str").

L'inizializzazione della variabile rx_2, poiché contiene un carattere e non una stringa, non va fatta con "" ma con un carattere (che si indica con il semplice apostrofo e non con virgolette).
In questo caso poi non serve neanche inizializzarla perché viene inserito un valore ad ogni uso per cui non esiste un "valore predefinito". Ad esempio non:

char rx_2="";

ma, se dovesse servire un "valore predefinito", es. '*':

char rx_2='*';

ma nel tuo caso puoi anche evitare di inizializzare un valore:

char rx_2;

Poi qui, non è ovviamente un errore ma si può evitare la prima if():

if(Serial2.available())        /*Se la seriale è attiva Bluetooth HC-08 Trasmette o Riceve*/
   {      
     while(Serial2.available())

Questo perché la prima if() è inutile perché la while già da sola fa quello che serve ossia se non ci sono caratteri non eseguirà nulla.

Per finire, le costanti:

const byte V_DSX(3);    /*Vin DX e SX*/
const byte R_dx_Av(24); /*RUOTE DX AVANTI*/
const byte R_dx_In(26); /*RUOTE DX INDIETRO*/
const byte R_sx_Av(30); /*RUOTE SX AVANTI*/
const byte R_sx_In(28);/*RUOTE SX INDIETRO*/

(modificato)
Dove hai trovato questa sintassi? Bene che tu abbia usato "byte", ma in genere esiste la convenzione di usare tutte maiuscole per le costanti (hai presente la HIGH, LOW, INPUT, eccetera che usi?).
Inoltre per commeti in singola riga usa solo "//" così eviti anche di dover mettere sempre la chiusura "*/".
Per progetti piccoli dove non ci sono problemi di ram puoi anche usare le più comuni "#define". Ossia:

const byte V_DSX   =  3 // Vin DX e SX
const byte R_DX_AV = 24 // RUOTE DX AVANT
const byte R_DX_IN = 26 // RUOTE DX INDIETRO
const byte R_SX_AV = 30 // RUOTE SX AVANTI
const byte R_SX_IN = 28 // RUOTE SX INDIETRO

(ovviamente poi aggiorna questi simboli all'interno del resto del codice).

docdoc, ti ricordo che ne abbiamo ampiamente parlato in passato e ... nel caso specifico ciò che ha scritto Puso produce un codice più "ottimizzato" (più piccolo)...

Se ricordi una lunga discussione di un paio di anni fa, si è chiaramente dimostrato che "const" e "#define" alla fine vengono compilate alla stessa maniera (grazie all'ottimizzazione che fa il compilatore), ma ... di default, prendendo una delle varie define qui sopra, "#define V_DSX 3" sostituisce ovunque incontri V_DSX con un "int" di due bytes di valore 3, mentre la definizione di Puso "const byte V_DSX(3);" dice al compilatore che basta un byte per contenere 3 e quindi il codice risultante sarà più piccolo.

Volendo occupare lo stesso spazio ridotto con la #define occorrera ricorrere a quella burutta cosa di un "cast" nella #define ... "#define V_DSX (byte) 3" ...

Guglielmo

Si, hai ragione (per quello avevo scritto che andava bene usare "const byte"), ho specificato male la cosa, io per default uso #define per i progetti dove non ho problemi di ram quindi necessità di compattare il compilato :wink: Correggo il post.

:grinning_face_with_smiling_eyes: Intendevo come soluzione ovviamente accorciabile a migliorabile, o se secondo voi è solo un inganno come il delay(), comunque lo avevo già provato e funziona.

La scelta di usare più caratteri deriva dal fatto che alla fine del mio progetto avrò molti comandi da utilizzare e se ci metto un solo carattere o numero, va poi a finire che non mi ricordo più a cosa servono (diciamo che cosi è per me più intuitivo quando devo fare delle modifiche o correggere errori).

Lo "switch..case" non mi è mai piaciuto perchè fa meno di "if" e
sempre in caso di errori o di modifiche faccio prima a sperimentare dentro un "if".

Per la nota stilistica effettivamente non è il mio forte, la verità è che faccio spesso copia incolla poi modifico il contenuto e già impazzisco per farlo funzionare tralasciando lo stile. (Ho l'eleganza di una prugna secca :cowboy_hat_face:).

Ora voglio accorciare ulteriormente facendo un "array", appena mi rinfresco la memoria.

Una domanda
lo string è simile all'array, che differenza c'è tra i 2 ?

Le stringhe classiche del 'C' altro non sono che array di char con alla fine il carattere 0x00 per indicare che la stringa è finita.

Da non confondere con la classe String e gli oggetti di tale classe che, su Arduino, è meglio evitare.

Guglielmo

Ok, non ho capito, ma mi fido e per il momento ne ho gia troppe cose de rifrescarmi la memoria e di cose da imparare, vedrò d'ora in poi di utilizzarle il meno possibile ed evitarle come la peste :japanese_ogre:

Guarda, leggi il post iniziale di QUESTO thread che spiega il problema della classe String e poi parla di una libreria alternativa, SafeString che le può sostituire in modo semplice, ma senza i problemi che esse hanno :wink:

Guglielmo

Sulle librerie la penso sempre come 2 anni fà.....meno le uso più imparo, anche se a volte ovviamente non posso farne a meno.
Al momento sto provando qualke modifica con 1 array di tipo char.

Per manipolare le stringhe classiche del 'C' hai comunque a disposizione tutto quello che AVR libc mette a disposizione ... porto in particolare la tua attenzione su tutte le funzioni che si trovano in <string.h> (... che, mettila come ti pare, ma sarai costretto ad usare se lavori con le stringhe :grin:).

Come al solito ... buono studio ! :wink:

Guglielmo

Dipende da come programmi... Ad esempio se usi dei simboli al posto dei caratteri puoi averli "mnemonici". Magari metti solo un prefisso per ricordare che sono comandi (es. "C_") ossia fai cose di questo tipo:

...
#define C_FERMO '0'
#define C_LENTO '1'
#define C_VELOCE '2'
#define C_AVANTI 'A'
#define C_INDIETRO 'I'
#define C_DESTRA 'D'
#define C_SINISTRA 'S'
...
  switch(rx_2) {
    case C_FERMO:
      Velocita = 0;
      break;
    case C_LENTO:
      Velocita = 1;
      break;
    case C_VELOCE:
      Velocita = 2;
      break;
    case C_AVANTI:
      Direzione = 1;
      break;
...eccetera

Insomma, hai almeno un centinaio di caratteri tra cui scegliere, e per il codice ti basta usare sempre il relativo simbolo mnemonico che serve sia per non sbagliarti sia per "leggere" il codice in modo più facile (ed in questo caso ti eviti pure i commenti)... :wink:

L' idea di mettere un prefisso mi piace.
Per quanto riguarda le "String", ho fatto un pò di tentativi ma effettivamente, non sono ancora pronto per avventurarmi in questo mondo, quindi per il momento le accantono, anche se questo "Void" lo tengo perchè prima o poi voglio tornarci sù.

Grazie a tutti.

PS :
Mi sono ambientato questo argomento se volete si può chiudere.
La prossima volta metto un titolo più specifico per risolvere i miei problemi cosi anche gli altri utenti interessati possono prendere spunto.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.