electronics arduino wireless nrf24l01+ rf transceiver ricetrasmettitore

Ricetrasmettitore wireless economico per Arduino con NRF24L01+

È da un po' che volevo farlo, alla fine mi ci son messo. L'obiettivo è aggiungere un po' di domotica al mio appartamento, più per sfida che per utilità. Ho scelto di usare Arduino per la prototipazione, poi quando avrò finito il progetto userò i più economici Atmega328 da soli e magari con l'alimentazione a batterie. Ho ordinato un po' di cose, ma per il momento mi sono arrivati solo i due moduli NRF24L01+ che ho comprato su ebay. Così mi son messo a provarli.

A cosa servono?

Sono dei ricetrasmettitori in radiofrequenza a 2.4Ghz (la stessa del WiFi) veramente molto economici. Comprati nuovi su ebay per 3.70 Euro l'uno. Ovviamente non offrono funzioni avanzate quelle del WiFi, né velocità di trasmissione esorbitanti. Ma per un sistema di domotica van più che bene. E a differenza dei più famosi moduli a 433Mhz funzionano sia in ricezione che in trasmissione.
Per il momento ne ho solo due, ma ora che ho provato che funzionano probabilmente ne acquisterò altri.

Come sono fatti?

NRF24L01-dimensioni.png

Un piccolo PCB di 14x29 mm con 8 pin, antennina stampata e circuito integrato Nordic Semiconductor NRF24L01+. I pin hanno la distanza standard, ma non ho potuto attaccarli direttamente alla breadboard perché altrimenti sarebbero stati in corto. Così ho dovuto mettere due header come in foto:

header.jpg connesso.jpg

L'altra possibilità è usare dei cavetti jumper maschio-femmina (che non ho) in questo modo:

nrf24l01-wireless-module-with-arduino_1.jpg

Per collegarlo all'Arduino si usano 7 dei pin disponibili, cioè tutti tranne IRQ.

NRF24L01-pinout.png pinout-postit.jpg

Come si collega all'arduino

Attenzione! L'alimentazione è a 3.3V, non a 5V come l'Arduino. Comunque si può usare l'uscita a 3.3V dell'Arduino, che è vicino al pin dei 5V.

L'ho testato sia con l'Arduino Duemilanove (Atmega 328P), sia con il Mega (Atmega 1280). Per i due Arduino i pin sono differenti:

NRF24L01DuemilanoveMega
1 GNDGNDGND
2 VCC3V33V3
3 CE846
4 CSN747
5 SCK1352
6 MOSI1151
7 MISO1250
8 IRQ

In realtà CE e CSN possono essere collegati a un qualsiasi output digitale, basta cambiare le configurazioni del programma.

Il programma

Ho usato la libreria Mirf che mi è sembrata relativamente semplice da usare. Ho preso gli esempi di client e server nella libreria e modificati per un test più strong: trasmettere l'inizio della Divina Commedia in radiofrequenza.

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

#define MIRF_PAYLOAD 32

byte rxData[MIRF_PAYLOAD + 1];
byte txData[MIRF_PAYLOAD + 1];

void setup(){
  memset(rxData, 0, sizeof(rxData));
  memset(txData, 0, sizeof(txData));
  Serial.begin(9600);
  Mirf.cePin = 8;
  Mirf.csnPin = 7;
  Mirf.spi = &MirfHardwareSpi;
  Mirf.init();
  Mirf.setRADDR((byte*)"serv1");
  Mirf.payload = MIRF_PAYLOAD;   
  Mirf.channel = 10;
  Mirf.config();
}

void loop(){
  memset(rxData, 0, sizeof(rxData));
  if(!Mirf.isSending() && Mirf.dataReady()){
    Mirf.getData(rxData);
    Serial.println((const char*)rxData);
    Mirf.setTADDR((byte*)"clie1");
    for (unsigned i = 0; i != MIRF_PAYLOAD; ++i) {
      txData[i] = rxData[i] + 1;
    }
    Mirf.send(txData);
  }
}
#include <SPI.h>
#include <Mirf.h>
#include <nRF24L01.h>
#include <MirfHardwareSpiDriver.h>

#define MIRF_PAYLOAD 32

byte rxData[MIRF_PAYLOAD + 1];
byte txData[MIRF_PAYLOAD + 1];
const char msg[]= "Nel mezzo del cammin di nostra vita mi ritrovai per una selva oscura, che' la diritta via era smarrita. Ahi quanto a dir qual era e' cosa dura, esta selva selvaggia e aspra e forte, che nel pensier rinova la paura! Tant'e' amara che poco e' piu' morte; ma per trattar del ben ch'i' vi trovai, diro' de l'altre cose ch'i' v'ho scorte. Io non so ben ridir com'i' v'intrai, tant'era pien di sonno a quel punto che la verace via abbandonai.";
int msgIndex = 0;

void setup(){
  memset(rxData, 0, sizeof(rxData));
  memset(txData, 0, sizeof(txData));
  Serial.begin(9600);
  Mirf.cePin = 46;
  Mirf.csnPin = 47;
  Mirf.spi = &MirfHardwareSpi;
  Mirf.init();
  Mirf.setRADDR((byte*)"clie1");
  Mirf.payload = MIRF_PAYLOAD;   
  Mirf.channel = 10;
  Mirf.config();
}

void loop() {
  Mirf.setTADDR((byte*)"serv1");
  memcpy(txData, msg + msgIndex, MIRF_PAYLOAD);
  Mirf.send(txData);
  while(Mirf.isSending()){
  }
  delay(10);
  unsigned long time = millis();
  while(!Mirf.dataReady()){
    if (( millis() - time ) > 1000) {
      Serial.println("timeout");
      return;
    }
  }
  Mirf.getData(rxData);
  Serial.println((const char*)rxData);
  msgIndex += MIRF_PAYLOAD;
  if (msgIndex + MIRF_PAYLOAD > sizeof(msg)) {
    msgIndex = 0;
  }
} 

Qui vediamo il programma server e quello client. Il server ascolta continuamente i pacchetti in arrivo e appena ne riceve uno lo scrive nella seriale e lo invia al client dopo averlo criptato con una semplice addizione. MIRF_PAYLOAD definisce la lunghezza in bytes dei pacchetti trasmessi. Nel programma client vediamo la costante string msg che contiene i primi versi della Divina Commedia. Nel loop si invia a pezzettini di 32bytes il contenuto di msg e si ricomincia da capo.

La parte importante, sia nel client che nel server si trova in setup(), dove viene configurata la libreria Mirf. Infatti si impostano di PIN configurabili (CE e CSN), il payload, il canale (da 0 a 127) e l'indirizzo del dispositivo (massimo 5 bytes).

Dopo aver caricato il firmware client nel Mega e il server nel Duemilanove, vediamo che cominciano a comunicare.

test.jpg

Ti è piaciuto l'articolo? Condividilo! Commentalo!

comments powered by Disqus