En esta entrada del blog, aprenderás cómo construir un mando IR universal y programable usando Arduino. Un mando a distancia por infrarrojos (IR) es un dispositivo común utilizado para controlar varios aparatos electrónicos como televisores, aires acondicionados y reproductores de DVD. Con la ayuda de Arduino, podemos crear nuestro propio mando IR que se puede programar para controlar múltiples dispositivos y unificar varios mandos en uno solo.
Al final de este tutorial, sabrás cómo usar receptores y transmisores infrarrojos, y cómo almacenar datos en la EEPROM no volátil. También tendrás el prototipo de un mando IR programable que podrás modificar o ampliar a tu gusto. Te permitirá tomar tus mandos IR existentes para TV, ventilador, etc., y copiar la función de sus teclas en el mando IR que estamos construyendo aquí.
¡Así que empecemos y sumerjámonos en el emocionante mundo de Arduino y el control remoto IR!
Componentes necesarios
A continuación encontrarás los componentes necesarios para construir el mando IR programable. También necesitarás un mando IR, si aún no tienes uno.

Arduino Uno

Juego de cables Dupont

Protoboard

Cable USB para Arduino UNO

Kit de resistencias y LEDs

Receptor y transmisor IR
Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.
Conexión de las piezas
En esta sección te mostraré cómo conectar los componentes al Arduino. La imagen a continuación muestra el cableado completo. Comenzaremos conectando la fuente de alimentación a la protoboard.

Fuente de alimentación
Conecta un cable azul desde el pin GND del Arduino a la línea negativa de alimentación de la protoboard (marcada con una línea azul). Luego conecta el pin 5V del Arduino a la línea positiva de alimentación (marcada con una línea roja) con un cable rojo.


Además, conecta ambas líneas positivas de la protoboard con otro cable rojo. Esto asegura que tengamos alimentación positiva en ambas líneas.

Módulo receptor IR
A continuación, te mostraré cómo conectar el receptor IR. Este recibe las señales infrarrojas emitidas por un mando IR y las envía al Arduino, donde se decodifican.
Conecta un cable azul y uno rojo desde el receptor a las líneas de alimentación correspondientes de la protoboard. El lado negativo suele estar marcado con un signo (-) en el receptor, mientras que el pin central suele ser el positivo. Después conecta el pin de señal (S) del receptor al pin 2 del Arduino; abajo se muestra con un cable morado.

Después de conectar el receptor, conectemos el módulo transmisor.
Módulo transmisor IR
El transmisor IR es el módulo con el LED IR blanco/transparente. Este módulo emite las señales infrarrojas usadas para controlar dispositivos.
De nuevo, primero conectamos la alimentación (cables rojo y azul). Luego conectamos el pin de señal (S) del transmisor al pin 3 del Arduino usando un cable blanco.

Como nuestro mando IR será programable, necesitamos un LED de estado. Este nos indicará si estamos en modo programación o en modo envío. A continuación se describe cómo conectar el LED de estado.
LED de estado
Coloca un LED rojo en la protoboard y conecta el cátodo (el pin más corto) con un cable azul a la línea negativa de alimentación de la protoboard. Luego conecta una resistencia de 330 Ohmios al ánodo del LED (el pin más largo). Finalmente, conecta la resistencia con un cable naranja al pin 11 del Arduino.

Botones
Por último, necesitamos tres botones. Un botón para cambiar entre el modo programación y el modo normal del mando IR. Y dos botones más para dos funciones diferentes del mando. Por ejemplo, para subir y bajar el volumen.
Como puedes ver abajo, los tres botones están conectados de la misma manera. Una resistencia de 10K Ohm actúa como pull-up resistor y se conecta a la línea positiva de alimentación. El pin del otro lado del botón se conecta a un pin de entrada del Arduino (más detalles abajo). El otro pin se conecta con un cable azul a la línea negativa de alimentación de la protoboard.

En el estado normal, abierto, del pulsador, la entrada está conectada a 5V a través de la resistencia y leeremos una señal ALTA. Sin embargo, si presionas un botón, la línea de entrada se conecta a tierra y leeremos una señal BAJA en la entrada.
El botón superior/primero será nuestro botón para cambiar de modo. Conéctalo con un cable amarillo al pin 4 del Arduino. El botón de abajo será para la primera función. Conéctalo al pin 5 (cable cian). Y el último botón es para la segunda función y lo conectamos con un cable verde al pin 6.

Eso es todo. Todo está conectado, esperamos que correctamente. En la siguiente sección veremos el software.
Escribiendo el software
Primero te mostraré el código completo y luego repasaremos las partes individuales para entender cómo funciona. Echa un vistazo rápido para obtener una visión general.
#include "EEPROM.h"
#include "IRremote.hpp"
#include "TinyIRSender.hpp"
const uint8_t irReceivePin = 2;
const uint8_t irSendPin = 3;
const uint8_t modePin = 4;
const uint8_t func1Pin = 5;
const uint8_t func2Pin = 6;
const uint8_t ledPin = 11;
const uint8_t sRepeats = 2;
uint8_t modeReceive = HIGH;
struct Code {
uint16_t adr;
uint16_t cmd;
} code;
bool isOn(int btn) {
return btn == LOW;
}
bool pressed(int pin) {
return isOn(digitalRead(pin));
}
int memadr(int btnId) {
return (btnId - 1) * sizeof(Code);
}
void store_code(int btnId, IRData &irData) {
digitalWrite(ledPin, LOW);
code = { irData.address, irData.command };
EEPROM.put(memadr(btnId), code);
delay(200);
digitalWrite(ledPin, HIGH);
}
void send_code(int btnId) {
digitalWrite(ledPin, HIGH);
EEPROM.get(memadr(btnId), code);
sendNECMinimal(irSendPin, code.adr, code.cmd, sRepeats);
delay(200);
digitalWrite(ledPin, LOW);
}
void toggle_mode() {
modeReceive = modeReceive == LOW ? HIGH : LOW;
digitalWrite(ledPin, isOn(modeReceive) ? HIGH : LOW);
isOn(modeReceive) ? IrReceiver.start() : IrReceiver.stop();
delay(200);
}
void send() {
if (pressed(func1Pin)) {
send_code(1);
} else if (pressed(func2Pin)) {
send_code(2);
}
}
void receive() {
if (IrReceiver.decode()) {
IRData &irData = IrReceiver.decodedIRData;
IrReceiver.printIRResultShort(&Serial);
if (pressed(func1Pin)) {
store_code(1, irData);
} else if (pressed(func2Pin)) {
store_code(2, irData);
}
IrReceiver.resume();
}
}
void setup() {
Serial.begin(9600);
IrReceiver.begin(irReceivePin, ENABLE_LED_FEEDBACK);
pinMode(ledPin, OUTPUT);
pinMode(modePin, INPUT);
pinMode(func1Pin, INPUT);
pinMode(func2Pin, INPUT);
digitalWrite(ledPin, LOW);
}
void loop() {
if (pressed(modePin)) toggle_mode();
isOn(modeReceive) ? receive() : send();
delay(100);
}
Librerías incluidas
Para este proyecto necesitarás install las siguientes librerías. EEPROM se usa para almacenar los códigos IR programados. La IRremote librería se usa para decodificar las señales IR que recibimos de un mando IR. Y TinyIRSender es parte de la librería IRremote y nos permite enviar señales IR, aunque limitado al protocolo NEC protocol .
#include "EEPROM.h" #include "IRremote.hpp" #include "TinyIRSender.hpp"
Constantes
En el siguiente bloque de código definimos qué pines del Arduino se usan para cada componente. irReceivePin y irSendPin son los pines conectados al receptor y transmisor IR. modePin, func1Pin y func2Pin están conectados a los botones. El LED de estado se controla a través del ledPin . Y sRepeats define con qué frecuencia se repite un IR command al enviar.
const uint8_t irReceivePin = 2; const uint8_t irSendPin = 3; const uint8_t modePin = 4; const uint8_t func1Pin = 5; const uint8_t func2Pin = 6; const uint8_t ledPin = 11; const uint8_t sRepeats = 2;
Estructuras de datos
Además de las constantes, necesitamos una variable para almacenar el modo actual (programación o normal) de nuestro mando IR. modeReceive es ALTO cuando estamos en modo programación, y BAJO en caso contrario.
uint8_t modeReceive = HIGH;
struct Code {
uint16_t adr;
uint16_t cmd;
} code;
La Code estructura almacena la dirección ( adr ) y el comando ( cmd ) de los códigos IR que vamos a recibir, almacenar y enviar. Por ejemplo, mi mando IR envía la dirección 0x20 y el comando 0x17 cuando se presiona la tecla VOL+.
Para más detalles, consulta la documentación de la IRremote lib o echa un vistazo a nuestro tutorial sobre How to use an IR receiver and remote with Arduino .
Funciones auxiliares
Para mantener el código simple y legible, implementamos algunas funciones auxiliares. La función isOn() devuelve True si un botón está LOW , lo que significa que está presionado. Con la función pressed() leemos el estado de un pin de entrada y luego usamos isOn() para determinar si el botón conectado está presionado.
bool isOn(int btn) {
return btn == LOW;
}
bool pressed(int pin) {
return isOn(digitalRead(pin));
}
Función de dirección de memoria
Para almacenar los códigos IR recibidos en memoria necesitamos una función que nos diga en qué dirección almacenar los datos. La función memadr() se usa para calcular en qué dirección de memoria en la EEPROM guardamos y leemos los códigos de comando IR.
int memadr(int btnId) {
return (btnId - 1) * sizeof(Code);
}
Esta función toma un btnId , que es 1 o 2 (para función 1 o 2) y calcula la dirección de memoria. Mira la siguiente imagen para entender mejor la relación entre btnId , el tamaño de una estructura Code y la dirección de memoria.

Funciones de código IR
Para el almacenamiento y envío de códigos IR usamos dos funciones. La siguiente función store_code() toma un id de botón ( btnId ) y un bloque de datos ( irData ) de datos IR recibidos.
En el primer paso, apagamos el LED de estado para indicar que estamos almacenando datos.
void store_code(int btnId, IRData &irData) {
digitalWrite(ledPin, LOW);
code = { irData.address, irData.command };
EEPROM.put(memadr(btnId), code);
delay(200);
digitalWrite(ledPin, HIGH);
}
Luego extraemos la dirección y el comando del bloque de datos y los almacenamos en una estructura Code . Escribimos esta estructura en la EEPROM con put() , usando la función memadr() para calcular la dirección de memoria.
Necesitamos almacenar los datos en EEPROM porque de lo contrario, cada vez que se apaga la alimentación, el Arduino pierde todos los datos almacenados. Con los datos en la EEPROM, los comandos/teclas programados permanecen guardados incluso cuando el Arduino está apagado.
Después de almacenar los datos esperamos 200 ms. Esto evita almacenamientos repetidos innecesarios cuando la tecla de programación permanece presionada. Finalmente, encendemos de nuevo el LED de estado para indicar que la programación ha finalizado.
El envío de códigos funciona esencialmente al revés. Mira la función send_code() a continuación. Primero encendemos el LED de estado para indicar que estamos enviando. Luego get el código a enviar desde la EEPROM para el botón presionado ( btnId ). La función sendNECMinimal() envía la dirección y el comando con el número dado de repeticiones ( sRepeats ).
void send_code(int btnId) {
digitalWrite(ledPin, HIGH);
EEPROM.get(memadr(btnId), code);
sendNECMinimal(irSendPin, code.adr, code.cmd, sRepeats);
delay(200);
digitalWrite(ledPin, LOW);
}
Después esperamos otros 200 ms y apagamos el LED de estado para indicar que el envío ha terminado.
Funciones principales
Ahora tenemos todas las funciones básicas para construir las funciones principales. Empezamos con una función toggle_mode() que cambia nuestro mando entre modo programación/recepción y modo envío. La primera línea alterna el modo. En la segunda línea, encendemos el LED de estado si estamos en modo programación. Si estamos en modo normal, el LED estará apagado.
void toggle_mode() {
modeReceive = modeReceive == LOW ? HIGH : LOW;
digitalWrite(ledPin, isOn(modeReceive) ? HIGH : LOW);
isOn(modeReceive) ? IrReceiver.start() : IrReceiver.stop();
delay(200);
}
En la tercera línea, activamos o desactivamos el IrReceiver según el modo. Si estamos en modo recepción, el IrReceiver se inicia, de lo contrario se detiene. Finalmente, tenemos un retardo usual de 200 ms para manejar pulsaciones largas.
La función send() a continuación usa send_code() para enviar los códigos IR almacenados para los botones 1 y 2. En otras palabras, dependiendo de qué botón se presione, enviará el código correspondiente.
void send() {
if (pressed(func1Pin)) {
send_code(1);
} else if (pressed(func2Pin)) {
send_code(2);
}
}
Finalmente, la última de las funciones principales es receive() . Allí recibimos los datos transmitidos desde un mando IR y los almacenamos para el botón 1 o 2, según cuál esté presionado. Para más detalles sobre cómo recibir datos IR, consulta nuestro tutorial: How to use an IR receiver and remote with Arduino .
void receive() {
if (IrReceiver.decode()) {
IRData &irData = IrReceiver.decodedIRData;
IrReceiver.printIRResultShort(&Serial);
if (pressed(func1Pin)) {
store_code(1, irData);
} else if (pressed(func2Pin)) {
store_code(2, irData);
}
IrReceiver.resume();
}
}
Función setup
¡Casi terminamos! Solo quedan dos funciones muy simples por implementar. En la función setup() establecemos la comunicación serial, inicializamos la IrReceiver y configuramos los modos de entrada/salida para los pines. También aseguramos que el LED de estado esté apagado, lo que indica que estamos en modo envío al inicio.
void setup() {
Serial.begin(9600);
IrReceiver.begin(irReceivePin, ENABLE_LED_FEEDBACK);
pinMode(ledPin, OUTPUT);
pinMode(modePin, INPUT);
pinMode(func1Pin, INPUT);
pinMode(func2Pin, INPUT);
digitalWrite(ledPin, LOW);
}
Función loop
Después de todo el trabajo duro anterior, el bucle principal es muy simple. Vigilamos el botón de modo conectado a modePin y si está pressed alternamos el modo. Luego comprobamos si estamos en modo recepción mediante isOn(modeReceive) . Si es así, recibimos y potencialmente almacenamos datos IR. De lo contrario, enviamos datos.
void loop() {
if (pressed(modePin)) toggle_mode();
isOn(modeReceive) ? receive() : send();
delay(100);
}
¡Y eso es todo! En la siguiente sección, explicaré rápidamente cómo usar el mando que acabamos de construir.
Cómo usar el mando
En esta sección te explicaré cómo usar el mando. Tenemos tres botones. El botón de modo se usa para cambiar del modo programación o recepción al modo envío. Al inicio, el mando está en modo envío y el LED de estado está apagado. Si presionas brevemente el botón de modo, el mando cambia a modo programación y el LED de estado se encenderá.

Programación
Para programar una de las dos teclas de función debes apuntar tu otro mando IR hacia el diodo receptor y presionar dos teclas juntas. La tecla del otro mando que quieres almacenar y la tecla de función en nuestro mando universal. La siguiente imagen muestra cómo almacenaríamos la tecla Siguiente Pista como Función 1.

El LED de estado parpadeará brevemente para indicar que se ha almacenado una función y entonces puedes soltar los botones.
Envío
Para enviar comandos IR, simplemente presiona el botón de modo (el LED de estado debería apagarse) y presiona una de las teclas de función que has programado. De nuevo, el LED de estado parpadeará para indicar que el comando ha sido enviado.
Depuración
Algunos mandos IR no son compatibles y no podrás programarlos. Puedes verificar esto conectando el monitor serial, cambiando al modo programación (el LED de estado debería estar encendido) y comprobando si la librería IRremote puede decodificar la señal. La salida debería ser similar a esta:

Aquí recibimos con éxito un comando con dirección 0x20 y código de comando 0x8 .
Para depurar la funcionalidad de envío, uno de estos testers de componentes será muy útil. De lo contrario, tendrás que confiar en prueba y error para descubrir qué está mal.

Tester multifunción
El tester de componentes anterior puede decodificar señales IR y una señal recibida con éxito se ve así:

Conclusiones
En este tutorial, has aprendido cómo construir un mando IR universal y programable usando Arduino. Siguiendo las instrucciones paso a paso, puedes crear fácilmente tu propio mando que puede operar una amplia gama de dispositivos infrarrojos.
Comenzamos discutiendo las piezas necesarias para este proyecto, que incluyen una placa Arduino, un módulo receptor IR y un módulo transmisor IR. Describimos el cableado entre estos componentes y proporcionamos el código para controlarlos. Además, explicamos cómo usar el mando para programar comandos IR de otros mandos.
Si tienes más preguntas o necesitas orientación adicional, consulta la sección de Preguntas Frecuentes o explora los enlaces proporcionados para más recursos e inspiración.
¡Feliz bricolaje!
Preguntas frecuentes
Aquí tienes algunas preguntas comunes sobre cómo construir un mando IR universal y programable con Arduino:
¿Puedo tener más botones de función?
Sí, solo replica el cableado de los botones existentes para los nuevos botones y extiende el código. Específicamente, las funciones receive() y send() deben ampliarse para manejar los botones adicionales.
¿Cómo puedo aumentar el alcance del mando IR?
Puedes conectar LEDs IR adicionales a otros pines de salida. O puedes alimentar un LED IR a un voltaje más alto, pero esto requerirá un transistor o MOSFET para controlar la señal de entrada al LED. Aquí tienes un circuito de ejemplo que usa una batería de 9V para alimentar un diodo transmisor IR:

Para más detalles y ejemplos sobre MOSFETs, consulta nuestro tutorial sobre Control Air-Conditioner via IR with ESP32 or ESP8266 y How To Control Fan using Arduino UNO .
¿No funciona con mi mando IR?
La librería IRremote es excelente pero no soporta todos los protocolos de comunicación IR que existen. Específicamente, para el envío usamos TinyIRSender , que está limitado al protocolo NEC, aunque la librería IRremote soporta otros protocolos también. Si eso no es suficiente, echa un vistazo a IRremoteESP8266 como posible alternativa.
¿Quiero controlar mi aire acondicionado con el mando IR?
Prueba la librería IRremoteESP8266 . Tiene un gran soporte para muchas unidades de aire acondicionado.
¿Puedo usar cualquier placa Arduino para este proyecto?
Sí, puedes usar cualquier placa Arduino para este proyecto siempre que puedas conectar un receptor y transmisor infrarrojo, y las librerías necesarias sean compatibles. Un ESP32, por ejemplo, sería una gran alternativa a un Arduino.
¿Cómo sé qué códigos IR usar para mis dispositivos?
Puedes encontrar los códigos IR para tus dispositivos buscando en línea o consultando el manual del usuario del dispositivo. Muchos fabricantes proporcionan bases de datos de códigos IR que pueden usarse con librerías Arduino. Alternativamente, puedes usar un módulo receptor IR para capturar los códigos de un mando existente. Consulta nuestro tutorial sobre How to use an IR receiver and remote with Arduino .
¿Puedo controlar múltiples dispositivos con este mando IR?
Sí, puedes controlar múltiples dispositivos con este mando IR. Programando diferentes códigos IR para cada dispositivo, puedes cambiar entre ellos usando botones o un sistema de menús en tu código Arduino. Ten en cuenta, sin embargo, que el código anterior solo soporta el protocolo NEC, pero afortunadamente la mayoría de los mandos IR lo usan.
¿Puedo añadir funciones adicionales al mando IR?
¡Por supuesto! La plataforma Arduino permite una personalización infinita. Puedes añadir funciones como una pantalla LCD retroiluminada, un codificador rotatorio para navegación de menús, o incluso integrarlo con otros dispositivos inteligentes del hogar usando protocolos de comunicación inalámbrica como Wi-Fi o Bluetooth.
Si tienes más preguntas o necesitas ayuda adicional, no dudes en preguntar en la sección de comentarios abajo.
Enlaces
A continuación algunos enlaces útiles para explicaciones adicionales y construcciones alternativas.
- IR Remote and Receiver with Arduino Tutorial (4 Examples)
- ESP32 And IR Remote Interface – A Complete Tutorial
- How to Control a Servo with an IR Remote
- Universal Arduino Remote : 10 Steps (with Pictures)
- Arduino Infrared (IR) Control… The Universal Remote …
- Arduino based universal TV Remote
- Arduino IR Remote Controller Tutorial – Setup and Map …
- Arduino Infrared Remote Tutorial : 7 Steps

