En esta guía voy a explicar como comunicar un Arduino y un Raspberry Pi con modulos nRF24L01+. Encontré en Internet varias guías para hacerlo, pero ninguna estaba completa o me funcionó completamente, entonces decidí registrar lo que hice por si lo necesito nuevamente. Esta parte tiene una introducción y explica como preparar el Arduino, mientras que en la parte 2 explicaré como preprar el Raspberry Pi y probar todo.

nRF24L01+

Como dije, voy a usar módulos basados en el chip nRF24L01+ de Nordic Semiconductors. La razón para elegirlos sobre otras alternativas es que siendo baratos no dejan de incluir ciertas características no encontradas en los módulos más baratos, como ser múltiples pipelines, buffers y auto retransmisión. En este caso uno de los módulos es uno común (el de la izquierda) y el otro tiene circuitos amplificadores (LNA, low noise amplifier, y PA, power amplifier) para mejorar el alcance (el de la derecha). Ambos son de Itead Studio.

nRF24L01+
módulo nRF24L01+ (izquierda) y módulo nRF24L01+ con PA y LNA (derecha)

SPI

Para interactuar con estos módulos tenemos que usar el bus SPI. SPI es una interfaz serie (Seria Peripheral Interface) que trabaja en un esquema maestro/esclavo. El bus SPI puede operar con un sólo dispositivo maestro y uno o más dispositivos esclavos. Utiliza tres cables comunes y uno extra por cada dispositivo esclavo. Los tres cables comunes (conectados a todos los dispositivos) son:

  • SCK: señal de reloj (salida desde el maestro)
  • MOSI: salida de maestro - entrada a esclavo
  • MISO: entrada a maestro - salida de esclavo

El cable extra es conocido como SS (slave select, selección de esclavo) o CS (chip select, selección de chip) y su función es habilitar el dispositivo esclavo con el que nos queremos comunicar (solo un esclavo puede ser habilitado a la vez). Si querés saber más sobre SPI y como funciona podés ir a Wikipedia. En este caso utilizaremos solo uno, pero en la imagen podes ver un esquema con múltiples esclavos.

Typical SPI bus: master and three independent slaves. [Wikipedia]
Bus SPI tipico: maestro y tres esclavos independientes. [Wikipedia]

Preparando el Arduino

Empezaremos preparando el Arduino porque es la parte más fácil. Estas instrucciones son para el Arduino ADK (también funcionan para el Arduino Mega 2560). Podés usarlas para cualquier Arduino, pero tené en cuenta que las conexiones de SPI generalmente varian. Si buscas tu modelo de Arduino en la página web vas a encontrar que pines tenes que usar para SPI. Las conexiones necesarias están resumidas en la tabla siguiente.

Pin nRF24L01+ Pin

Señal

Pin Arduino

Color del Cable (sólo referencia)

1

GND

GND

Negro

2

3V3

3V3

Rojo

3

CE

9

Amarillo

4

CSN (SPI)

10

Azul

5

SCK (SPI)

52 (SCK)

Marrón

6

MOSI (SPI)

51 (MOSI)

Verde

7

MISO (SPI)

50 (MISO)

Blanco

8

Interrupción

-

-

Deberías tener en cuenta algunas cosas:

  • El módulo trabaja con 3.3V, así que tenés que conectarlo a esa línea y NO a los 5v
  • El módulo usa un cable extra para "datos" además de los de SPI (CE: Chip Enable, habilitación de chip)
  • La librería no utiliza el pin SS del Arduino, si no que un pin digital regular como SS
  • Ambas conexiones (CE y SS) se definen al inicializar la librería y pueden ser modificadas
  • Las conexiones SCK, MOSI y MISO dependen del Arduino, por lo que estarán en pines diferentes si usas otro modelo
  • El octavo pin del módulo es para interrupciones y no se usa actualmente en la librería

En caso de que te sea más fácil verlo gráficamente, hice una imagen en Fritzing:

Arduino - nRF24L01+ Connections
Conexión Arduino - nRF24L01+ (No está en escala)

Si pensás usar un breadboard vas a tener que hacer un adaptador (si tenés un breadboard común, no hay forma de conectar el módulo directamente sin que queden conectados dos pines)

Etapa de programación

Entonces todo está listo y es momento de programar el Arduino. Hay varias librerías para estos módulos, yo utilicé la RF24 de maniacbug. Si explorás un poco la red de este repositorio vas a ver que hay un montón de forks, sin embargo no pude encontrar una diferencia relevante entre ellos (no es que haya buscado mucho). Como con cualquier librería de Arduino, simplemente cloná el repo de Github o bajá el zip e instalalo. Si, como yo, bajaste la versión zip de la IDE de Arduino, simplemente descomprimí la carpeta RF24-master (la de adentro del zip, no el zip en si) en la carpeta "libraries" de tu IDE y renombrala a RF24. En cualquier otro caso, o si estas instrucciones no te funcionan, acá hay instrucciones más detalladas.

Ya está todo listo, abrí tu IDE Arduino y andá a Archivo > Ejemplos > RF24 > pingpair y cargalo a tu Arduino. Si leíste un poco el sketch vas a haber notado que el pin 7 controla el rol del Arduino. Si se deja desconectado el Arduino entra al rol "pong back", en el que espera un mensaje y lo envía de vuelta al recibirlo. Si el pin se conecta a la tierra (ground), el Arduino entra al rol "ping out", en el cual envía paquetes constantemente y espera su confirmación. Tené en cuenta que el Arduino no cambia su rol mientras está encendido, vas a tener que resetearlo si cambias el estado del pin.Ahora comprobaremos que la comunicación con el módulo funciona correctamente (la del bus SPI, no la comunicación inalámbrica con otro módulo). Para eso abrí el Monitor Serie de la IDE (o cualquier terminal serie que te guste) y configurala en 57600 baudios. Si el Arduino está en el rol pong deberías ver algo así:

RF24/examples/pingpair/
ROLE: Pong back
STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1 = 0xf0f0f0f0d2 0xf0f0f0f0e1
RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6
TX_ADDR = 0xf0f0f0f0d2
RX_PW_P0-6 = 0x08 0x08 0x00 0x00 0x00 0x00
EN_AA = 0x3f
EN_RXADDR = 0x03
RF_CH = 0x4c
RF_SETUP = 0x07
CONFIG = 0x0f
DYNPD/FEATURE = 0x00 0x00
Data Rate = 1MBPS
Model = nRF24L01+
CRC Length = 16 bits
PA Power = PA_HIGH

Si en cambio recibis todos ceros podés tener algo mal conectado o tu módulo no funciona correctamente (en general será la primer opción). Si esto pasa controlá que hayas conectado todo bien y probá de nuevo.

RF24/examples/pingpair/
ROLE: Pong back
STATUS = 0x00 RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=0 TX_FULL=0
RX_ADDR_P0-1 = 0x0000000000 0x0000000000
RX_ADDR_P2-5 = 0x00 0x00 0x00 0x00
TX_ADDR = 0x0000000000
RX_PW_P0-6 = 0x00 0x00 0x00 0x00 0x00 0x00
EN_AA = 0x00
EN_RXADDR = 0x00
RF_CH = 0x00
RF_SETUP = 0x00
CONFIG = 0x00
DYNPD/FEATURE = 0x00 0x00
Data Rate = 1MBPS
Model = nRF24L01
CRC Length = Disabled
PA Power = PA_MIN

Una vez que el módulo esta respondiendo bien estamos listos para probar la comunicación inalámbrica. Bueno, hay un problema recién preparamos un dispositivo, el otro será el Raspberry Pi que configuraremos en la siguiente parte, así que habrá que esperar hasta entonces para probar la comunicación entre módulos. Si tenés otro Arduino y no podés esperar, podés repetir el proceso, poner un Arduino en cada rol y probarlos.

De todas maneras, estate listo para la siguiente parte ya que la configuración del Raspberry Pi es un poco más compleja. Para concluir, algunos links útiles (algunos ya estan en el post, otros son nuevos):