La función de este artículo es ofrecer una explicación sobre cómo establecer una comunicación inalámbrica entre dos placas Arduino usando el módulo transceptor NRF24L01.
La primera comunicación inalámbrica que explicaré será básica: enviar un simple mensaje de texto, tipo «Hola Mundo», de un Arduino a otro.
A continuación podremos extender este ejemplo de comunicación al envío de comandos de texto —usando el mismo circuito y estructura de programa— para controlar un sistema cualquiera ubicado en el extremo receptor.
Más adelante ofreceré un artículo con un ejemplo de comunicación bidireccional entre placas Arduino. Un Arduino tiene conectado un potenciómetro con el que se controla un servo en el segundo Arduino. Y en el otro sentido, unos interruptores en el segundo Arduino servirán para controlar LEDs en el primero.
Módulo transceptor NRF24L01
En la imagen se observa el módulo transceptor NRF24L01. Utiliza la banda de 2,4 GHz y puede operar con velocidades de transmisión de 250 kbps hasta 2 Mbps. Si se usa en espacios abiertos y, con menor velocidad de transmisión, su alcance puede llegar hasta los 100 metros. Para mayores distancias, hasta 1000 metros, existen módulos provistos con una antena externa en lugar de una antena trazada sobre la misma placa, como se observa en la imagen.
El módulo puede usar 125 canales diferentes, lo que da la posibilidad de tener una red de 125 módems que funcionen con independencia uno de otro en un solo lugar. Cada canal puede tener hasta 6 direcciones, es decir, cada unidad puede comunicarse con hasta otras 6 unidades al mismo tiempo.
El consumo de este módulo es de alrededor de 12 mA durante la transmisión, un valor menor al de un LED encendido. El voltaje de operación del módulo es de 1,9 a 3,6V, pero lo bueno es que los demás pines toleran la lógica de 5V, por lo que podemos conectarlo sin problemas a un Arduino sin necesidad de un convertidor de niveles lógicos.
Tres de estos pines son para la comunicación SPI: MOSI, MISO y SCK, que deben conectarse a los pines de la interfaz SPI del Arduino. Se debe tener en cuenta que diferentes placas Arduino pueden tener los pines del interfaz SPI en diferentes posiciones. Los pines CSN y CE se pueden conectar a cualquier pin digital de la placa Arduino, y su función es configurar el módulo en modo de espera o activo, así como para alternar entre modo de transmisión o de comando. El último pin, IRQ, es un pin de interrupción que no es necesario utilizar.
Una vez conectados los módulos NRF24L01 a las placas Arduino, llegará el momento de escribir los programas para el transmisor, y para el receptor.
Conexionado para utilizar Arduinos Uno R3 en ambos lados de la comunicación:
Código para los Arduino
Primero debemos descargar e instalar la librería RF24.
Aquí están los dos códigos para la comunicación inalámbrica y abajo, en los archivos, hay amplias explicaciones. He puesto la mayor parte de las explicaciones dentro del programa, como comentarios.
Código del Transmisor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
/* Comunicacion inalambrica con NRF24L01 Arduino Ejemplo 1 – Programa para el Transmisor Libreria: TMRh20/RF24 https://github.com/tmrh20/RF24/ */ /* Debemos incluir la libreria SPI basica y la libreria RF24 que ya hemos instalado */ #include <SPI.h> #include <RF24.h> /* Crear un objeto RF24 al que llamaremos “radio”. Los dos argumentos que se utilizan en la funcion son los numeros de pin que vamos a usar para CS y CE. */ RF24 radio(7, 8); // CE, CSN /* Creamos una matriz de bytes que represente la direccion con la que se reconoceran entre si los dos modulos. Podemos cambiar el valor de esta direccion a cualquier conjunto de 5 letras y/o numeros. Esta direccion permite elegir con que receptor vamos a comunicarnos. En nuestro caso, usaremos la misma direccion tanto en el receptor como en el transmisor. */ const byte identificacion[6] = "00001"; void setup() { /* En la seccion de configuracion debemos inicializar el objeto “radio” */ radio.begin(); /* Mediante la funcion radio.openWritingPipe(), establecer la direccion del receptor al que enviaremos los datos. En este ejemplo, la cadena de 5 caracteres que hemos configurado. */ radio.openWritingPipe(identificacion); /* Configuramos el nivel del amplificador de potencia, usando la funcion radio.setPALevel(). Mientras estemos a este nivel de prueba, es decir prototipos sobre la mesa de trabajo, lo establecemos al minimo, ya que los modulos estaran cerca el uno del otro. Si se utiliza un nivel mas alto, se recomienda utilizar capacitores de filtro entre las entradas GND y 3,3 V de los mdulos para que su voltaje se mantenga más estable durante el funcionamiento. */ radio.setPALevel(RF24_PA_MIN); /* La función radio.stopListening() cumple la de establecer al módulo como transmisor. */ radio.stopListening(); } void loop() { /* Creamos una matriz de caracteres a la que asignamos el mensaje "Hola mundo" o cualquiera que usted desee enviar. */ const char texto[] = "Hola Mundo"; /* Usando la funcion radio.write() se envía el mensaje al receptor. El primer argumento es la variable que deseamos enviar. */ radio.write(&texto, sizeof(texto)); /* El simbolo “&” delante del nombre de la variable establece un indicador que apunta a la variable que contiene los datos que queremos enviar y, con el segundo argumento, establecemos la cantidad de bytes que se van a usar de esa variable. En este caso, la funcion sizeof() nos devuelve la cantidad total de los bytes de la cadena "texto". */ delay(1000); // Un segundo (1000 milisegundos) de espera entre envío y envío } |
Código del receptor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
/* Comunicacion inalambrica con NRF24L01 Arduino Ejemplo 1 – Programa para el Receptor Libreria: TMRh20/RF24 https://github.com/tmrh20/RF24/ */ /* Debemos incluir la libreria SPI basica y la libreria RF24 que ya hemos instalado */ #include <SPI.h> #include <RF24.h> /* Crear un objeto RF24 al que llamaremos “radio”. Los dos argumentos que se utilizan en la funcion son los numeros de pin que vamos a usar para CS y CE. */ RF24 radio(7, 8); // CE, CSN /* Creamos una matriz de bytes que represente la direccion con la que se reconoceran entre si los dos modulos. Podemos cambiar el valor de esta direccion a cualquier conjunto de 5 letras y/o numeros. Esta direccion permite elegir con que receptor vamos a comunicarnos. En nuestro caso, usaremos la misma direccion tanto en el receptor como en el transmisor. */ const byte identificacion[6] = "00001"; void setup() { Serial.begin(9600); // Iniciamos la comunicacion serie hacia el Monitor Serie en la PC /* En la sección de configuracion debemos inicializar el objeto “radio” */ radio.begin(); /* En el receptor establecemos la misma direccion que en el transmisor usando la funcion radio.setReadingPipe() y asi queda habilitada la comunicacion entre los dos modulos. */ radio.openReadingPipe(0, identificacion); /* Configuramos el nivel del amplificador de potencia, usando la funcion radio.setPALevel(). Mientras estemos a este nivel de prueba, es decir prototipos sobre la mesa de trabajo, lo establecemos al minimo, ya que los modulos estaran cerca el uno del otro. Si se utiliza un nivel mas alto, se recomienda utilizar capacitores de filtro entre las entradas GND y 3,3 V de los mdulos para que su voltaje se mantenga mas estable durante el funcionamiento. */ radio.setPALevel(RF24_PA_MIN); /* La funcion radio.startListening() establece al modulo como receptor. */ radio.startListening(); } void loop() { if (radio.available()) { char texto[32] = ""; /* Creamos una matriz de caracteres donde recibir el mensaje */ radio.read(&texto, sizeof(texto)); // Esperamos que llegue algo por RF desde el módulo /* El símbolo “&” delante del nombre de la variable establece un indicador que señala a la variable que contiene los datos que queremos enviar y, con el segundo argumento, establecemos la cantidad de bytes que se van a usar de esa variable. En este caso, la funcion sizeof() nos devolvera la cantidad total de los bytes de la cadena "texto". */ Serial.println(texto); /* Enviamos lo que hemos recibido al Monitor Serie en la PC */ } } |
Una vez cargados ambos programas, podemos abrir el monitor serie en el Arduino receptor y observaremos la aparición del mensaje «Hola Mundo» cada 1 segundo.
CONTROL INALÁMBRICO A DISTANCIA
Esta prueba consiste en tener un Arduino (con el programa TRANSMISOR listado más abajo) conectado a la PC a través de USB / Conexión Serie, con el Monitor Serie del IDE de Arduino abierto (Herramientas > Monitor Serie) y asignado en el COM que corresponde, y transmitiendo en forma inalámbrica los caracteres que son tipeados dentro de este Monitor.
Nota: Un defecto que tiene el Monitor Serie del IDE del Arduino es que para que se transmita un caracter, o una serie de caracteres, hay que tipearlo y pulsar ENTER (ENTRAR). Eso es incómodo para controlar un equipo remoto pulsando teclas. Por eso recomiendo utilizar un programa simple y gratuito de terminal. Quizás usted ya tenga uno. En mi caso utilizo el programa Parallax Serial Terminal (PST.EXE), que se puede bajar de aquí (Página de manual de uso).
El otro Arduino lleva grabado el programa RECEPTOR, y en ese Arduino se ha agregado un pequeño servo al diagrama estándar, como muestra la figura más abajo.
El funcionamiento será básico: pulsando los números de 1 a 0 ubicados en la hilera superior del teclado, o si lo desea y lo tiene, en el teclado numérico a la derecha. Para cada uno de estos números el servo se ubicará en 10 posiciones diferentes, separadas 20º. Desde 0 a 180º, que es el rango que tiene todo servo, y más aún estos pequeños. Los servos mayores se pueden mover 270º. La selección de acciones que corresponden a cada comando se realiza por medio de comparaciones IF en el primer programa ejemplo de RECEPTOR, y por medio de una estructura SWICH-CASE en el segundo programa ejemplo. El primero es así porque puede resultar más comprensible para los recién iniciados, y el segundo ejemplo es más simple, elegante y profesional. Puse enlaces en los nombres de las estructuras de programa que apuntan a la sección de REFERENCIA del sitio oficial de Arduino.
La elección de cuál programa RECEPTOR desea usar queda a su gusto. En realidad, es conveniente probar ambos. En lo funcional se comportarán igual.
DIAGRAMA
TRANSMISOR
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
/* Comunicacion inalambrica con NRF24L01 Arduino Ejemplo 1 – Manejo de servo / Programa del Transmisor Libreria: TMRh20/RF24 https://github.com/tmrh20/RF24/ */ /* Debemos incluir la libreria SPI basica y la libreria RF24 que ya hemos instalado */ #include <SPI.h> #include <RF24.h> /* Crear un objeto RF24 al que llamaremos “radio”. Los dos argumentos que se utilizan en la funcion son los numeros de pin que vamos a usar para CS y CE. */ RF24 radio(7, 8); // CE, CSN /* Creamos una matriz de bytes que represente la direccion con la que se reconoceran entre si los dos modulos. Podemos cambiar el valor de esta direccion a cualquier conjunto de 5 letras y/o numeros. Esta direccion permite elegir con que receptor vamos a comunicarnos. En nuestro caso, usaremos la misma direccion tanto en el receptor como en el transmisor. */ const byte identificacion[6] = "00001"; void setup() { Serial.begin(9600); // Iniciamos la comunicacion serie hacia el Monitor Serie en la PC /* En la seccion de configuracion debemos inicializar el objeto “radio” */ radio.begin(); /* Mediante la funcion radio.openWritingPipe(), establecer la direccion del receptor al que enviaremos los datos. En este ejemplo, la cadena de 5 caracteres que hemos configurado. */ radio.openWritingPipe(identificacion); /* Configuramos el nivel del amplificador de potencia, usando la funcion radio.setPALevel(). Mientras estemos a este nivel de prueba, es decir prototipos sobre la mesa de trabajo, lo establecemos al minimo, ya que los modulos estaran cerca el uno del otro. Si se utiliza un nivel mas alto, se recomienda utilizar capacitores de filtro entre las entradas GND y 3,3 V de los mdulos para que su voltaje se mantenga más estable durante el funcionamiento. */ radio.setPALevel(RF24_PA_MIN); /* La función radio.stopListening() cumple la de establecer al módulo como transmisor. */ radio.stopListening(); } void loop() { /* Creamos un constante de un caracter que se recibe desde el teclado de la PC. */ char caracter; /* Esperamos a que llegue un caracter por la linea serie que usaremos para controlar */ if (Serial.available() > 0) { /* leer el caracter que llega desde PC: */ caracter = Serial.read(); /* Usando la funcion radio.write() se envía el mensaje al receptor. El primer argumento es la variable que deseamos enviar y el segundo la longitud de la variable caracter. */ if (sizeof(caracter) == 1) { radio.write(&caracter, 1); } } /* El simbolo “&” delante del nombre de la variable establece un indicador que apunta a la variable que contiene los datos que queremos enviar y, con el segundo argumento, establecemos la cantidad de bytes que se van a usar de esa variable. En este caso, se usa 1 ya que char es un caracter unico. */ } |
RECEPTOR – Basado en elección de comandos por IF
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
/* Comunicacion inalambrica con NRF24L01 Arduino Ejemplo 1 – Control un servo a distancia - Programa para el Receptor Libreria: TMRh20/RF24 https://github.com/tmrh20/RF24/ */ /* Debemos incluir la libreria SPI basica y la libreria RF24 que ya hemos instalado */ #include <SPI.h> #include <RF24.h> #include <Servo.h> /* Crear un objeto RF24 al que llamaremos “radio”. Los dos argumentos que se utilizan en la funcion son los numeros de pin que vamos a usar para CS y CE. */ RF24 radio(7, 8); // CE, CSN /* Creamos una matriz de bytes que represente la direccion con la que se reconoceran entre si los dos modulos. Podemos cambiar el valor de esta direccion a cualquier conjunto de 5 letras y/o numeros. Esta direccion permite elegir con que receptor vamos a comunicarnos. En nuestro caso, usaremos la misma direccion tanto en el receptor como en el transmisor. */ const byte identificacion[6] = "00001"; Servo miServo; void setup() { miServo.attach(5); Serial.begin(9600); // Iniciamos la comunicacion serie hacia el Monitor Serie en la PC /* En la sección de configuracion debemos inicializar el objeto “radio” */ radio.begin(); /* En el receptor establecemos la misma direccion que en el transmisor usando la funcion radio.setReadingPipe() y asi queda habilitada la comunicacion entre los dos modulos. */ radio.openReadingPipe(0, identificacion); /* Configuramos el nivel del amplificador de potencia, usando la funcion radio.setPALevel(). Mientras estemos a este nivel de prueba, es decir prototipos sobre la mesa de trabajo, lo establecemos al minimo, ya que los modulos estaran cerca el uno del otro. Si se utiliza un nivel mas alto, se recomienda utilizar capacitores de filtro entre las entradas GND y 3,3 V de los modulos para que su voltaje se mantenga mas estable durante el funcionamiento. */ radio.setPALevel(RF24_PA_MIN); /* La funcion radio.startListening() establece al modulo como receptor. */ radio.startListening(); } void loop() { if (radio.available()) { char texto; /* Creamos una matriz de caracteres donde recibir el mensaje */ radio.read(&texto, 1); // Esperamos que llegue algo por RF desde el módulo /* El símbolo “&” delante del nombre de la variable establece un indicador que señala a la variable que contiene los datos que queremos enviar y, con el segundo argumento, establecemos la cantidad de bytes que se van a usar de esa variable. En este caso, la funcion sizeof() nos devolvera 1 que es un char. */ if (sizeof(texto)>0) { if (texto == '0') { miServo.write(0); } if (texto == '1') { miServo.write(20); } if (texto == '2') { miServo.write(40); } if (texto == '3') { miServo.write(60); } if (texto == '4') { miServo.write(80); } if (texto == '5') { miServo.write(100); } if (texto == '6') { miServo.write(120); } if (texto == '7') { miServo.write(140); } if (texto == '8') { miServo.write(160); } if (texto == '9') { miServo.write(180); } } /* Enviamos una posicion al servo en base a lo que hemos recibido desde el Monitor Serie del transmisor, tecleado en la PC */ } } |
RECEPTOR – Basado en elección de comandos por SWITCH-CASE
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
/* Comunicacion inalambrica con NRF24L01 Arduino Ejemplo 2 – Manejo servo / Programa del Receptor Libreria: TMRh20/RF24 https://github.com/tmrh20/RF24/ */ /* Debemos incluir la libreria SPI basica, la libreria RF24 que ya hemos instalado y la libreria Servo para manejar un servo*/ #include <SPI.h> #include <RF24.h> #include <Servo.h> /* Crear un objeto RF24 al que llamaremos “radio”. Los dos argumentos que se utilizan en la funcion son los numeros de pin que vamos a usar para CS y CE. */ RF24 radio(7, 8); // CE, CSN /* Creamos una matriz de bytes que represente la direccion con la que se reconoceran entre si los dos modulos. Podemos cambiar el valor de esta direccion a cualquier conjunto de 5 letras y/o numeros. Esta direccion permite elegir con que receptor vamos a comunicarnos. En nuestro caso, usaremos la misma direccion tanto en el receptor como en el transmisor. */ const byte identificacion[6] = "00001"; Servo miServo; /* Definimos e nombre miServo para este servo */ void setup() { miServo.attach(5); // Define que el pin 5 controla el servo Serial.begin(9600); // Iniciamos la comunicacion serie hacia el Monitor Serie en la PC /* En la sección de configuracion debemos inicializar el objeto “radio” */ radio.begin(); /* En el receptor establecemos la misma direccion que en el transmisor usando la funcion radio.setReadingPipe() y asi queda habilitada la comunicacion entre los dos modulos. */ radio.openReadingPipe(0, identificacion); /* Configuramos el nivel del amplificador de potencia, usando la funcion radio.setPALevel(). Mientras estemos a este nivel de prueba, es decir prototipos sobre la mesa de trabajo, lo establecemos al minimo, ya que los modulos estaran cerca el uno del otro. Si se utiliza un nivel mas alto, se recomienda utilizar capacitores de filtro entre las entradas GND y 3,3 V de los modulos para que su voltaje se mantenga mas estable durante el funcionamiento. */ radio.setPALevel(RF24_PA_MIN); /* La funcion radio.startListening() establece al modulo como receptor. */ radio.startListening(); } void loop() { if (radio.available()) { char texto; /* Creamos una matriz de caracteres donde recibir el mensaje */ radio.read(&texto, 1); // Esperamos que llegue algo por RF desde el módulo /* El símbolo “&” delante del nombre de la variable establece un indicador que señala a la variable que contiene los datos que queremos enviar y, con el segundo argumento, establecemos la cantidad de bytes que se van a usar de esa variable. En este caso se usa 1 porque un char mide 1. */ /* Podemos enviar comandos 0 a 9 desde la PC. Cada valor pondra el servo en una posicion, una cada 20 grados, de 0 a 180. Usamos la estructura switch / case para la eleccion. */ if (sizeof(texto)>0) { switch(texto) { case '1': miServo.write(0); break; case '2': miServo.write(20); break; case '3': miServo.write(40); break; case '4': miServo.write(60); break; case '5': miServo.write(80); break; case '6': miServo.write(100); break; case '7': miServo.write(120); break; case '8': miServo.write(140); break; case '9': miServo.write(160); break; case '0': miServo.write(180); break; } } /* Enviamos una posicion al servo en base a lo que hemos recibido desde el Monitor Serie del transmisor, tecleado en la PC */ } } |
AQUÍ LOS ARDUINOS ARMADOS
Pingback: Control de relés por enlace de 2,4 GHz – módulos NRF24L01 (Domótica 4) | Robots Didácticos