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

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..

danyevo:
Ma perche usa la libreria softwareserial?

Perché ... ha SEI seriali da gestire e la Mega ne ha fisicamente solo tre ... :grin:

Ovviamente, con un po' di esperienza, avrebbe potuto semplificare il progetto ...
... ad esempio usando una sola linea RS485 (con gli appositi adattatori) collegata ad una sola delle seriali della MEGA e da software avrebbe potuto implementare un protocollo di "polling" ... ma magari ci arriverà in futuro ... ora mi sembra veramente agli inizi ... :slight_smile:

Guglielmo

non è possibile utilizzare una porta seriale e collegare tutti gli arduini li?
tutti i tx degli arduini vanno nel rx del mega, tutti i rx degli arduini i vanno nel tx del mega
magari sincronizandoli che trasmettono prima uno poi l'altro e così via
magari il mega quando riceve i dati dal primo invia i dati per far partire il secondo poi il terzo ecc ecc

NO, non è possibile mettere in parallelo così le porte seriali.

Guglielmo

gpb01:
NO, non è possibile mettere in parallelo così le porte seriali.

Direttamente no, i TX sono degli out e metterli brutalmente in parallelo vuol dire fare un corto, però un modo semplice per mettere in parallelo delle UART c'è.
Tenuto conto che lo stato di idle della seriale è 1 logico basta appendere il RX al +5V con una pullup da 10k , mettere in serie ai vari TX un diodo schottky, p.e. un BAT48, collegando il catodo sul TX e i loro anodi in parallello sul RX, in questo modo i vari pin TX sono tra loro isolati e quando uno va a zero logico di conseguenza traina anche l'RX a questo livello consentendo la comunicazione.
Ovviamente con una soluzione di questo tipo è necessario usare un protocollo di comunicazione basato su un address tenendo conto che solo un TX per volta può entrare in funzione, va da se che il TX della Mega deve essere collegato in parallelo su tutti gli RX delle varie UNO.

PaoloP:
... si dovrebbero programmare i micro in puro ANSI C. ]:smiley:

Perche' vuoi complicarti la vita ? ... vai di binario ... :stuck_out_tongue: XD ]:smiley: