6 Arduini UNO che comunicano un float a un MEGA 2560 con SoftwareSerial

Un saluto a tutti !
Come ho già scritto in presentazione riprendo in mano un pò di aggeggi elettronici dopo 15 anni di digiuno.. XD

Sto smanettando da settimane ormai con i miei arduini e un passo alla volta mi sto districando tra le varie funzioni.
Il mio progetto che ho in testa è di domotizzare casa mia in maniera modulare. Pensavo a mettere un'Arduino UNO con TFT in ogni camera per renderli indipendenti in caso di guasti e collegarli ad una MEGA 2560 da mettere all'ingresso. La MEGA grazie a una shield Annikken Andee (che già ho e trovo fantastica perchè non devo imparare da zero a programmare android) viene comandata da un tablet Android.
Il progetto è in comtinua evoluzione e implementazione man mano che le mie conoscenze crescono.

Ma veniamo al mio problema.

Ho già preparato uno sketch che funge da termostato che verrà caricato su ogni arduino UNO (manca la parte TFT ma ci arriverò..). In questo sketch in sostanza mi trovo con due variabili Timpostata e Tambiente. L'unica cosa che mi manca è trasmettere queste variabili alla MEGA per poterle visualizzare con l'Andee sul tablet.

Penso che la soluzione migliore sia la libreria SoftwareSerial e finora sono riuscito in qualche modo a trasmettere qualcosa ma un problema mi blocca e pur cercando come un matto non trovo niente che mi aiuti.

#include <SoftwareSerial.h>
SoftwareSerial mySerial(10,11);

float valore = 0.0 ;
void setup()
{
  Serial.begin(9600);
  pinMode(13 , OUTPUT);
  mySerial.begin(9600);
}

void loop(){
  if (mySerial.available()) 
  {
    valore = mySerial.read();  
    Serial.println(valore); 
    digitalWrite(13, HIGH);  
   
  }
    
  
}

Questo è lo sketch sul ricevitore, la MEGA 2560. Ho impostato la variabile valore come float perche la temperatura è con 2 decimali.

#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); 

float valore = 0.0 ;       

void setup()  
{

  Serial.begin(9600);
  mySerial.begin(9600);
}

void loop()
{
  valore = 3.5;            
    
  if (valore>0){
     mySerial.print(valore);
     Serial.println(valore);  

}
}

Questo è lo sketch sulla arduino UNO, il trasmettitore diciamo. Per ora come esperimento immetto a mano il valore della variabile.

Il problema è che sul monitor seriale della trasmittente mi scrive il valore corretto 3.50 mentre sul monitor seriale mi scrive valori sballati.
Tipo:
53
45
67
32
34
ecc ecc...

Oppure il meglio che sono riuscito a fare (e non ricordo come...) valori tipo 22.00 anche se il valore di partenza era 21.77.

Chi mi spiega un pochino come fare ?

Graaaazie....

Il problema è ... che non leggete il reference e cosa fanno le funzioni (... uso il plurale perché ogni volta è esattamente la stessa cosa ... se fai un po' di ricerche sul forum ne trovi a decine :wink: )

SoftwareSerial.read() : "Return a character that was received on the RX pin ..."

La funzione " mySerial.read()" (come la Serial.read) restituisce UN char ovvero legge un singolo byte. Se da un lato si trasmette una serie di bytes, come può fare una Serial.print ... dall'altro lato occorre gestire un meccanismo per ricevere una serie di bytes e capire quando essi sono finiti.

Quindi ... dovrai implemnetare un ciclo in cui leggerai carattere a carattere quello che arriva sulla seriale, dovrai capire, ad esempio con un carattere terminatore (es. CR) quando il dato è terminato ed infine ... trasformare la stringa di char che avrai ricevuto nel tuo valore numerico ...

Ripeto, se ne è parlato infinite volte e, se fai delle ricerche, trovi anche degli esempi fatti :wink:

Guglielmo

gpb01:
Il problema è ... che non leggete il reference e cosa fanno le funzioni (... uso il plurale perché ogni volta è esattamente la stessa cosa ... se fai un po' di ricerche sul forum ne trovi a decine :wink: )

Ringrazio sinceramente per la risposta ma il problema è ... che all'epoca non ho avuto la fortuna di poter studiare l'inglese, che non ho avuto modo di studiare linguaggio C e che chi scrive le reference magari sono persone che non pensano che dovrebbero essere rivolte anche ai niubbi che vogliono imparare ma le scrivono per gli addetti ai lavori... tutto quello che so su questi argomenti è autodidattico.

Io cerco di leggere tutto il possibile, di cercare il più possibile nei forum e di chiedere il meno possibile... ma quando non capisco una cosa e nonostante giorni di tentativi e ricerche non riesco ad arrivarci da solo mi tocca disturbare... abbiate pazienza.
Il progetto è oltre la mia portata attuale ma il mio scopo non è finirlo e venderlo ma imparare. Tanto è vero che non ho chiesto uno sketch pronto, ma che qualcuno mi spiegasse.

Senza rancore, giusto per mettere in chiaro le cose. :wink:

Ora che so cosa cercare nel forum, vado a cercare.

Marcobz:
Ringrazio sinceramente per la risposta ma il problema è ... che all'epoca non ho avuto la fortuna di poter studiare l'inglese, che non ho avuto modo di studiare linguaggio C ....

Capisco, ma purtroppo questo è un ambiente di lavoro (Arduino) dove se non sai il C ... non vai da nessuna parte e, se non sai l'inglese ... vai da ben poche parti ... mi spiace ... :frowning:

Magari, prima di buttarti su un progetto così articolato ... io dedicherei molto più tempo a studiare BENE il linguaggio e le sue regole. Esistono un'infinità di ottimi testi e tutorials anche in lingua Italiana ... :wink:

Quando avrai padronanza dello strumento ... allora vedrai che molte cose saranno più semplici ... :slight_smile:

Guglielmo

Senza volermi dilungare troppo su di me.. ho scritto che non ho avuto la fortuna di poter studiare inglese e C intendendo a scuola..(non erano previste come materie nonostante l'indirizzo di "Tecnico delle industrie elettriche ed elettroniche")... ma poi i miei manualetti per i fatti miei me li sono letti ! XD E per l'inglese pian pianino negli anni qualcosa mi è entrato !

Comunque forse inizio a capire come far leggere la serie di caratteri ... mi hai dato la chiave giusta.
Appena riesco a mettere insieme uno sketch se lo posto me lo potresti controllare e vedere se ho capito bene ?

Grazie !
p.s. naturalmente la richiesta è per tutti !

Marcobz:
...
Appena riesco a mettere insieme uno sketch se lo posto me lo potresti controllare e vedere se ho capito bene ?

... naturalmente ... SI XD

Guglielmo

Niente... mi sta fumando la testa e ho gli occhi così :astonished: a furia di cercare e capire ma non ci arrivo.. non posto neanche gli sketch che ho provato...

Qualcuno può darmi una manina a trasmettere sto float da un'arduino all'altro ? Ormai sono in confusione totale... :~

Marco,
da un lato puoi continuare a trasmettere tranquillamente usando la Serial.print solo che, dopo il tuo numero, aggiungi una Serial.print() di UN carattere che, per te, identificherà il separatore, esempio il carattere CR (0x0D oppure '\r') ...

... dall'altro lato, basta un ciclo che legge carattere a carattere e memorizza in un array che costituirà la tua stringa ricevuta (... ricordandosi di mettere sempre come ultimo carattere lo 0x00 and indicare la fine della stringa).

Finita la ricezione, dovrai convertire la stringa (array di char) nel tuo numero.

L'ho già messo in altri post e lo rimetto anche qui ...
... ecco un esempio "generico" di come ricevere una serie di caratteri terminati da un carattere terminatore :

#define MAXCHAR  32
#define TERCHAR  0x0D

char inputString[MAXCHAR + 1];
char inChar;
byte strIndex;


void setup() {
  
  strIndex = 0;
  inputString[strIndex] = 0x00;
  
  Serial.begin(9600);
  
}

void loop() {
  
  if (Serial.available()) {
    inChar = Serial.read();
    // se si vogliono vedere in HEX i caratteri che si ricevono
    // togliere il commento alla riga seguente
    // Serial.println(inChar, HEX);
    if (inChar == (char) TERCHAR) {
      // è arrivato il carattere terminatore, si puo' elaborare la stringa
      // In questo esempio semplicemente la si stampa ...
      Serial.println(inputString);
      //
      // finito il suo uso la si ripulisce per un uso successivo
      strIndex = 0;
      inputString[strIndex] = 0x00;
    }
    // NON è arrivato il carattere terminatore, si memorizza il carattere ricevuto
    // e si sposta il fine stringa ...
    inputString[strIndex] = inChar;
    strIndex++;
    if (strIndex > MAXCHAR) {
      // ... NON c'è pi` spazio nella stringa ... bisogna elaborarla e svuotarla
      // In questo esempio semplicemente la si stampa ...
      Serial.println(inputString);
      //
      // e la si ripulisce per un uso successivo
      strIndex = 0;
      inputString[strIndex] = 0x00;
    }
  }
}

... ora a te lavorarci sopra per adattarlo alle tue esigenze ... ! :wink:

Guglielmo

Nelle ultime versioni dell'IDE è stato inserito Parsefloat --> Serial.parseFloat() - Arduino Reference
Una discussione in merito --> Sending floats over serial - Programming Questions - Arduino Forum

@Paolo : Paolo, leggi bene il thread, stiamo parlando della SoftwareSerial (deve gestire SEI seriali su una Mega) e ... non mi sembra che qualcuno si sia preso la briga di implementarla con TUTTE le funzioni della Serial ]:smiley: ]:smiley: ]:smiley:

Inoltre, parlando in generale, anche sulla Serial ritengo che chi comincia debba imparare a fare le cose come si debbono fare e non ad usare la "pappetta" fatta che, come si allontana dall'IDE di Arduino .. non trova più e non sa cosa fare ! :roll_eyes:

Certe funzioni sono solo diseducative !!! ]:smiley:

Guglielmo

gpb01:
Inoltre, parlando in generale, anche sulla Serial ritengo che chi comincia debba imparare a fare le cose come si debbono fare e non ad usare la "pappetta" fatta che, come si allontana dall'IDE di Arduino .. non trova più e non sa cosa fare ! :roll_eyes:
Certe funzioni sono solo diseducative !!! ]:smiley:

Assolutamente d'accordo :slight_smile:
Manca ancora la spiegazione di come fare per scomporre un float nei quattro byte che lo compongono e come riunirli per ottenere nuovamente il float, il tutto lo spiego qui, leggere anche i post seguenti.

@Astro : Stavo pensando di fagli trasmettere il float come semplice stringa (mySerial.print) e poi di riconvertire la stringa di caratteri ricevuta con una atof() (... che ho visto essere presente nella stdlib.h AVR) ... ma non ricordo se poi a livello di libreria nella Toolchain Arduino standard ... è implementata :wink:

Guglielmo

Edit : Comunque la tua spiegazione che hai linkato è molto più educativa ... almeno imparano anche ad accedere ai bytes attraverso l'uso dei pointers :wink:

gpb01:
@Astro : Stavo pensando di fagli trasmettere il float come semplice stringa (mySerial.print) e poi di riconvertire la stringa di caratteri ricevuta con una atof() (... che ho visto essere presente nella stdlib.h AVR) ... ma non ricordo se poi a livello di libreria nella Toolchain Arduino standard ... è implementata :wink:

Non mi ricordo se sono implementate ftoa() e atof() in Arduino e/o avrgcc, però se si impara ad usare le unioni è meglio, assieme alle strutture e i puntatori sono tra gli strumenti più potenti del C e consentono di risolvere molte problematiche.
Da non scordarsi che le funzioni di manipolazione stringhe e conversione delle stesse sono molto pesanti dal punto di vista del codice e cicli macchina, una unione viene tradotta come uso di puntatori, senza dovere "combattere" direttamente con gli stessi, richiede pochi byte di codice e pochi cicli macchina per la sua esecuzione.

astrobeed:
... però se si impara ad usare le unioni è meglio, assieme alle strutture e i puntatori sono tra gli strumenti più potente del C e consentono di risolvere molte problematiche.

@Guglielmo
ParseInt e Parsefloat sono, mi pare, nella classe stream, quindi richiamabili anche dalla softserial.
Comunque sarebbe da verificare.

Se ragionate così allora tutto il core di Arduino è "diseducativo" e si dovrebbero programmare i micro in puro ANSI C. ]:smiley:

Ciao come fai a far capire al mega chi degli arduini a inviato la temperatura?

PaoloP:
@Guglielmo
ParseInt e Parsefloat sono, mi pare, nella classe stream, quindi richiamabili anche dalla softserial.
Comunque sarebbe da verificare.

Paolo ... prima di scrivere .. avevo già provato ... mi dice che in SoftwareSerial non esiste la funzione :frowning: .

PaoloP:
Se ragionate così allora tutto il core di Arduino è "diseducativo" e si dovrebbero programmare i micro in puro ANSI C.

Buona parte LO E' ]:smiley:
Tanto è vero che molti, appena decidono di avvicinarsi ad un altra MCU ... vanno "nel pallone" ... XD

Guglielmo

Edit : Avevo scritto male ... effettivamente parseFloat funziona :wink:

danyevo:
Ciao come fai a far capire al mega chi degli arduini a inviato la temperatura?

Basta ch prima dei dati invii un identificativo della board ... in pratica costruisci una struttura in cui c'è "l'indirizzo" del mittente ed "il messaggio" e poi trasmetti il tutto :wink:

Guglielmo

Ma perche usa la libreria softwareserial?

Per identificare l'arduino che invia la temperatura potrebbe fare così:

 stringa0 += char('a');  (a) è l'indirizzo
 stringa0 += int(t1);  (t1) e la variabile dove è scritta la temperatura
 Serial.println(stringa0)  invia la stringa

Giusto..