Sincronizzazione di più Arduino tramite moduli wirelless

Ciao a tutti, sto utilizzando la libreria radiohead, in particolare i driver RH_RF24 con il seguente modulo wireless : HC-12 SI4463 Wireless.

Per la gestione dei pacchetti, sto utilizzando la libreria manager di radiohead: Rhdatagram.h.

I 3 Arduino di cui dispongo sono dotati del micro-controllore ATMega328p.

Il mio obbiettivo è quello di inviare dati dai sensori periferici, verso il nodo centrale. Ogni nodo però ha un tempo limitato a disposizione per l'invio dei dati e questo invio non deve sovrapporsi con l'invio dei dati di altri nodi periferici, appunto per evitare interferenze. Per ora non sto utilizzando gli ACK.
Nella prima fase del mio piccolo progetto, avevo intenzione di sincronizzare in questa maniera:

  1. Fase di sincronizzazione iniziale.
  2. Ogni 8 secondi, il nodo 1 ha altrettanti 8 secondi per il inviare i dati.
  3. Finiti gli 8 secondi parte il nodo 2 per altri 8 secondi.
  4. ecc ecc.

Il Nodo centrale però deve sapere quale nodo sta trasmettendo e chi trasmetterà dopo, quindi deve tenere traccia del tempo che sta passando ed essendo collegato al pc non ha bisogno di risparmiare energia.

In un primo momento per risparmiare batteria stavo utilizzando il watchdog in modalità interrupt, quindi il nodo 1, una volta passati gli 8 secondi a sua disposizione(valutati tramite la funzione millis) andava in sleep per un tempo pari 8 secondi, ovvero fin tanto che il nodo 2 non ha smesso di trasmettere.
Ho notato che utilizzando questo metodo, si veniva a creare uno sfasamento tra i tempi del nodo centrale e i 2 nodi periferici, che a lungo andare diveniva non trascurabile. Ciò penso sia dovuto al fatto che il passaggio tra sleep e normal mode, impiegava troppo tempo.

Allora ora per semplicità sto utilizzando solo la funzione millis per tenere conto del tempo che passa, e sto spegnendo solo la radio. Ovviamente il timer interno di arduino non è ottimo e quindi diciamo che anche in questo caso si viene a definire uno sfasamento.

Non voglio un aiuto dal punto di vista del codice, ma più che altro un metodo da cui prendere spunto per effettuare questo tipo di sincronizzazione, cercando di risparmiare più energia possibile.

Le mie domande sono le seguenti:

Secondo voi sarebbe più utile utilizzare un RTC esterno da sincronizzare con il nodo centrale? E magari utilizzare questo RTC per inviare degli interrupt per accendere il nodo al momento giusto, tenendo conto dei tempi di accensione?

Mi potreste indicare qualche metodo di sincronizzazione che magari avete utilizzato?

Mi sapreste anche indicare come effettuare un sense del canale con i moduli che ho a disposizione?

E' un po' difficile spiegarvi cosa ho in testa attraverso un forum, quindi scusatemi se non sono riuscito a rendere bene l'idea.

Ringrazio tutti in anticipo per l'aiuto.

beh, io forse sto facendo qualcosa di simile al tuo
con un mio collega stiamo realizzando una rete di termometri remoti, che leggono la temepratra delle stanze
e la trasmettono ad una macchina centrale
ma per scelta precisa abbiamo deciso di non usare librerie di comunicazione
per il momento teniemo i satelliti in sleep, ongi 8 secondi si svegliano, e tornano a dormire
solo ogni 8 cicli leggono la temperatura, e solo se questa è cambiata di piu' di un valore di soglia la trasmettono alla centrale, assieme al numero del satellite
la gestione dell'orario la fa la centrale, che quando registra la temperatura le aggiunge l'ora
alla ricezione la centrale fa un check su una cifra di controllo, controllo superato, temperatura registrata e ritrasmessa al satellite
se il satellite ottiene la risposta torna a dormire: risposta ricevuta -> lavoro fatto
se non la ottine aspetta un tempo che dipende dal suo indirizzo (un numero di decimi di secondo pari al suo indirizzo)
siccome se due macchine trasmettono assieme si disturbano, MA non ci sono due macchine con lo stesso indirizzo trasmissione disturbata -> ritardo differente -> prossima trasmissione non disturbata

