comunicacion-inalambrica-a-2-4ghz-con-arduino-y-nrf24l01

Comunicación inalámbrica a 2.4Ghz con Arduino y NRF24L01

¿Qué es el NRF24L01?

El NRF24L01 es un chip de comunicación inalámbrica fabricado por Nordic Semiconductor que podemos conectar a un procesador como Arduino

El NRF24L01 integra un transceptor RF (transmisor + receptor) a una frecuencia entre 2.4GHz a 2.5GHz, una banda libre para uso gratuito. La velocidad de transmisión es configurable entre 250 Kbps, 1Mbps, y 2 Mbps y permite la conexión simultánea con hasta 6 dispositivos.

El NRF24L01 también incorpora la lógica necesaria para que la comunicación sea robusta, como corrección de errores y reenvío de datos si es necesario, liberando de esta tarea al procesador. El control del módulo se realiza a través de bus SPI, por lo que es sencillo controlarlo desde un procesador como Arduino.

La banda de frecuencia es de 2400 a 2525 MHz, pudiendo elegir entre 125 canales espaciados a razón de 1MHz. Se recomienda usar las frecuencias de 2501 a 2525 MHz para evitar interferencias con las redes Wifi.

La tensión de alimentación del NRF24L01 es de 1.9 a 3.6V, aunque los pines de datos son tolerantes a 5V. El consumo eléctrico en Stand By es bajo, y de unos 15mA durante el envío y recepción. Lógicamente, el consumo del módulo es superior, pudiendo llegar hasta 150-250 mA en modelos con antenas más potentes.

Existen dos versiones de módulos que montan el NRF24L01, uno con antena integrada en forma de zig-zag y un alcance máximo de 20-30 metros, y la versión de alta potencia que incorpora amplificador y antena externa, con un alcance máximo de 700-1000 metros.

Sin embargo, el alcance real se ve limitado por muchos factores, incluso en condiciones visibilidad directa sin obstáculos. Con el módulo de antena integrada y alimentación desde Arduino y velocidad de transmisión de 2 Mbps el alcance será apenas de 2-3 metros.

Un factor de gran impacto en el alcance es la alimentación del módulo. Para conseguir el máximo alcance conviene alimentar el módulo con una fuente externa de 3.3V, estable y con potencia suficiente.

Los módulos NRF24L01 son ampliamente empleados por su bajo precio y buenas características. Podemos emplearlos, por ejemplo, para recepción remota de sensores como temperatura presión, aplicaciones de domótica y edificios inteligentes, activación remota de dispositivos como iluminación, alarmas, y control o monitorización de robots en el rango de hasta 700 metros.

Precio

Actualmente los módulos RF de 2.4 GHz que montan el NRF24L01 son dispositivos muy baratos. Podemos encontrar el modelo con antena integrada en zig-zag por 0.65€, buscando en vendedores internacionales de eBay o AliExpress.

Le versión con amplificador y antena externa tiene un precio superior de 1.70€, pero a cambio mejoran el alcance hasta 700-1000 metros, aunque para conseguir este alcance obligatoriamente necesitaremos alimentar el módulo con una fuente externa de 3.3V.

arduino-nrf24l01-2.4ghz-componente-antena

Lógicamente, en ambos casos, necesitaremos dos módulos NRF24L01, uno como emisor y otro como receptor.

Esquema de montaje

La conexión de un módulo RF 2.4 GHz NRF24L01 es sencillo, simplemente alimentamos el integrado desde Arduino mediante GND y 5V y conectamos los pines de datos como vimos en la entrada sobre el bus SPI.

arduino-nrf24l01-2.4ghz-conexion

Mientras que conexión vista desde el lado de Arduino quedaría así.

arduino-nrf24l01-2.4ghz-esquema

Como hemos dicho, el funcionamiento del módulo mejora si empleamos una fuente externa de 3.3V. En este caso, recordar poner Gnd en común. Para un óptimo funcionamiento también resulta conveniente conectar un condensador de 100pF - 1uF entre Gnd y 3.3V del NRF24L01.

El módulo funciona a 3.3V. No lo alimentéis a 5V o dañaréis el módulo.

Los pines de SPI que figuran son válidos para los modelos En Arduino Uno, Nano y Mini Pro. Para otros modelos de Arduino consultar el esquema patillaje correspondiente.

Ejemplos de código

Para realizar el control del NRF24L01 usaremos la librería RF24, disponible en este enlace.

La librería proporciona ejemplos de código, que resulta aconsejable revisar. Los siguientes ejemplos son modificaciones a partir de los disponibles en la librería

Enviar un string

El siguiente ejemplo muestra el envío de una cadena de texto desde un Arduino emisor a un Arduino receptor, que al recibir el texto lo muestra por puerto serie.

Código emisor

#include <nRF24L01.h>
#include <RF24.h>
#include <RF24_config.h>
#include <SPI.h>

const int pinCE = 9;
const int pinCSN = 10;
RF24 radio(pinCE, pinCSN);

// Single radio pipe address for the 2 nodes to communicate.
const uint64_t pipe = 0xE8E8F0F0E1LL;
 
char data[16]="Hola mundo" ;

void setup(void)
{
  radio.begin();
  radio.openWritingPipe(pipe);
}
 
void loop(void)
{
  radio.write(data, sizeof data);
  delay(1000);
}

Código receptor

#include <nRF24L01.h>
#include <RF24.h>
#include <RF24_config.h>
#include <SPI.h>

const int pinCE = 9;
const int pinCSN = 10;
RF24 radio(pinCE, pinCSN);

// Single radio pipe address for the 2 nodes to communicate.
const uint64_t pipe = 0xE8E8F0F0E1LL;

char data[16];

void setup(void)
{
  Serial.begin(9600);
  radio.begin();
  radio.openReadingPipe(1,pipe);
  radio.startListening();
}
 
void loop(void)
{
  if (radio.available())
  {
    radio.read(data, sizeof data); 
    Serial.println(data);
  }
}

Enviar variables integer o float

El siguiente ejemplo muestra el envío de variables integer o float desde un Arduino emisor a otro receptor, que muestra los datos por puerto serie. El Arduino emisor envía dos datos cualquiera, en el ejemplo millis()/1000 como integer y 3.14 como float.

Por su parte, el receptor recibe los datos, y en función del identificador convierte los datos recibidos a integer o float, y muestra el resultado por el puerto serie.

Código emisor

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
 
const int pinCE = 9;
const int pinCSN = 10;
RF24 radio(pinCE, pinCSN);

// Single radio pipe address for the 2 nodes to communicate.
const uint64_t pipe = 0xE8E8F0F0E1LL;

float data[2];

void setup()
{
  radio.begin();
  radio.openWritingPipe(pipe);
}
 
void loop()
{ 
  data[0]= 3.14;
  data[1] = millis()/1000.0;
  
  radio.write(data, sizeof data);
  delay(1000);
}

Código receptor

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
 
const int pinCE = 9;
const int pinCSN = 10;
RF24 radio(pinCE, pinCSN);
 
// Single radio pipe address for the 2 nodes to communicate.
const uint64_t pipe = 0xE8E8F0F0E1LL;

float data[3];

void setup()
{
  radio.begin();
  Serial.begin(9600); 
  radio.openReadingPipe(1, pipe);
  radio.startListening();
}
 
void loop()
{
  if (radio.available())
  {    
    radio.read(data, sizeof data);
    Serial.print("Dato0= " );
    Serial.print(data[0]);
    Serial.print("Dato1= " );
    Serial.print(data[1]);
    Serial.println("");
  }
  delay(1000);
}