Informazioni necessarie per dividire la stringa di dati ricevuti.

SAlve a tutti, ho una serie di domande informatiche :slight_smile:
Scopo finale dividere i dati ricevutii in modo tale da associarli al sensore corrispondente.

Domanda 1.

Da quel che ho capito, un simbolo char vale un byte.
< un byte, > un byte, ; un byte.
se invio <255;255;255> sto inviando 13 byte?
ho definito gli interi di analogRead, che dovrebbero essere prima 16bit = 2byte in 8bit (ho diviso per 4) ma poi convertendoli in un char[4]diventano 3byte?

Scusate, mi sembra di essere alle elementari quando dovevo imparare le tabelline. Ma per me Ă© veramente indispensabile se mi aiutate ad imparare a contare!!! :confused:

  1. OK ma la conversione di un int a un vettore di char varia da 1 a 5 byte a seconda del numero.

2)sembra che sai contare.

Stai attento perché nel c le stringhe hanno il terminatore '\0' in c++ no.
Arduino che usa entrambi i linguaggi in certi casi può essere confusionario.

Vediamo se riusciamo a fare un po’ di chiarezza, un char necessità di un byte di spazio, cioè 8bit, la quantità minima di informazione che puoi inviare attraverso seriale (in realtà si possono inviare 7bit se si attiva il bit di controllo parità ma è un discorso che non ci riguarda per il momento). Quindi inviando un singolo char stai trasferendo ben 8 bit di informazioni cioè 256 alternative. Errore molto frequente sta nel far comunicare due dispositivi mediante stringhe, quando tu dici per inviare <255;255;255> necessito di 13 byte hai ragione ma questa non è la reale informazione che è contenuta nella stringa inviata, si potrebbe ridurre l’informazione a solo 24bit cioè 8 bit per il primo 255, 8 bit per il secondo e 8 bit per il terzo.
Buona norma che semplifica il trasferimento di informazioni è avvalersi delle struct

struct package {
int a, b, c;
byte e, f;
}

Questo può rappresentare il pacchetto di dati che trasferire in particolare questo contiene 8byte di informazioni, che puoi inviare per seriale sotto forma di 8 pacchetti da 8 bit. Arrivati al PC potrai ricomporli nella struttura di partenza. a potrebbe essere la distanza di un oggetto, b la velocità dello stesso, c un orientamento, sei tu con il tuo algoritmo che dai un senso ai dati.

Un array di char occupa n byte(n numero di elementi), se è una stringa va considerato il \0 finale quindi diventa n+1, se invece parliamo dell’oggetto string del c++ allora l’allocazione della memoria diventa dinamica e hai necessità di un puntatore al’heap quindi 2 byte in più. L’informazione comunque rimane sempre n byte.

Wao che mondo!!!!

grazie mille ad entrambi!!!!

Posso chiedere cosa devi inviare tra pc ed Arduino?

Sto inviando da arduino ad arduino!
Valori presi da A0, A1 A2 per ora ho messo 5V (pin di arduino) in AO e A2 e ground in A1 per sapere cosa invio e se ricevo giusto.
e sto usando la comunicazione seriale.
Poi il progetto Ă© per misurare tre segnali analogico provenienti da sensori il cui voltaggio varia da 1.7 a 3V la frequenza da 0 a 50Hz.
e per trasportare il messaggio uso fibra ottica.

Credo di averti dato tutte le info :slight_smile:

la strtok è una funzione del c, dunque x1 dovrà terminare col carattere '\0'.
Quello che sta cercando di dirti @RobertoBochet è perché converti un numero in stringa lo invii e lo torni a convertire in numero?
Perché non invii direttamente il numero?
devi inviare tre valori in formato byte?

Serial.write(byte1);
Serial.write(byte2);
...

e per riceverlo

while(!Serial.available());
byte1 = Serial.read();
while(!Serial.available());
byte2 = Serial.read();
...

non volevo perdere i dati nel vento, ad esempio se arduino ricevente non Ă© pronto a ricevere, volevo mettere una sorta di codifica per essere sicura che il valore viene dal sensore n e non n+ o -1.
e ho pensato che mandandolo in stringa fosse compatto e non andava nel vuoto.
Questi raggionamenti sono di una che non ha mai studiato telecomunicazioni e ha imparato da due settimane cosa sia serial communication.
:slight_smile: Per questo scrivo un sacco nel forum :slight_smile:

un altra cosa Ă© che con Serial.write invio il dato sotto forma di byte. ma come lo interpreto?
che ne so se invio
Serial.write(analogRead(10)>>2);
quello che vedo nel monitor seriale sono una serie di y
e poi, come faccio a codificare il messaggio?
con le stringhe la cosa mi Ă© piu chiara visto che vedo cosa mando.

Giulialiuyi:
con le stringhe la cosa mi Ă© piu chiara visto che vedo cosa mando.

Ed è proprio qui che capisci che il tuo approccio non è il migliore! Per noi umani dotati di quello che possiamo definire intelletto flessibile è di piu semplice comprensione una frase che una serie di bit, per le macchine le frasi non sono che una perdita di tempo, codificare un numero in caratteri?! ma siamo pazzi un numero è una serie ben precisa di 1 e 0, cosa c'è di più comodo per fare somme sottrazioni e altre operazioni logiche. Tu vuoi far comunicare due Arduino, loro parlano bene con il linguaggio informatico, non insegnarli a convertire il linguaggio matematico in parola parlata per poi riconvertirlo in linguaggio matematico. Se devi eseguire un debug ti basterà rifarti ad un serial monitor leggermente piu professionale di quello di Arduino che permette solo di visualizzare i dati ricevuti mediante tabella aschii.

Per quanto riguarda la perdita di dati, ora non vorrei dire una cavolata, ma dovrebbe essere piuttosto difficile perdere dati attraverso UART, al massimo arrivano corrotti, o non ne arriva neanche mezzo, nell'ultimo caso forse sarebbe meglio rivedere il collegamento fisico. In ogni caso se ti preoccupa puoi inventare tu un protocollo per garantire l'integritĂ  dei dati.

La uart è bufferizzata, quindi se non sei li in quel momento viene messo in un buffer e tu lo prendi in un secondo momento, il tutto è gestito automaticamente e tu non devi far nulla.
Per quanto riguarda gli errori dipende da molti fattori, alcuni baund possono generare piĂą errori di altri, ma per il momento puoi tralasciare e puoi concentrarti sulla comunicazione vera e propria.

Come inviare?
analogRead() restituisce un intero ovvero 2 byte, ossia High Word e LOW Word, parte alta e parte bassa, 16 bit.
Ora tralasciamo che l’adc USA realmente solo 10bit.
Ora tu hai un valore int e lo vuoi spedire e il metodo più semplice per gestire il marshalling dei dati è il seguente:
invio:

int adc = analogread(...);
Serial.write(adc >> 8 );
Serial.write(adc & 0xFF);

Quindi prima cosa leggiamo il valore, poi inviamo prima la parte alta spostando a destra i suoi bit e successivamente la sua parte bassa grazie all’operatore bitwise AND e la maschera FF preleviamo e inviamo solo gli otto bit meno significativi.

Ora riceverli è solo l’operazione inversa:

int adc;
while(!Serial.available ());
adc = Serial.read() << 8;
while(!Serial.available ());
adc |= Serial.read();

Ovvero attendo di avete il dato e poi lo prelevo e lo spostò di un byte a sx, aspetto il sucessivo byte e lo metto nella parte bassa della mia variabile int tramite l’operatore bitwise or.

Per riuscire a interpretare meglio tutto ciò che sta succedendo ti consiglio di fare una ricerca tipo “linguaggio c operatori bitwise”, queste sono operazioni fondamentali da studiare.

Naturalmente puoi inviare il pre e post inviò tramite un semplicissimo:

Serial.println(adc);

RobertoBochet:
Ed è proprio qui che capisci che il tuo approccio non è il migliore! Per noi umani dotati di quello che possiamo definire intelletto flessibile è di piu semplice comprensione una frase che una serie di bit, per le macchine le frasi non sono che una perdita di tempo, codificare un numero in caratteri?! ma siamo pazzi un numero è una serie ben precisa di 1 e 0, cosa c'è di più comodo per fare somme sottrazioni e altre operazioni logiche. Tu vuoi far comunicare due Arduino, loro parlano bene con il linguaggio informatico, non insegnarli a convertire il linguaggio matematico in parola parlata per poi riconvertirlo in linguaggio matematico. Se devi eseguire un debug ti basterà rifarti ad un serial monitor leggermente piu professionale di quello di Arduino che permette solo di visualizzare i dati ricevuti mediante tabella aschii.