Si questa potrebbe essere una soluzione, ovvero tenere il tempo solo con il nodo centrale(nel vostro caso la centrale) e mandare direttamente in sleep gli altri. La comunicazione che posso effettuare è la seguente:

  1. Il nodo si sveglia e rimane sveglio per un tempo pari ad esempio 8 secondi e lo comunica al nodo centrale, indicandogli il tempo trascorso dall'attivazione.

  2. il nodo centrale richiede il dato e una volta ricevuto manda un ack al nodo periferico, che una volta terminato il range di 8 secondi, va in modalità sleep.

3)Dal momento in cui l'altro nodo finisce di comunicare dovrebbe partire l'altro nodo periferico, e così via.

In questo caso però interviene una comunicazione in più con il nodo centrale,dato che comunque devo avvisare il nodo centrale dell'attivazione di quel nodo. Purtroppo credo che senza l'utilizzo di RTC esterni, mi toccherà per forza utilizzare un metodo di questo genere. Andare a correggere gli errori di drift e offset non è una buona idea, anche perchè i timer di arduino, non sono tanto affidabili.

Se qualcuno ha in mente un altro metodo, è ben accetto.

BlackHole900:
In questo caso però interviene una comunicazione in più con il nodo centrale,dato che comunque devo avvisare il nodo centrale dell'attivazione di quel nodo.

Se qualcuno ha in mente un altro metodo, è ben accetto.

perché?
Da me il satellite si sveglia e se il caso trasmette senza essere interrogato, trasmetto direttamente numero (indirizzo) del satellite e temperatura, senza attendere richiesta
Stiamo pensando di aggiungere una fase di ore-sincronismo. Col satellite che prima di trasmettere vede se il canale è libero, ma sto valutando se ne vale la pena

Devo avvisare il nodo centrale, perchè vorrei implementare dei comandi da inviare al nodo periferico, ad esempio per modificare alcuni parametri. Io ho necessità che i pacchetti vadano a destinazione senza interferenze, quindi volevo trovare un modo per fare il channel sense con i moduli che ho a disposizione, ma per fare ciò dovrei andare a modificare la libreria rh_rf24, e sinceramente è un passo troppo lungo in questo momento. Ora proverò a sfruttare quello che hai detto tu, per effettuare quel tipo di connessione.

Idea senza RTC:

Il nodo centrale continua a chiamare a rotazione i periferici (ciascuno col suo nome).

Quando un periferico si sveglia aspetta di essere chiamato, e a quel punto trasmette sicuramente su canale pulito perché gli altri parleranno solo quando chiamati (visto che si parla di slot di 10..20 secondi immagino che i tempi non siano stringenti).

Poi a seconda dell'affidabilità richiesta si può implementare un ACK da centrale a periferico o una richiesta di ritrasmissione.

In ogni caso i pacchetti dati devono avere un controllo errori robusto, minimo un CRC16 (non basta uno XOR o un checksum).

Si questa è una buona idea, per ora lascio perdere gli RTC dato che ancora devo comprarli. Grazie, lascio il topic aperto, casomai a qualcuno vengono altre idee in mente.

Ciao, vi riscrivo su questa discussione perchè vorrei sapere quanto impiega il microcontrollore per passare dallo stato PWR_DOWN allo stato attivo. Non riesco a trovare questo dato nel datasheet.

... se ben ricordo, riavviato l'oscillatore, pochi cicli di clock ... nel datasheet c'è sicuramnete, magari non come valore in una tabella, ma in qualche grafico temporale, prova a cercarlo ... ::slight_smile:

Guglielmo

ok, provo a cercare meglio, grazie per la dritta :slight_smile:

Ragazzi torno a scrivervi. La rete funziona utilizzando gli RTC ds3231, il problema è che si generano offsett tra i vari Arduino che devo corregere ogni volta. Vi è un modo per modificare la frequenza di clock degli RTC, al fine di eliminare questo offset? Sapete indicarmi qualche guida?

L'uomo con un orologio conosce l'ora
L'uomo con due orologi conosce il dubbio

Mi stanno facendo impazzire , comunque la rete funziona, ogni nodo si sveglia al momento giusto, ma questi offset mi fanno impazzire. Devo correggerli spesso, via software.

Puoi risolvere decidendo dal nodo centrale una volta al giorno (ad esempio ma potresti farlo anche più spesso se necessario) di inviare l'ora da settare ai nodi periferici, lo potresti fare quando il nodo periferico contatta il master, come risposta invii l'ora da settare

Come sei messo ?
Io dopo che mi sono arrivati gli attiny85 ho quasi finito.
Mi manca solo la fase di ack dopo trasmissione.
Se mi va bene oggi pubblico il definitivo
Però io tengo l'ora centralizzata, presa da server ntp, i miei satelliti non sanno l'ora

Allora, io praticamente ora ho un nodo principale che raccoglie le informazioni e gli altri che trasmettono in delle slot temporali a loro dedicate. Ovvero se la sincronizzazione è perfetta, si svegliano, recuperano informazioni dal server per eliminare offset e poi trasmettono il dato. Il problema di fondo è l'utilizzo sia di millis e sia dell'RTC.

Purtroppo l'RTC ds3231 non conta i millisecondi passati,ed è un bel problema. E' presente un'uscita a 32Khz sull'RTC ma non so come utilizzarla sinceramente, qualcuno di voi ha un'idea? Leggevo in rete la possibilità di contare i millisecondi grazie ad interrupt ma, credo che questo rallenterebbe il programma. Un'altro metodo sarebbe quello di rendere accurato il timer0 di Arduino, ma anche in questo caso non trovo neanche un esempio in giro da cui posso studiare.

Scusa, ho capito male io?
il satellite si sveglia
contatta il server per sapere come correggere l'orario
corrregge l'orario
trasmette
e torna a nanna?
e quale sarebbe il problema?
EDITO ah, s', ovvio, capito adesso, SE la sincronizzazione è perfetta
pero' non mi è chiara la dinamica, scusami
ma ogni quanto trasmetteresti?
quante macchine, che dati trasmetti, un idea generale di cosa vuoi fare, sarebbero utili per capire
cosè? un termometro distribuito, un antifurto...

Il nodo centrale collegato al pc esegue sempre lo stesso ciclo ogni 4 secondi e di questi 4 secondi, utilizza 1 secondo per inviare in BROADCAST informazioni riguardo il tempo passato dall'inizio dei 4 secondi e il valore dell'RTC. Il client quando si attiva preleva questi dati e corregge gli errori. Passato questo secondo invia i dati e aspetta un ack. Il problema è quel secondo, purtroppo è necessario. Però potrei ridurre gli errori se solo ci fosse un modo per contare i millisecondi dell'RTC.

Le informazioni le invio in broadcast perchè in questa maniera posso permettere la sincronizzazione di altri nodi che posso aggiungere durante il funzionamento della rete.
Quindi supponiamo che ci siano 10 nodi già sincronizzati. Quando uno si sveglia corregge l'offset, trasmette ed esegue altre operazioni per un intervallo di 4 secondi, poi dorme per un tempo pari al numero dei nodi della rete moltiplicato per l'intervallo utilizzato(4 secondi nel mio caso).

