Puente IR Inteligente para SmartThings con Arduino UNO y ThingShield
Componentes y Suministros
| Componente | Cantidad |
|---|---|
| Arduino UNO | 1 |
| SmartThings Shield para Arduino (ThingShield) | 1 |
| LED Emisor IR | 1 |
| Diodo Receptor IR | 1 |
| Resistencia 100 Ohm (opcional) | 1 |
Introducción
Un mando a distancia de TV común puede hacer mucho más que cambiar de canal cuando se conecta a la nube de SmartThings. Con un número reducido de componentes y un resultado inmediato, este proyecto es una excelente forma de explorar la plataforma.
Arduino y el ThingShield
El SmartThings ThingShield facilita la creación de prototipos SmartThings usando Arduino. El shield se conecta directamente al UNO y se comunica con el hub SmartThings mediante protocolo Zigbee. Un interruptor en el shield permite elegir entre los pines 0,1 o 2,3 para la comunicación con Arduino. El ThingShield ya reserva el pin 6.
Más información sobre primeros pasos con Arduino: Guía oficial Arduino
Paso 1: Materiales Necesarios
- (x1) SmartThings Arduino ThingShield
- (x1) Arduino Uno
- (x1) Receptor IR
- (x1) LED Emisor IR
- (x1) Resistencia 100 Ohm (opcional)
Paso 2: Librería IR
El proyecto depende de la magnífica librería Arduino IRremote desarrollada por Ken Shirriff: GitHub Arduino-IRremote
Instala la librería en el IDE Arduino (guía oficial). Una vez instalada, modifica IRRemoteInt.h para usar el timer en el pin 9. En este ejemplo usamos el pin 3 para comunicación con el ThingShield.
Paso 3: Sketch Arduino
Sube el sketch a tu placa Arduino (ver sección Código).
Paso 4: Montaje
Conecta el ThingShield sobre el Arduino. Para el receptor IR: pines correspondientes a GND y 5V, pin de datos al pin 11 de Arduino. Conecta el LED emisor IR al pin 9 y GND. La resistencia de 100 ohm es opcional ya que el LED puede manejar la corriente máxima del Arduino al parpadear rápidamente; si se deja encendido continuamente, la misma corriente podría quemar el LED.
Paso 5: Crear Tipo de Dispositivo Personalizado en SmartThings
- En el IDE de SmartThings, ve a "My Device Types" y haz clic en "New SmartDevice".
- Nombra el nuevo tipo: "Ir Bridge".
- Define Atributos y Comandos para dos botones programables y un botón de grabación. Añade los mostrados en la documentación original.
- Copia la definición del dispositivo (ver sección Código) en la ventana de código del IDE. Guarda y Publica.
Paso 6: Actualizar ThingShield al Nuevo Tipo de Dispositivo
- Añade tu ThingShield al hub SmartThings si no está configurado. Para emparejar: conecta el shield al Arduino, alimenta, mantén el botón "Switch" 6 segundos. En la app SmartThings, selecciona Add, pulsa una vez más el botón físico "switch" y el hub identificará el ThingShield.
- En el IDE, ve a "devices", selecciona tu dispositivo, clic en "Edit". En el desplegable "Type" elige el nuevo tipo "Ir Bridge". Actualiza.
- Nota: al publicar actualizaciones futuras, verifica que los dispositivos físicos permanezcan asociados al tipo correcto.
Paso 7: Escribir la SmartApp
- En "My SmartApps", crea "New SmartApp". Nombre, descripción, categoría "My apps".
- Copia el código SmartApp (ver sección Código). Guarda y Publica.
- Referencia al tipo de dispositivo:
input "irDevice", "device.IrBridge"(el nombre "Ir Bridge" se convierte en "IrBridge" en camelCase sin espacios).
Paso 8: Activar la SmartApp
En la app SmartThings, asocia la nueva SmartApp con el dispositivo IR y selecciona los interruptores a controlar. Pulsa "install".
Para programar cada botón: ve a detalles del tile (icono engranaje). Selecciona el botón grande de grabación (se pone rojo = modo grabación). Pulsa el tile (Play/Pausa o B) a controlar (se pone amarillo). Apunta tu mando al ThingShield y pulsa el botón a aprender. El ThingShield enviará el código a la nube SmartThings y lo asociará al botón elegido. El botón programado se pondrá verde y el de grabación volverá a blanco.
La próxima vez que pulses ese botón en tu mando, alternarás el interruptor asociado en la SmartApp.
Código
Sketch Arduino (C/C++)
#include <SoftwareSerial.h>
#include <SmartThings.h>
#include <IRremote.h>
#define PIN_LED 13
#define PIN_RECV 11
#define PIN_THING_RX 3
#define PIN_THING_TX 2
SmartThingsCallout_t messageCallout;
SmartThings smartthing(PIN_THING_RX, PIN_THING_TX, messageCallout);
bool isDebugEnabled = true;
int stateLED = 0;
IRrecv irrecv(PIN_RECV);
IRsend irsend;
decode_results results;
void setup() {
pinMode(PIN_LED, OUTPUT);
digitalWrite(PIN_LED, LOW);
if (isDebugEnabled) { Serial.begin(9600); Serial.println("setup.."); }
irrecv.enableIRIn();
}
void loop() {
smartthing.run();
if (irrecv.decode(&results)) {
blue();
irrecv.resume();
String irCmd;
if (results.decode_type == NEC) {
irCmd = String(results.value, HEX) + "," + "NEC" + String(results.bits, DEC) + ":" + String(results.value, HEX);
} else if (results.decode_type == SONY) {
irCmd = String(results.value, HEX) + "," + "SNY" + String(results.bits, DEC) + ":" + String(results.value, HEX);
} else if (results.decode_type == RC5) {
irCmd = String(results.value, HEX) + "," + "RC5" + String(results.bits, DEC) + ":" + String(results.value, HEX);
} else if (results.decode_type == RC6) {
irCmd = String(results.value, HEX) + "," + "RC6" + String(results.bits, DEC) + ":" + String(results.value, HEX);
} else {
irCmd = String(results.value, HEX) + "," + "RAW" + String(results.bits, DEC) + ":";
}
Serial.println(irCmd);
smartthing.send(irCmd);
}
}
void messageCallout(String message) {
smartthing.shieldSetLED(0, 0, 0);
if (isDebugEnabled) { Serial.print("Rx: '"); Serial.print(message); Serial.println("' "); }
String type = message.substring(0,3);
int startCode = message.indexOf(':');
String lenStr = message.substring(3, startCode);
String codeStr = message.substring(startCode + 1);
unsigned long code = (type != "RAW") ? stringToNum(codeStr, 16) : 0;
int len = stringToNum(lenStr, 10);
if (type == "NEC") { irsend.sendNEC(code, len); irrecv.enableIRIn(); }
else if (type == "SNY") { irsend.sendSony(code, len); irrecv.enableIRIn(); }
else if (type == "RC5") { irsend.sendRC5(code, len); irrecv.enableIRIn(); }
else if (type == "RC6") { irsend.sendRC6(code, len); irrecv.enableIRIn(); }
}
// Funciones auxiliares: stringToNum, exponent, green, blue, red, off
Definición del Dispositivo (Groovy)
metadata {
simulator {}
tiles {
standardTile("recStatus", "device.recStatus", width: 2, height: 2, canChangeIcon: true, canChangeBackground: true) {
state "off", label: 'record', action: "record", backgroundColor: "#ffffff"
state "on", label: 'record', action: "record", backgroundColor: "#ff0000"
}
standardTile("buttonA", "device.buttonAStatus", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
state "unset", label: '', action: "buttonA", icon: "st.custom.buttons.play-pause", backgroundColor: "#cccccc"
state "prog", label: '', action: "buttonA", icon: "st.custom.buttons.play-pause", backgroundColor: "#FDE910"
state "set", label: '', action: "buttonA", icon: "st.custom.buttons.play-pause", backgroundColor: "#79b821"
}
standardTile("buttonB", "device.buttonBStatus", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
state "unset", label: '', action: "buttonB", icon: "st.custom.buttons.b", backgroundColor: "#cccccc"
state "prog", label: '', action: "buttonB", icon: "st.custom.buttons.b", backgroundColor: "#FDE910"
state "set", label: '', action: "buttonB", icon: "st.custom.buttons.b", backgroundColor: "#79b821"
}
main (["buttonA","buttonB"])
details (["recStatus","buttonA","buttonB"])
}
}
def parse(String description) { ... }
def record() { ... }
def buttonA() { ... }
def buttonB() { ... }
def clearLast() { ... }
SmartApp (Groovy)
preferences {
section("Pick an IR device...") { input "irDevice", "device.IrBridge" }
section("Button A turns on or off...") { input "switch1", "capability.switch", title: "This light", required: false }
section("Button B turns on or off...") { input "switch2", "capability.switch", title: "This light", required: false }
}
def installed() { subscribe(irDevice, "button.B", handleB); subscribe(irDevice, "button.A", handleA) }
def updated() { unsubscribe(); subscribe(irDevice, "button.B", handleB); subscribe(irDevice, "button.A", handleA) }
def handleA(evt) { if (switch1.currentValue("switch") == "on") switch1.off() else switch1.on() }
def handleB(evt) { if (switch2.currentValue("switch") == "on") switch2.off() else switch2.on() }
Proceso de manufactura
- Construya un robot con Raspberry Pi y Python: Guía completa
- Construye un Segway Autoequilibrado con Raspberry Pi
- Captura Gotas de Agua en Acción con Arduino Nano: Fotografía de Alta Velocidad DIY
- Sensor K30 CO₂: Monitorización en tiempo real de la calidad del aire interior
- Facilitar la comunicación sordo‑ciego usando 1Sheeld y Arduino
- Alcancía Inteligente: Controla un Aceptador de Monedas con Arduino Nano
- Controla un LED por Bluetooth con Arduino – Guía DIY paso a paso
- Monitoriza la Temperatura de tu Hogar desde Cualquier Lugar con Integración Arduino Cloud
- Integración del Sensor de Pulso MAX30100 con Arduino: Guía Paso a Paso
- Construyendo la fuerza laboral del mañana: Cómo la automatización inteligente mejora la experiencia del empleado
- Aprovechar los datos en el Internet de la Fiabilidad: estrategias para una gestión efectiva