Ago 202016
 

Ne abbiamo parlato spesso dei moduli NR24L01+, ma quest’oggi approfitto di una richiesta particolare che mi è giunta per effettuare alcune prove con i nuovi moduli che mi sono arrivati. In passato ero limitato da due soli moduli con antenna stampata, ma ora ho preso una decina di nuovi moduli a cui se ne aggiungono 4 con l’antenna esterna che dovrebbero garantirmi una portata decisamente superiore. Inoltre ho acquistato anche delle antenne esterne più performanti e sarà l’occasione per testarle.

Un piccolo aiuto per un grande progetto

La richiesta di aiuto questa volta è stata davvero particolare, mi è giunta da Futuro Solare, una onlus Siciliana che si occupa dello sviluppo di tecnologie inerenti lo sviluppo di veicoli ad energia solare a basso costo, più nel particolare l’attuale progetto è un’auto a singolo pilota, che non poteva che chiamarsi Archimede. Dal 21 al 26 settembre quest’auto parteciperà  all’iLumen European Solar Challenge che si terrà nel circuito di Zolder, in Belgio ed il regolamento di gara prevede quantomeno la telemetria monodirezionale, ossia la trasmissione dei dati della vettura dall’auto a bordo pista. Ciò permette di trasmettere al team i valori di capacità residua e temperatura delle batterie, la temperatura dei pannelli solari, la coppia applicata ai motori, etc, senza contare le applicazioni future che prevedono ad esempio il battito cardiaco e la temperatura corporea del pilota o la trasmissione bidirezionale per intervenire sul funzionamento della vettura. Siccome già ora tutta l’elettronica è gestita da Arduino, perchè non usare i moduli nrf24 per questo compito? Ma come spesso accade, anche il buon Marco che si occupa della realizzazione del sistema, si è trovato un po’ in difficoltà nello sviluppo del protocollo di comunicazione per cui oggi ci soffermiamo ancora una volta su questi moduli ma con una bella sorpresa, una nuova libreria sviluppata apposta per l’occasione e che andrò a breve ad integrare nella McMajan Library Pack, anch’essa aggiornata in varie parti, in particolare per renderla compatibile con Arduino Due.

Cavi e cavetti

Prima di tutto farei un ripassino su come collegare i moduli, so che è una ripetizione ma avere tutto sott’occhio nello stesso articolo è sempre molto comodo. Rivediamo perciò brevemente la piedinatura dell’interfaccia SPI che come sappiamo è differente in tutte le schede Arduino a meno di utilizzare il connettore ICSP. Qui sotto vi riporto la solita tabellina.

Arduino Board MOSI MISO SCK SS (slave) SS (master)
Uno / Duemilanove / Pro / Nano / Fio 11 or ICSP-4 12 or ICSP-1 13 or ICSP-3 10
Mega1280 or Mega2560 51 or ICSP-4 50 or ICSP-1 52 or ICSP-3 53
Leonardo / Micro / YUN ICSP-4 ICSP-1 ICSP-3
Due ICSP-4 ICSP-1 ICSP-3 4, 10, 52
Mini 11 12 13

Per completezza vi riporto in maniera grafica i pin del connettore ICSP: qui a lato potete vedere una piccola porzione di uno screenshoot della mia App icspin cui si possono vedere le varie connessione nel loro “ordine fisico”. Notare il numero uno che identifica appunto il primo pin del connettore e che normalmente trovate sulle varie schede segnato con un piccolo pallino.

Vi propongo qui sotto uno schemino riassuntivo anche della piedinatura dei moduli NRF24. Faccio notare che il pinout è il medesimo sia per i moduli con antenna stampata che quelli con antenna esterna. Lo schema in questo caso è orientato guardando i pin esattamente come nella foto.

rf24-pin

Cerchiamo di non scordare che il modulo è alimentato da una tensione compresa fra 1.9 e 3.6V ma i restanti pin sono tolleranti anche ai 5V. Per questo motivo NON potete prelevare l’alimentazione dal connettore ICSP che è a 5V a meno di non interporvi un regolatore di tensione, mentre i restanti pin possono essere tranquillamente collegati sia alle schede a 5V come Arduino UNO che a 3.3V come Arduino DUE.