Comunque lasciamo stare cosa invio, ma più che altro è il problema della sincronizzazione.Che si mantiene, ma dovrebbe essere migliorato. Comunque appena lo finirò posterò anche il mio progetto, per ora c'è tanto da sistemare.

BlackHole900:
Il client quando si attiva preleva questi dati e corregge gli errori.

che cosa vuol dire questa frase?
se il client non è li ad ascoltare, ma si deve ancora svegliare, quello informazioni, dove sono rimaste?
cioè:
il master trasmette, delle due l'una
o il satellite è acceso, riceve e fa quello che deve
oppure è spento, lui e la sua radio, quelle info sono perse
o amgari vuoi dire che il master trasmette ogni 4 secondi e il client, 'solo se acceso' effettua la correzzione?
ma in questo caso devi essere sicuro che il client sia già acceso al momento che il master trasmette
cosa fai, lo fai svegliare un paio di secondi prima del previsto?
no, inutile, non mi è chiaro che problema hai e che dinamica usi
se metti il programma ne posso uscire....

Scusa, piu' ti leggo e ti rileggo e meno capisco
tu usi degli RTC che hanno accuratezza di 2 parti per milione
e hai difficoltà di timing?
scusa, ma non ci credo, con accuratezza di due parti per milione e slot time di 4 secondi tu potresti avere dei problemi non prima di un milione di secondi (che fa' un errore atteso di 2 secondi, mezzo slot time)
un milione di secondi sono un fracco di tempo, circa 11 giorni
Non è ancora passato abbastanza tempo da quando hai cominciato per aver visto questi problemi, siamo al 27 maggio e non credo che tu abbia cominciato con gli RTC molto tempo fa
faccio delle libere ipotesi e poi mi fermo, visto che senza dettagli da parte tua non si va molto avanti

  1. tu ti affidi per la riaccensione dei satelliti solo sul watchdog, e questo potrebbe essere non preciso
  2. tu non verifichi mai la correttezza dei tempi dei vari satelliti e lasci che tra watchdog e tempi tecnici vari lentamente escano fuori passo
    secondo me quello che vuoi fare si fa tranquillamente senza alcun RTC, e ti è già stato detto come
    io farei così, senza alcun RTC
    divido il tempo di trasmissione in slot-time di 4 secondi
    faccio svegliare da watch dog il satellite di turno (tra poco vedi come)
    il satellite aspetta la trasmissione da parte del centrale
    il centrale trasmette al secondo 2 del time slot
    alla ricezione il satellite ri-regola i suoi tempi (memorizza millis, ad esempio)
    il satellite trasmette quello che deve trasmettere nel secondo 3 (ovvero mille millisecondi dopo la ricezione)
    il satellite fa quello che deve
    al termine dei suoi compiti il satellite calcola il tempo di sleep che gli serve per svegliarsi circa un secondo prima della prossima trasmissione a lui destinata,
    se sbaglia in più, ovvero dorme troppo, ha un secondo di margine
    se sbaglia in meno, ovvero dorme troppo poco, nulla di grave, aspetta la trasmissione un pochino di più, ma tanto ripete i calcoli ad ogni ciclo
    naturalmente il master ripete un ciclo di 4 secondi, al secondo 2 trasmette e si aspetta una ricezione al secondo 3
    se calcoli in maniera analitica i massimi errori del master e del satellite puoi regolare i tempi in maniera da avere anche più di un secondo di margine se per caso il satellite si "sveglia tardi"
    se oltretutto usi degli rtc con un pin di sveglia, come quelli che usi, puoi, prima di andare a mandare a dormire il sattellite, ri-calcolare il wake up time sul valore attuale ottenuto dal timing delle trasmissioni, in questa maniera nemmeno ti affidi al watch dog, che non è precisissimo
    ma comunque, in ogni caso, se l'errore massimo atteso sommando l'errore del master e quello del satellite è minore della fascia di sicurezza che gli lasci, sei sicuro che si ri-sincronizzano ad ogni trasmissione