Receptor Infrarrojo (TSOP38238 / VS1838B)
Detecta ráfagas de 38 kHz. Salida conectada al Pin Digital 43 del Arduino Mega.
Barra de 9 LEDs en la Protoboard (Pines 13 al 5)
🔌 Conexiones y Circuito Eléctrico (Práctica 4)
Ubicación física del receptor IR en la protoboard y conexión al Pin 43 del Arduino Mega.
* El cable morado conecta el pin OUT del sensor al Pin 43 del Arduino Mega (fila impar, bajo el cable azul del sensor DHT22).
| Terminal | Pin Mega | Función |
|---|---|---|
| OUT (Señal) | Pin 43 | Señal demodulada 38 kHz |
| VCC (+) | 5V | Alimentación positiva |
| GND (-) | GND | Masa común |
| Caso | Tecla Mando | Acción en LEDs |
|---|---|---|
| caso = 1 | Tecla 1 | Enciende todos los 9 LEDs |
| caso = 2 | Tecla 2 | Apaga todos los 9 LEDs |
| caso = 3 | Tecla 3 | Secuencia 3: Marquesina |
| caso = 4 | Tecla 4 | Secuencia 4: Relleno |
💻 Monitor Serie Virtual (9600 Baudios)
Muestra los códigos en tiempo real al hacer click en el mando.
📜 Código Arduino Completo (Estructura por Casos)
Listo para copiar y subir directamente con Arduino IDE.
// =============================================================================
// MAQUETA ARDUINO MEGA 2560 — PRÁCTICA 4
// Control por Mando a Distancia (IR) mediante variable "caso"
// Librería necesaria: "IRremote" (incluir )
// =============================================================================
#include <IRremote.hpp>
// 1. PINES DE LOS 9 LEDs (Pines 13 al 5)
const uint8_t NUM_LEDS = 9;
const uint8_t PINES_LEDS[NUM_LEDS] = {13, 12, 11, 10, 9, 8, 7, 6, 5};
// 2. RECEPTOR IR (Conectado al Pin 43)
const int PIN_RECEPTOR = 43;
// 3. VARIABLE DE CONTROL DE CASO
// Caso 1: Enciende todos | Caso 2: Apaga todos | Caso 3: Marquesina | Caso 4: Relleno
int caso = 2; // Inicia en Caso 2 (Apagado)
// Variables de tiempo para las secuencias con millis()
unsigned long tiempoUltimoPasoLED = 0;
const unsigned long INTERVALO_ANIMACION = 150; // Velocidad de la secuencia (ms)
int pasoActual = 0;
// =============================================================================
// SETUP
// =============================================================================
void setup() {
Serial.begin(9600); // Monitor Serie USB para depuración
Serial3.begin(9600); // Bluetooth (Serial3: Pin 14 TX, Pin 15 RX)
// Configurar los 9 LEDs como salida
for (uint8_t i = 0; i < NUM_LEDS; i++) {
pinMode(PINES_LEDS[i], OUTPUT);
digitalWrite(PINES_LEDS[i], LOW);
}
// Inicializar receptor IR en Pin 43
IrReceiver.begin(PIN_RECEPTOR, ENABLE_LED_FEEDBACK);
Serial.println(F("=================================================="));
Serial.println(F(" PRÁCTICA 4: CONTROL POR CASOS (MANDO IR) "));
Serial.println(F("=================================================="));
Serial.println(F(" Caso 1: Enciende todos (Tecla 1 / BT '1')"));
Serial.println(F(" Caso 2: Apaga todos (Tecla 2 / BT '2')"));
Serial.println(F(" Caso 3: Marquesina (Tecla 3 / BT '3')"));
Serial.println(F(" Caso 4: Relleno (Tecla 4 / BT '4')"));
Serial.println(F("=================================================="));
apagarTodos();
}
// =============================================================================
// LOOP PRINCIPAL
// =============================================================================
void loop() {
// 1. Escanear señales del Mando IR
leerMandoIR();
// 2. Escanear órdenes de Bluetooth
leerBluetooth();
// 3. Máquina de estados según el "caso"
switch (caso) {
case 1:
// Caso 1: Todos los LEDs encendidos
encenderTodos();
break;
case 2:
// Caso 2: Todos los LEDs apagados
apagarTodos();
break;
case 3:
// Caso 3: Secuencia Marquesina cíclica
secuencia3(INTERVALO_ANIMACION);
break;
case 4:
// Caso 4: Secuencia Relleno acumulativo cíclico
secuencia4(INTERVALO_ANIMACION);
break;
}
}
// =============================================================================
// LECTURA DEL MANDO IR
// =============================================================================
void leerMandoIR() {
if (IrReceiver.decode()) {
uint32_t cmd = IrReceiver.decodedIRData.command;
uint32_t raw = IrReceiver.decodedIRData.decodedRawData;
Serial.print(F("Comando IR recibido: 0x"));
Serial.println(cmd, HEX);
// Tecla 1 (Encender todos)
if (cmd == 0x45 || cmd == 0x16 || cmd == 0xC || raw == 0xFF6897) {
cambiarCaso(1);
}
// Tecla 2 (Apagar todos)
else if (cmd == 0x46 || cmd == 0x19 || cmd == 0x18 || raw == 0xFF9867) {
cambiarCaso(2);
}
// Tecla 3 (Secuencia Marquesina)
else if (cmd == 0x47 || cmd == 0xD || cmd == 0x5E || raw == 0xFFB04F) {
cambiarCaso(3);
}
// Tecla 4 (Secuencia Relleno)
else if (cmd == 0x44 || cmd == 0xC || cmd == 0x8 || raw == 0xFF30CF) {
cambiarCaso(4);
}
IrReceiver.resume(); // Listo para el siguiente pulso
}
}
// =============================================================================
// LECTURA DEL BLUETOOTH (Serial3)
// =============================================================================
void leerBluetooth() {
if (Serial3.available() > 0) {
char dato = Serial3.read();
Serial.print(F("Dato Bluetooth: '"));
Serial.print(dato);
Serial.println(F("'"));
if (dato == '1') cambiarCaso(1);
if (dato == '2') cambiarCaso(2);
if (dato == '3') cambiarCaso(3);
if (dato == '4') cambiarCaso(4);
}
}
// =============================================================================
// FUNCIÓN PARA CAMBIAR DE CASO
// =============================================================================
void cambiarCaso(int nuevoCaso) {
caso = nuevoCaso;
pasoActual = 0;
tiempoUltimoPasoLED = millis() - INTERVALO_ANIMACION;
if (caso == 1) encenderTodos();
if (caso == 2) apagarTodos();
if (caso == 3 || caso == 4) apagarTodos();
Serial.print(F("-> ACTIVADO CASO: "));
Serial.println(caso);
}
// =============================================================================
// FUNCIONES DE CONTROL DE LEDs
// =============================================================================
void apagarTodos() {
for (uint8_t i = 0; i < NUM_LEDS; i++) {
digitalWrite(PINES_LEDS[i], LOW);
}
}
void encenderTodos() {
for (uint8_t i = 0; i < NUM_LEDS; i++) {
digitalWrite(PINES_LEDS[i], HIGH);
}
}
// Secuencia 3: Se enciende un LED y se apaga el anterior de forma cíclica
void secuencia3(unsigned long retardo) {
unsigned long tiempoActual = millis();
if (tiempoActual - tiempoUltimoPasoLED >= retardo) {
tiempoUltimoPasoLED = tiempoActual;
apagarTodos();
digitalWrite(PINES_LEDS[pasoActual], HIGH);
pasoActual++;
if (pasoActual >= NUM_LEDS) pasoActual = 0;
}
}
// Secuencia 4: Acumulativo de LEDs encendidos hasta completarse y reiniciar
void secuencia4(unsigned long retardo) {
unsigned long tiempoActual = millis();
if (tiempoActual - tiempoUltimoPasoLED >= retardo) {
tiempoUltimoPasoLED = tiempoActual;
if (pasoActual < NUM_LEDS) {
digitalWrite(PINES_LEDS[pasoActual], HIGH);
pasoActual++;
} else {
apagarTodos();
pasoActual = 0;
}
}
}
🧠 Fundamentos Técnicos del Mando Infrarrojo
Cómo viaja la información desde el mando hasta el microcontrolador.
La luz ambiente (sol, tubos fluorescentes) emite infrarrojos. Para evitar interferencias, el mando modula la luz a 38.000 Hz. El filtro interno del sensor TSOP solo amplifica esa frecuencia exacta.
Codifica bits mediante modulación por distancia de pulsos (Pulse Distance Modulation). Un bit '0' dura 1.12 ms y un bit '1' dura 2.25 ms. Cada paquete transmite 32 bits (dirección y comando invertido para comprobación).
El receptor IR requiere medir micropulsos. Si el código tuviera un delay(500) durante la animación de los LEDs, el Arduino quedaría ciego y perdería las pulsaciones del mando.