McAir24

Come vi accennavo, per l’occasione ho scritto una nuova libreria, la McAir24. Questa nuova libreria è derivata della Mirf che pare non essere più supportata visto che sono diversi anni che non viene aggiornata. Ho aggiunto il supporto ad Arduino DUE, ho introdotto alcuni miglioramenti del codice e rivisitato il sistema di inizializzazione. Ma sin qui nulla di particolarmente eclatante, la vera novità sta nell’integrazione di un sistema semplificato per l’invio e ricezione di dati semplici, e con semplici intendo singoli caratteri, interi, float o unsigned long. La verità è che nella maggior parte dei casi non abbiamo bisogno di trasferire complesse strutture di dati, ma più di frequente abbiamo la necessità di inviare dati semplici, come possono essere letture di temperatura, umidità, pressione, tempo, etc. I dettagli di funzionamento della libreria ve li presenterò in una pagina apposita che pubblicherò a breve assieme alla libreria stessa, oggi ci accontentiamo di risolvere il problema della trasmissione dei dati e vedremo finalmente una prova comparativa di portata fra i moduli con antenna stampata ed esterna. Le fasi di preparazione sono abbastanza simili a quelle che avevamo con la Mirf, ho cercato di mantenerle la maggior similitudine possibile per semplificare il passaggio alla nuova libreria, per chi fosse interessato a farlo.

#include <SPI.h>
#include <McAir24.h>
#include <ss_nrf24.h> 

Le iniziali inclusioni non hanno bisogno di particolari commenti visto che devono essere fatte così come le trovate.

void setup()
{
  McAir24.init(9,10); //ce,csn
  UseMcAir24Data;
  McAir24.Set_Speed_Power(McAir24_SPD_1M | McAir24_PWR_18dB);
  McAir24.setChannel(40);
  McAir24.setRADDR((byte *)"clie1");
}

Il setup necessita di sole 5 istruzioni. Intanto vediamo che la classe McAir24 è già predefinita per cui non dobbiamo preoccuparci di definirla noi. L’istruzione init() inizializza i parametri fondamentali per il funzionamento del modulo, inoltre vengono specificati i numeri dei pin ce e csn. Attenzione che questa istruzione deve essere sempre la prima delle istruzioni che riguardano il setup del modulo. Successivamente troviamo UseMcAir24Data che come vedete non prevede l’uso delle parentesi perchè non è una funzione ma un #define che esegue alcune operazioni necessarie ad implementare il sistema di invio semplificato dei dati di cui vi accennavo (McAirData). Non è per nulla obbligatorio usare questa modalità di invio / ricezione, e nel caso venga usata si possono tranquillamente mescolare le due modalità. L’istruzione Set_Speed_Power serve a settare velocità e potenza di trasmissione del modulo, cosa che con la Mirf avveniva solamente con la manipolazione diretta dei registri. I parametri possibili sono quelli qui sotto. Vi segnalo che per oscuri motivi con i nuovi moduli in mio possesso, nonostante siano sicuramente degli nrf24L01+, non sono risuscito a settare la velocità di 250K al momento della stesura dell’articolo ne con la mia libreria ne con le altre. Ho avuto i primi riscontri positivi quando l’articolo era oramai finito per cui non troverete i test a questa velocità, ma sapete già che il passaggio a questa velocità permette di recuperare ancora un po’ di copertura del segnale se questa e la nostra priorità.

  • McAir24_SPD_250K
  • McAir24_SPD_1M
  • McAir24_SPD_2M

Mentre i valori di potenza sono:

  • McAir24_PWR_18dB
  • McAir24_PWR_12dB
  • McAir24_PWR_6dB
  • McAir24_PWR_0dB

dove lo 0 indica la massima potenza, 18 la minima. setChannel serve chiaramente a stabilire il canale di trasmissione e ricezione, ricordo che è un valore compreso fra 0 e 127, ma in alcuni paesi potrebbero esserci delle restrizioni (sino a 84 in USA ad esempio). Ogni singolo canale aumenta la frequenza di circa 1MHz, anche se l’esatta occupazione di frequenze dipende anche da altri fattori, primo fra tutti la velocità di trasmissione. La setRADDR serve a settare l’indirizzo ricevente (5 caratteri), ossia del modulo locale. Faccio invece notare che usando il sistema McAirData non è necessario usare la setPayLoadSize in quanto viene automaticamente impostata a 6 e ricontrollata ad ogni trasmissione, ma nel caso non usiate il sistema McAirData, deve essere usata e deve avere lo stesso valore fra trasmittente e ricevente.

