La union impone a tutti i suoi membri di condividere la stessa area di memoria, in questo modo la struct str occuperà gli stessi byte di memoria dell'array arr, se modifichi un valore nella struct anche nell'array questo cambierà, cosi facendo nella struct ti ritroverai i valori belli ordinati e formattati e nell'array i singoli byte che le compongono. Ti basterà implementare la struttura su entrambi i device, usando la str per operare sui dati e inviando tra di loro i byte contenuti in arr.
int Th;
int RPM;
float Lat;
float Long;
float Speed;
byte a, b, c, d, e;
void Request()
{
Wire.requestFrom(6,5);
while (Wire.available())
{
a = Wire.read();
b = Wire.read();
c = Wire.read();
d = Wire.read();
e = Wire.read();
Th = a;
RPM = b;
Lat = c;
Long = d;
Speed =e;
delay(1);
}
come inserisco il codice che mi hai descritto nel mio sketch
I valori lat e long li leggerò e scriverò con frame.str.lat e frame.str.long, stesso discorso per l'array di byte frame.arr
Adesso lo slave legge i valori di longitudine e latitudine da un gps, li mette dentro la struttura frame.str e invia al master l'array di byte frame.arr, il master riceverà l'array di byte e lo posizionerà nel suo array frame.arr e leggera i valori formattati dalla struttura frame.str.
Ora è più chiaro?
Prestiamo attenzione alla dimensione dell'array, hai una struct che occupa tanti byte quanti quelli occupati dagli elementi che contiene, su Arduino i float sono da 2 byte, per sicurezza usiamo scrivere sizeof(float) questo permette la piena portabilità del codice su piattaforme diverse, in questo caso arr lo facciamo grande quanto str, quindi sizeof(frame.str) (in realtà potevamo anche farlo da un singolo elemento, a noi quello che interessa è il puntatore in se alla struct). Facciamo un piccolo calcolo per l'invio di byte, abbiamo sizeof(float per 8 elementi, abbiamo detto che sizeof(float) = 2 quindi inviamo frame di 16 byte alla volta, quindi scriveremo Wire.write(frame.arr, 16) o piu semplicemente sizeof(frame.str) la dimensione della struct.
Dall'altra parte attenderemo quindi 16byte, ci mettiamo in ascolto e all'arrivo del sedicesimo byte copiamo il tutto nel frame.arr.
Perché è il metodo piu inefficiente che esista, risposta breve. Cosi facendo per ogni variabile rinizi da capo la connessione. L'array di byte mediante union è forse il metodo piu usato in C per la serializzazione dei dati. La serializzazione dei dati e la de serializzazione è completamente affidata al compilatore che la esegue senza invocare mezza call.
Mi sfugge la differenza a livello di trasmissione tra la spedizione della versione byte o di quella struttura, mi sembra sia solo più semplice da capire per chi non ha dimestichezza con i puntatori.
PS: dubito che si possa chiamare una variabile long
è semplice formalità, non sarebbe nemmeno errato usare come puntatore &Lat e come numero di byte 16. Con l'array eviti semplicemente il cast, ma come dici te è corretto ed equivalente.
Prestiamo attenzione alla dimensione dell'array, hai una struct che occupa tanti byte quanti quelli occupati dagli elementi che contiene, su Arduino i float sono da 2 byte, per sicurezza usiamo scrivere sizeof(float) questo permette la piena portabilità del codice su piattaforme diverse, in questo caso arr lo facciamo grande quanto str, quindi sizeof(frame.str) (in realtà potevamo anche farlo da un singolo elemento, a noi quello che interessa è il puntatore in se alla struct). Facciamo un piccolo calcolo per l'invio di byte, abbiamo sizeof(float per 8 elementi, abbiamo detto che sizeof(float) = 2 quindi inviamo frame di 16 byte alla volta, quindi scriveremo Wire.write(frame.arr, 16) o piu semplicemente sizeof(frame.str) la dimensione della struct.
Dall'altra parte attenderemo quindi 16byte, ci mettiamo in ascolto e all'arrivo del sedicesimo byte copiamo il tutto nel frame.arr.
Premesso che ho sonno, devi essenzialmente richiedere tot byte, aspettare che arrivino ed accodarli in arr, alla fine potrai usare str per recuperare quel che hai trasmesso. Qualcosa del genere potrebbe funzionare:
#define ADDRESS 0x27 // Inventato a caso
void boh() {
union {
struct {
float Lat;
float Long;
float Speed;
float Alt;
float Amp;
float Volt;
float Watt;
float HR;
} str;
byte arr[sizeof(float) * 8];
} frame;
Wire.requestFrom(ADDRESS, sizeof (frame));
for (byte b = 0; b < sizeof (frame); b++) {
// Attende il prossimo byte
while (!Wire.available())
;
// Accoda in arr
frame.arr[b] = Wire.read ();
}
// A questo punto la struttura è completa ed utilizzabile con frame.str
}
Immagino ci siano modi migliori di farlo, ma questo dovrebbe essere il più semplice da capire.
@RobertoBochet, parlare di efficienza su Arduino fa scappare dal ridere.
La union rimane una sciocchezza in codesto contesto, un'inutile ridondanza.
Se hai una struttura che contiene i tuoi dati la puoi tranquillamente inviare e ricevere senza impazzire con cose inutili:
Master: