[RISOLTO] NRF24L01+ && Mirf && Shockburst && Multiceiver

Ciao a tutti, sono iscritto da tempo sul forum che consulto spesso ed è giunto il momento del mio primo post.
Mi sto divertendo con arduino per creare una piccola rete domestica wireless basata su moduli nrf24l01+ con antenna integrata (quelli piccoli).
Attualmente la situazione è questa (ovviamente tutti i moduli sono provvisti di nrf24l01+):
1 arduino nano che funge da master con collegamento seriale ad una linux box (PRX)
2 arduino nano PTX
3 modulo standalone atmega8 PTX
4 modulo standalone atmega328 PTX
5 arduino nano PTX

Gli sketch sono basati sulla libreria mirf ed erano impostati con payload 32byte, 250kbps , muticeiver&shockburst disabilitati.
Una volta posizionati nelle stanze mi sono reso conto che purtroppo alcuni moduli non erano nel range di copertura del master con conseguente perdita di pacchetti ed ho deciso di sostituire l'nrf24l01+ del master con uno NRF24L01+PA+LNA SMA . La situazione è nettamente migliorata ma a volte qualche pacchetto veniva perso comunque credo a causa di collissioni in trasmissione.
Dopo aver verificato l'alimentazione dei moduli su tutti gli arduino (saldando dei condensatori da 100nf direttamente sui moduli basati su arduino nano) ho consultato il datasheet ed ho deciso di provare ad abilitare le funzioni shockburst/multiceiver.
Inutile dire che se sto scrivendo questo post non sono riuscito a settare correttamente i registri.
Dopo averli variati purtroppo l'affidabilità è peggiorata ed in più ho notato che a volte ai ptx viene inviato un doppio comando quando in realtà ne dovrebbe arrivare solo uno.
Cercando su internet ho trovato un documento dove avvisa che effettivamente ci potrebbero essere dei problemi con la pipe0 e con i timing dell'ack.

Per farla breve, nonostante i miei sforzi, non solo non ho risolto il problema ma in più ho una gran confusione in testa.
In rete sono reperibili molte librerie con supporto multiceiver ma capirete che "mi prende il freddo" al solo pensiero di dover riadattare tutto il codice degli sketch specialmente perchè i moduli sono già posizionati nelle stanze e non è comodissimo riflashare i moduli, specialmente quelli standalone dove devo estrarre fisicamente il pic.
In più mi è sorto il dubbio che la libreria mirf non possa gestire il device in multiceiver.
Per il momento non entro nel dettaglio altrimenti rischierei di scrivere un pò troppo. Anche rileggendo più volte il datasheet ho ancora qualche dubbio sulla gestione delle pipe e come impostare correttamente i registri per poter avere una comunicazione wireless tra questi moduli senza perdere pacchetti.
Spero che qualcuno di voi possa darmi qualche suggerimento in merito perchè dopo una settimana di prove non sono riuscito a venirne a capo.
Ricapitolando....
Volendo impostare la rete a stella in questo modo:
250kbps
crc 2 byte
shockburst/multiceiver abilitato (se abilito shockburst di conseguenza è obbligatorio il multiceiver giusto?)
ART 15
ARD 4000uS

Di seguito parte dello sketch del PRX e del PTX.

sul PRX :

#include <SPI.h>
#include <Mirf.h>
#include <nRF24L01.h>
#include <MirfHardwareSpiDriver.h>

char * nodo[10] = {
  "ard00","ard01","ard02","ard03","ard04","ard05","ard06","ard07","ard08","ard09"};
const byte nodoid = 0; // id del nodo assegnato a questo sketch
const byte destid = 1; // id del nodo al quale trasmettere - viene riassegnato nel loop


//Set the SPI Driver.
  Mirf.cePin = 8;
  Mirf.csnPin = 7;
  Mirf.spi = &MirfHardwareSpi;
  //Setup pins / SPI.
  Mirf.init();
  //Configure reciving address.
  Mirf.setRADDR((byte *)nodo[nodoid]);
  //set payload 
  Mirf.payload = 32;
  //The RF channel frequency is set according to the following formula: F0= 2400 + RF_CH [MHz]
  Mirf.channel = 90;
  Mirf.config();
  
  // imposto lunghezza indirizzo device a 5 bytes
  //Mirf.configRegister(SETUP_AW, 0x03);
  
  // imposto come PRX , power up, crc a 2bytes
  Mirf.configRegister(CONFIG, 0x0F); 
  
  // imposto velocità a 250k, potenza finale al massimo 0dbm
  Mirf.configRegister(RF_SETUP, 0x26);
  
  // abilito l'auto acknowledgment su tutte le datapipe
  Mirf.configRegister(EN_AA, 0x3F);
  
  //abilito tutte le datapipe in ricezoine
  Mirf.configRegister(EN_RXADDR, 0x3F);
  
  //Mirf.configRegister(EN_RXADDR, 0x03);
  
  // PAYLOAD = 32BYTE
  Mirf.configRegister(RX_PW_P0, 0x20);
  Mirf.configRegister(RX_PW_P1, 0x20);
  Mirf.configRegister(RX_PW_P2, 0x20);
  Mirf.configRegister(RX_PW_P3, 0x20);
  Mirf.configRegister(RX_PW_P4, 0x20);
  Mirf.configRegister(RX_PW_P5, 0x20);
  
  // IMPOSTO GLI INDIRIZZI multiceiver
  Mirf.configRegister(RX_ADDR_P0, *nodo[1]);
  Mirf.configRegister(RX_ADDR_P1, *nodo[2]);
  Mirf.configRegister(RX_ADDR_P2, '3');
  Mirf.configRegister(RX_ADDR_P3, '4');
  Mirf.configRegister(RX_ADDR_P4, '5');
  Mirf.configRegister(RX_ADDR_P5, '6');
  
  
  
  // imposto l'auto retransmit count a 15 ed il tempo di reinvio del pacchetto a 4000us ( per impostare a 2250 us = 0x8F )
  Mirf.configRegister(SETUP_RETR, 0XFF);

sul PTX :

//Set the SPI Driver.
  Mirf.cePin = 8;
  Mirf.csnPin = 7;
  Mirf.spi = &MirfHardwareSpi;
  //Setup pins / SPI.
  Mirf.init();
  //Configure reciving address.
  Mirf.setRADDR((byte *)nodo[nodoid]);
  //set payload 
  Mirf.payload = 32;
  //The RF channel frequency is set according to the following formula: F0= 2400 + RF_CH [MHz]
  Mirf.channel = 90;
  Mirf.configRegister(CONFIG, 0x0E); 
  Mirf.configRegister(RF_SETUP, 0x26);
  Mirf.configRegister(EN_AA, 0x3F);
  Mirf.configRegister(EN_RXADDR, 0x3F);
  //Mirf.configRegister(EN_RXADDR, 0x03);
  Mirf.configRegister(RX_PW_P0, 0x20);
  Mirf.configRegister(RX_PW_P1, 0x20);
  Mirf.configRegister(RX_PW_P2, 0x20);
  Mirf.configRegister(RX_PW_P3, 0x20);
  Mirf.configRegister(RX_PW_P4, 0x20);
  Mirf.configRegister(RX_PW_P5, 0x20);
  Mirf.configRegister(SETUP_AW, 0x03);
  Mirf.configRegister(SETUP_RETR, 0XFF); 
  //Write channel and payload config then power up reciver.
  Mirf.config();
  Mirf.setTADDR((byte *)nodo[destid]);

Per avere il massimo della copertura e della affidabilità voi come impostereste i registri? :sweat_smile:

io ci ho perso mesi e mesi con la mirf per impostare il multiceiver.
dal datasheet non è molto chiaro come vadano impostati i registri e soprattuto come impostare le pipe
alla fine mi sono arreso.
ho riadattato il tutto usando la lib RF24.
c'è anche un'altra lib, RF24Network, già predisposta per creare una rete di sensori.

Grazie ricdata per avermi risposto. E già, anche rileggendo più volte il datasheet alcune cose non mi sono ancora chiare.
Ad esempio, supponendo una rete one to six, dall'immagine nel datasheet indica che in multiceiver al PRX andrebbero assegnati a tutti i registri RX_ADDR_PN gli indirizzi dei PTX, mentre sui PTX in teoria andrebbero assegnati solo i registri RX_ADDR_P0 e il TX_ADDR.
Inoltre sul datasheet leggo che il TX_ADDR dovrebbe essere usato solo dai PTX. E come faccio ad inviare arbitrariamente un payload dal PRX al PTX se non posso impostare l'indirizzo del PTX?
Leggendo il file mirf.ccp trovo che

void Nrf24l::setRADDR(uint8_t * adr) 
// Sets the receiving address
{
	ceLow();
	writeRegister(RX_ADDR_P1,adr,mirf_ADDR_LEN);
	ceHi();
}



void Nrf24l::setTADDR(uint8_t * adr)
// Sets the transmitting address
{
	/*
	 * RX_ADDR_P0 must be set to the sending addr for auto ack to work.
	 */

	writeRegister(RX_ADDR_P0,adr,mirf_ADDR_LEN);
	writeRegister(TX_ADDR,adr,mirf_ADDR_LEN);
}

e quindi varia in automatico il registro P0..... ma sul PRX il P0 non deve contenere costantemente l'indirizzo di un singolo PTX?

In più leggendo il commento
"RX_ADDR_P0 must be set to the sending addr for auto ack to work."
e come se lasciasse intendere che la libreria riesca a gestire l'auto ack esclusivamente utilizzando il RX_ADDR_P0.
Di conseguenza, a meno che non stia prendendo un cantonata mostruosa, la domanda è:
ma per usare i moduli in shockburst non è obbligatorio impostare in multiceiver e di conseguenza abilitare tutte le pipe?
Il PRX come può gestire l'autoack su tutti i moduli con il solo P0?
La libreria è stata concepita per essere utilizzata con un massimo di due nrf24l01?
Se nello sketch del PRX uso la funzione setTADDR mi varia P0, cosa che non dovrebbe fare impostando i moduli in multiceiver? giusto?
Appena ho un pò di tempo vedo se riesco a capire dov'è il problema, ma dal tuo intervento mi sembra di capire che faccio prima ad utilizzare la libreria RF24.
Adesso vado un pò di fretta, scusatemi per eventuali errori, appena ho novità vi aggiorno

se non ricordo male la mirf non gestisce ACK, milticeiver e shochburst.
puoi usarla anche per più di due device, ma gli indirizzi vanno gestiti manualmente nello sketch.

mi dispiace ma non riesco ad esserti d'aiuto. già ci capii poco mentre lo stavo studiando, ora è passato del tempo ed è svanito anche quel poco.

Invece mi sei stato di grande aiuto, se non fosse stato per te starei ancora sbattendo sulla mirf.
Con la gestione manuale degli indirizzi la libreria mirf è facile da usare ed è stabile. Collegando due soli moduli ho fatto un test di 6 ore inviando un payload ogni 10ms non ho riscontrato problemi ( a 7 ms invece qualche dato lo perde).
In configurazione "standard" con 5 moduli nrf inviando dei payload da bash/master ogni 100ms perde almeno un payload su 10. Con la configurazione da me postata la situazione migliora ma quasi sempre arriva un doppio payload allo slave.
Ho dato uno sguardo alla rf24network, sulla "carta" sembra bellissima, non è proprio una mesh pura ma ci siamo vicini.
Adesso mi trovo davanti ad un bivio, tenermi la rete così com'è ed implementare l'ack da codice o fare il porting verso un'altra libreria (visto il progetto reale dello sviluppatore probabilmente utilizzerò rf24network).
Sicuramente opterò per la seconda sperando che non debba impiegare nuovamente decine e decine di ore per renderla stabile e "veloce".
Peccato mi sarebbe bastato l'autoack. Se qualcuno ha dei consigli da darmi sono tutte orecchie :slight_smile:
Non mi resta che mettermi nelle condizione di fare qualche test e soprattutto studiare la nuova libreria.
"Appena" avrò novità aggiornerò il thread.
Speriamo bene......

Ok, è stato più semplice del previsto :slight_smile:
Dalla Mirf sono passato alla RF24 e poi alla RF24Network per poi ritornare alla RF24 nel momento in cui mi sono accorto che il payload massimo per la RF24Network è di 24byte causa header (e il mio progetto utilizza payload a 32byte). Non so se può gestire payload superiori ai 24byte con le adeguate modifiche, non ho indagato a fondo.
Con ritrasmissione pari a 15 con 4000us di ritardo (sempre a 250kbps) ho notato qualche giovamento ma niente di eccezionale.
Dato che gli "slave" sono al confine del raggio di azione del master spesso il modulo slave riceveva più volte il payload. Questo perche il master è un NRF24L01+PA+LNA mentre gli slave sono degli NRF24L01 "normali" (quelli piccoli) e quindi il master non riceveva l'ack e ritrasmetteva il payload. La soluzione che ho adottato è stata quella di scartare da sketch i payload in arrivo uguali a quello precedente (più qualche piccola accortezza). Su un modulo slave, a circa 6mt dal master con due stanze di mezzo, ho risolto il problema con una mini EZ-10 scalata al 40% se non ricordo male ( http://www.freeantennas.com/ ).
Anche se il thread era riferito alla Mirf, posso affermare : 'probelma risolto' :slight_smile:

Ciao misix, volevo chiederti un consiglio visto che sei riuscito a risolvere questa tua situazione che sento molto "vicina" a quello che vorrei realizzare io.
Dovrei far comunicare 3 schede arduino (a,b,c) in modo che:

  • la prima scheda 'a' invii uno stesso segnale alle altre due (ex una costante intera)
  • 'b' e 'c' iniziano la comunicazione tra di loro
  • infine una delle 2 ('b' o 'c' indifferentemente) invia il risultato finale alla prima scheda 'a'.

A parte tutte le elaborazioni che dovrò implementare per sensori ecc, non ho trovato un esempio chiaro di base per impostare una comunicazione tra 3 schede arduino (con moduli nrf24l01+).
Di esempi chiarissi ce ne sono molti, ma se imposto la comunicazione 'a 2'. Ce ne sono tanti anche per le comunicazioni ad 'n' nodi dove la rete riconosce in automatico la configurazione...ma è troppo complesso per il mio livello e per i miei scopi.
A me servirebbe semplicemente capire come poter impostare una situazione del genere:

  • scheda 'a' invia segnale sia a 'b' che a 'c'
  • scheda 'b' e 'c' scambiano vicendevolmente segnali.
  • scheda 'b' o 'c' (alla fine dello sketch) inviano risultati ad 'a'.

Puoi indirizzarmi per favore?

Grazie 1000

Federico

Buon giorno a tutti. Io mi accosto al mondo dei moduli nrf24 da poco per cui può essere che sto dicendo una ovvietà.
Il mio pensiero è questo: ma non è possibili settare gli indirizzi dei vari client e quindi fare una sorta di ciclicità nelle interrogazione dei vari arduino sparsi per la casa in modo da non avere problemi di sovrapposizione delle trasmissioni?

Grazie anticipatamente