Ora dobbiamo preparare la trasmissione dei dati sfruttando il sistema McAirData. La prima cosa da fare è settare l’indirizzo di destinazione con l’istruzione setTADDR. Se la destinazione è sempre la medesima vi conviene inserire questa istruzione direttamente nel setup iniziale.

McAir24.setTADDR((byte *)"serv1");

Il sistema McAirData si basa su una versione leggermente modificata del sistema usato in questo vecchio articolo, più nel dettaglio per ogni dato possiamo ora specificare due valori numerici, ognuno compreso fra 0 e 255. Questi valori che ho chiamato gruppo ed elemento, possono essere usati a vostro piacimento, potreste ad esempio stabilire che il gruppo 1 contiene valori di temperatura o che il 5 contiene valori di umidità, o quel che preferite. Una volta che avete deciso il tipo di codifica da usare, non dovete far altro che usare l’istruzione SendAirData

McAir24.SendAirData(1,5,time);

Nell’esempio sopra viene inviata la variabile time, specificando un gruppo pari a 1 ed elemento pari a 5. Finito, non dovete far altro, questa istruzione si occupa di tutto, controlla la lunghezza del payload, invia il dato, attende l’effettiva trasmissione,  e poi ritorna il controllo al vostro sketch. Non so se sono riuscito a chiarire il concetto, ma per inviare il dato di nostro interessa ho usato una sola istruzione, senza puntatori, allocazione di memoria ne niente altro.

Per completezza vi segnalo che è possibile aggiungere un quarto parametro opzionale che indica il delay in millisecondi da attendere fra la fine trasmissione ed il ritorno allo sketch richiamante. Questo è di default impostato a 30 e serve a concedere all’Arduino ricevente un tempo sufficiente per gestire i dati ricevuti prima che ne vengano inviati di nuovi con il concreto rischio di saturare il buffer. Se però abbiamo la certezza di non inviare ulteriori dati in rapida successione, come nell’esempio del ping, possiamo aggiungere un ,0 in modo da eliminare questo ritardo.

Ora non ci resta che leggere il dato ricevuto sul server. Anche qui vi sono venuto incontro con un lavoro di semplificazione senza eguali. Per testare se ci sono dati pronti basta utilizzare la funzione GetAirData. Questa si occupa di ogni possibile aspetto della ricezione, una volta che ritorna un valore true, saprete che è stato ricevuto un dato a cui potete facilmente accedere:

if(McAir24.GetAirData())
{
  Serial.printf(McAirData.datalong); // semplificabile con McAirDataLong
  Serial.printf(McAirGroup);   
  Serial.printf(McAirElement); 
}

Come potete osservare con McAirData, McAirGroup e McAirElement potete accedere ai tre elementi della trasmissione. L’unica accortezza riguarda il primo, infatti nell’esempio trovate McAirData.datalong in quanto è atteso un dato di tipo long, ma ci sono altre tre possibilità che sono datafloat, dataint e datachar per i rispettivi tipi di dato. Ma come avrete già intuito ho semplificato ulteriormente la cosa con le parole chiave McAirDataLong, McAirDataFloat, McAirDataInt e McAirDataChar che permettono l’accesso diretto a ogni singolo tipo di dato.

Vediamo ora un semplice esempio, vi riporto due listati, da inserire rispettivamente nell’Arduino trasmittente e ricevente. Il primo listato non fa altro che preparare tre float con tre diversi valori e li invia ripetutamente alla stazione remota. Quest’ultima riceve i float, li identifica e li stampa sulla porta seriale. Nell’esempio ho usato il gruppo ‘T’ per tutti i valori, come se fossero ad esempio delle temperature, mentre come elementi ho usato i numeri progressivi 1, 2 e 3.