Per quanto riguarda la perdita di dati, ora non vorrei dire una cavolata, ma dovrebbe essere piuttosto difficile perdere dati attraverso UART, al massimo arrivano corrotti, o non ne arriva neanche mezzo, nell'ultimo caso forse sarebbe meglio rivedere il collegamento fisico. In ogni caso se ti preoccupa puoi inventare tu un protocollo per garantire l'integritĂ  dei dati.

Si hai ragionissima, ma non sapendo come controllare o che altri tipi di IDE usare avevo preferito quella via. So che gli arduino comunicano via 0, 1, gli sto facendo comunicare per fibra ottica attraverso il pin Tx0 e Rx0 e naturalmente inverto il messaggio prima che arrivi all'altro arduino. insomma il concetto di 0,1 mi é chiaro. La mia svista stava anche nel fatto che (ahahhahahaha) pensavo la UART fosse l'uscita dove per collegare arduino al pc ma, dopo aver letto ho capito "Nei microcontrollori che la posseggono questa funzione è interna allo stesso." XD

@vbextreme grazie mille della spiegazione!!! Se non hai gia un blog dovresti farlo! e se ce l'hai mi daresti il link?
sto inviando i dati ad un baud di 115200,

analogRead() restituisce un intero ovvero 2 byte, ossia High Word e LOW Word, parte alta e parte bassa, 16 bit.
Ora tralasciamo che l'adc USA realmente solo 10bit.
Ora tu hai un valore int e lo vuoi spedire e il metodo più semplice per gestire il marshalling dei dati è il seguente:

quella parte prima che la scrivessi non mi era chiara per niente!!
Grazie scrivero novita!

vbextreme:

int adc;

while(!Serial.available ());
adc = Serial.read() << 8;
while(!Serial.available ());
adc |= Serial.read();

Domanda, perché metti due volte while(!Serial.available) ?
e non é meglio mettere if (Serial available>0)? diciamo qual’è la differenza sostanziale? con if ho capito che se c’è un byte disponibile nella seriale allora inizi a leggere, invece con while è mentre ricevi bit inizi a leggere?

un altra domanda

int adc = analogread(...);
Serial.write(adc >> 8 );
Serial.write(adc & 0xFF);

int adc = analogRead(A0) >>2; // mi restituisce un byte. posso mandare tutto insieme no?

while(!Serial.available ());Si potrebbe tradurre con <Aspetta finché nel buffer UART non vi è almeno un byte da poter leggere.>
Puoi riscriverlo cosi

while(Serial.available () < 2);//Attendi finché non vi sono almeno 2 byte disponibili per la lettura
adc = Serial.read() << 8 | Serial.read();//Preleva i dati dal buffer e ricomponi l'intero di partenza

Oppure con l’if se vuoi evitare di bloccare l’intero sketch

if(Serial.available () >= 2); adc = Serial.read() << 8 | Serial.read();

La scelta migliore non esiste dipende da come scegli di comunicare i dati tra i due Arduino.

Giulialiuyi:
con if ho capito che se c’è un byte disponibile nella seriale allora inizi a leggere, invece con while è mentre ricevi bit inizi a leggere?

Con while attendi che il byte sia disponibile, quindi blocchi l’AVR finché questo non riceve un byte.

Giulialiuyi:
int adc = analogRead(A0) >>2; // mi restituisce un byte. posso mandare tutto insieme no?

In realtà continua a restituire un intero con i bit spostati di 2 verso destra. Quando usi l’operatore di shift il primo elemento è la serie di bit che vuoi far spostare, il secondo elemento dopo l’operatore è il numero di posizioni di cui vuoi far spostare i bit.

int adc = 0b0101011110110111;
int adc = adc >> 5;//adc = 0b0000001010111101

Domanda

adctx1 = analogRead(A0)>>2

perché lo shift di 2?

int adctx1 = analogRead(A0);
int adctx2 = analogRead(A1);
int adctx3 = analogRead(A2);

Serial.write(adctx1 >> 8);
Serial.write(adctx1 & 0xFF);
Serial.write(adctx2 >> 8);
Serial.write(adctx2 & 0xFF);
Serial.write(adctx3 >> 8);
Serial.write(adctx3 & 0xFF);

delay(200);//Buona norma per non saturare i buffer dell'UART
if (Serial.available () >0)//Errore piuttosto grave, tu hai bisogno di 2 byte per ogni ingresso analogico, non puoi accontentarti di questa condizione che restituisce true anche solo con un byte nel buffer
if(Serial.available() >= 6) {
    adcrx1 = Serial.read() << 8 | Serial.read();
    adcrx2 = Serial.read() << 8 | Serial.read();
    adcrx3 = Serial.read() << 8 | Serial.read();

    //Ora li puoi stampare
}

RISPOSTA
nella mia mente mette tutti zero a sinistra essendo int da sedici a adc da 10 bit cosi ho al Massimo 8 uno, e il resto Ă© zero e nel caso posso eliminare un byte, ma naturalmente prima di imparare a correre bisogna imparare a camminare!!! __

Poi l’errore grave.
Nel moi raggionamento metevo auel primo if > 0 per non far fare niente ad arduino sino a che non collegavo il cavo in rx. e poi c’era l’altro if >2 per i primi due bit.
Ma ho capito che Ă© un ragionamento sbagliato.

if (Serial.available () >0)
{
if(Serial.available()>2)
{
digitalWrite(LED_TX,HIGH);
adcrx1 = Serial.read() << 8 | Serial

demay da 200ms buono, ci avevo pensato ma non mi sono messa a contare i tempi, insomma, GRAZIE GRAZIE GRAZIE. ora modifico! e poi riaggiorno :slight_smile:

FUNZIONA!!!!!!!!! yeeeeeeeeee XD XD XD
TI ho gia messo un KARMA anche se te ne metterei un altro!!!!
Grazie!!!!!!!!!!!!!!!!!!!!
SONO FELICE

Se la tua necessità è quella di far comunicare due Arduino è comodo condividere un interfaccia per i dati tra i due, puoi creare una libreria da caricare su entrambi, ti faccio un esempio

class Data {
  public:
  int val1;
  int val2;
  byte val3;
  
  void receive();
  void send();
};
void Data::receive() {
  while(Serial.available() >= 5);
  this->val1 = Serial.read() << 8 | Serial.read();
  this->val2 = Serial.read() << 8 | Serial.read();
  this->val3 = Serial.read();
}
void Data::send() {
  Serial.write(this->val1 >> 8);
  Serial.write(this->val1 & 0xFF);
  Serial.write(this->val2 >> 8);
  Serial.write(this->val2 & 0xFF);
  Serial.write(this->val3);
}

Data data;

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

void loop() {
  data.receive();//Mi metto in ricezione dei dati
  //ora posso accedere ai dati semplicemente con data.val1 o data.val2 o data.val3
  data.val1 = 56675;//Modifico i valori dei dati
  data.val2 = -2323;
  data.val3 = 56;
  data.send();//Invio i dati
}

Caricando la classe data su entrambi avrò una semplice interfaccia che mi permetterà di evitare confusione tra i dati, questo ovviamente necessità di qualche byte aggiuntivo di memoria, ma semplifica di molto la gestione.

Grazie! capisco in genarale cosa intendi ma personalmente non conosco le funzioni di tipo class.
Link per capire come funzionano cosa sono, come utilizzarle?

Dovresti dare un'occhiata ad un libro che insegni la programmazione ad oggetti (tipo "thinking in C++" di Bruce Eckel che trovi scaricabile in internet)

class non è una funzione ma bensì l'identificativo di una classe, che si può vedere come una struttura che ammette oltre che a variabili anche metodi.
Se si tratta solo comprendere la sintassi e l'utilizzo puoi rifarti alla guida di html.it. Attenzione è una guida, fornisce il minimo indispensabile per riuscire a gestire le classi, nulla di piu.