#include <SPI.h>
#include <McAir24.h>
#include <ss_nrf24.h>
float t1,t2,t3;

void setup()
{
  Serial.begin(9600);
  while (!Serial);
  McAir24.init(9,10); //ce,csn
  UseMcAirData; 
  McAir24.Set_Speed_Power(McAir24_SPD_1M | McAir24_PWR_18dB); 
  McAir24.setRADDR((byte *)"serv1");
  McAir24.setTADDR((byte *)"clie1");
  McAir24.setChannel(40);
  Serial.println("Start sending data..."); 
  t1=50.3;
  t2=80.4;
  t3=15.6;
  
}
void loop()
{
   McAir24.SendAirData('T',1,t1);
   McAir24.SendAirData('T',2,t2); 
   McAir24.SendAirData('T',3,t3); 

   delay(1000); 
}

Per quanto riguarda la ricezione:

#include <SPI.h>
#include <McAir24.h>
#include <ss_nrf24.h>

void setup(void)
{
  Serial.begin(9600);
  while (!Serial);
  McAir24.init(9,10); //ce,csn
  UseMcAirData; 
  McAir24.Set_Speed_Power(McAir24_SPD_1M | McAir24_PWR_18dB);
  McAir24.setRADDR((byte *)"clie1");
  McAir24.setChannel(40);
  Serial.println("Init OK"); 
}


void loop(void) // loop principale....
{
  if(McAir24.GetAirData()) // controllo se ho ricevuto dati rf24
  {
    if(McAirGroup=='T') // lettura temperature
    {
      if(McAirElement==1) Serial.print("Temp1: "); 
      else if(McAirElement==2) Serial.print("Temp2: "); 
      else Serial.print("Temp xx: "); // ho volutamente "fatto finta" di non conoscere l'elemento 3
      Serial.print(McAirDataFloat)); //stampo la lettura
    }
    else Serial.print("Gruppo non riconosciuto "); // non sono temperature
    Serial.println(" "); 
   
  } 
}

Spero tanto di essere riuscito a farvi capire ed apprezzare quanto diventi semplice inviare e ricevere dati grazie a McAirData. Ovviamente nella libreria che pubblicherò a breve dopo gli ultimi ritocchi, trovate tutta una serie di esempi già pronti che mostrano il funzionamento della libreria.

La portata del segnale

Come vi accennavo oltre ai moduli con antenna stampata, mi sono procurato quelli con l’antenna esterna e, giusto per completare il quadro, ho acquistato anche delle antenneantenne esterne più performanti (9dbi) ed ora andrò a testare le reali potenzialità di questi moduli. Nella figura a lato potete vedere il confronto fra l’antenna standard del modulo e quella potenziata che ora vado a provare per la prima volta. Il mio interesse non è tanto l’utilizzo esclusivo all’aperto quanto quello indoor, in particolare mi interessa capire quanta distanza possiamo coprire in un reale ambiente casalingo. A dirla tutta però ho l’interesse a posizionare alcuni sensori / attuatori anche all’esterno della casa per cui farò delle prove anche al di fuori della casa stessa.

Mi risulta davvero difficile mostrare in maniera semplice i risultati delle prove in quanto la distanza raggiunta dal segnale dipende dal numero di pareti attraversate, il loro spessore, la loro composizione, etc. Ho preparato due immagini, la prima è una schematizzazione 3D della casa dove vivo, che in realtà è solo parte di una casa molto più grande. Questa prima immagine mi permette di evidenziare meglio i segnali più deboli. La seconda immagine è una vista satellitare che mi permette di mostrare in maniera più evidente i segnali più forti. Sia chiaro che la rappresentazione non è delle più fedeli, ovviamente il segnale non segue un’ellisse perfetta in quanto la dipendenza dai muri fa si che la distribuzione sia irregolare. Inoltre nei segnali più forti non potevo certo entrare nelle case altrui per cercare i limiti di trasmissione per cui ho riportato i limiti dell’abitazione.

18db-pcbIn questa prima immagine a sinistra vediamo in rosso la posizione del trasmettitore. In verde vediamo la portata dei moduli con antenna stampata su pcb, con impostazione della potenza di entrambi i moduli a -18dBi e velocità di 1MB/s. Come vedete il segnale arriva a malapena oltre i muri perimetrali della stanza. Per questo motivo non ho testato i 2MB/s in quanto possono essere utili solamente per comunicazioni nel contesto della stessa stanza. La velocità di 250KB/s non l’ho testata per il semplice motivo che non sono riuscito a far funzionare i moduli a questa velocità in tempo per la stesura dell’articolo, ma dalle prove precedenti c’è da aspettarsi una copertura leggermente superiore, diciamo un ulteriore 10-15%.

In giallo vediamo gli stessi moduli, sempre a 1MB/s con la potenza portata al massimo (0dB). Come potete osservare con questa semplice modifica riesco a coprire tutto l’appartamento e parte del giardino esterno. Qui di seguito vediamo invece l’immagine satellitare della casa, in rosso verde e blu gli stessi significati dell’immagine appena vista. In azzurro invece i moduli sempre a 1MB/s a 0dB ma con l’antenna esterna esatellite_segnale, come potete vedete, la copertura aumenta in modo considerevole. Se guardata a sinistra verso il basso, la copertura è circa 3-4 volte superiore. Faccio invece notare che in basso a destra il segnale pur molto più esteso, non copre interamente il giardino della casa. Ciò è legato al fatto che il trasmettitore si trova all’angolo opposto della casa per cui deve attraversare un numero di muri decisamente superiore, inoltre, cosa non comprensibile dall’alto, siamo da mezzo ad un piano più bassi per cui c’è parte della struttura in cemento armato del piano inferiore da attraversare. L’ultima prova ha riguardato l’antenna esterna potenziata, ma qui ho avuto una gran delusione. Nonostante abbia dotato entrambi i moduli di questo tipo di antenna, la portata complessiva ha oltrepassato di poco la limitante gialla, quella dei moduli con antenna stampata a pari velocità e potenza di trasmissione, molto peggio quindi dell’antenna esterna in dotazione. Non ho una spiegazione per questo tipo di comportamento, ma dovrò fare più approfondite verifiche per stabilire quale sia la causa del problema. Sulla vettura Archimede l’antenna usata è molto più performante e la portata all’aperto ha superato i 2.5Km, e questa è la dimostrazione che l’antenna ha la sua importanza, ma quelle che ho acquistato non sembrano all’altezza, anche se certamente non mi arrendo così facilmente al primo colpo.

  4 Responses to “nrf24 – Alziamo le antenne – it”

  1.  

    Ben venga una nuova libreria ma tieni conto che la libreria di riferimento per questi moduli è questa
    https://github.com/TMRh20/RF24
    Che invece viene aggiornata anche adesso.
    Sono interessanti anche le altre librerie sempre di TMRh20

    Occhio che in giro ci sono sketch che fanno riferimento ad una libreria omonima ma di Maniac Bug. E’ quasi identica ma alcune cose sono cambiate.
    Tipicamente l’errore è NRF24L01 and “error: void value not ignored as it ought to be”
    Ma basta cambiare lo sketch come ho scritto qui (su suggerimento di TMRh)
    https://zoomxtech.wordpress.com/2015/10/13/nrf24l01-and-error-void-value-not-ignored-as-it-ought-to-be/

  2.  

    Dimenticavo,
    un elettrolitico aggiunto all’alimentazione aiuta molto ad evitare molti errori dovuti ad alimentazione insufficiente nei picchi di trasmissione, se si alimenta il modulo da Arduino o cloni (specialmente i cloni).

  3.  

    C’ è la possibilità di leggere un valore del segnale ricevuto, tipo RSSI dei moduli RF Aurel o simili.
    Grazie
    Vincenzo

    •  

      Purtroppo no. Esiste solo la possibilità di avere un input del tipo “cìè segnale sufficiente” o “non c’è segnale sufficiente”. Nella libreria in via di definizione ho aggiunto un esempio che effettua uno scan ricorsivo su tutti i canali e stampa su seriale una sorta di “grafico a caratteri” che mostra i canali con più o meno segnale, ma ciò non sostituisce certo la “forza del segnale”. E’ davvero un peccato che manchi una funzione del genere, mi avrebbe decisamente semplificato la vita 🙂