Início›Projetos›Comando Universal IR
⬤ Avançado · Projeto Integrado

📺 Comando Universal IR

⏱️ 60–75 min📊 Avançado
Recetor IREmissor IRJoystickLED RGB

Nesta página

🎯 Objetivo do Projeto

Criar um comando universal programável que captura os códigos IR de qualquer comando existente (TV, ar condicionado, etc.) e os replica. O joystick navega num menu de dispositivos/funções guardadas na EEPROM do Arduino. O LED RGB indica o dispositivo activo.

MóduloPino do móduloPino ArduinoBiblioteca
Recetor IR (#8)VCC / GND / OUT5V / GND / D11IRremote — receber e descodificar
Emissor IR (#23)VCC / GND / S5V / GND / D3 (PWM)IRremote — enviar NEC/SONY
Joystick (#30)VCC / GND / VRx / VRy / SW5V / GND / A0 / A1 / D2— (analogRead / digitalRead)
LED RGB (#27)VCC / GND / R / G / B5V / GND / D9 / D10 / D12— (analogWrite)
⚠️
A biblioteca IRremote usa o pino D11 para receção e o pino D3 para emissão (é um pino PWM obrigatório para gerar a portadora de 38kHz). Não podes usar D3 para outra função neste projeto.

📻 Fase 1 — Capturar Códigos IR

1

Instalar a biblioteca IRremote

No Arduino IDE: Ferramentas → Gerir Bibliotecas → pesquisa IRremote → instala a versão de z3t0/shirriff.

2

Carregar o sketch de captura

Carrega o sketch abaixo. Aponta qualquer comando TV ao recetor e prime um botão. O código hexadecimal aparece no Serial Monitor.

3

Registar os códigos

Para cada botão que queres replicar, regista: protocolo (NEC, SONY, RC5…), endereço e código. Copia para a tabela na EEPROM do sketch principal.

ir_capturar.ino
#include <IRremote.hpp>
#define RECV_PIN 11

void setup() {
  Serial.begin(9600);
  IrReceiver.begin(RECV_PIN, ENABLE_LED_FEEDBACK);
  Serial.println("A aguardar sinal IR — aponta o comando e prime um botão");
}

void loop() {
  if (IrReceiver.decode()) {
    Serial.print("Protocolo: ");
    Serial.print(IrReceiver.decodedIRData.protocol);
    Serial.print("  Endereço: 0x");
    Serial.print(IrReceiver.decodedIRData.address, HEX);
    Serial.print("  Código: 0x");
    Serial.println(IrReceiver.decodedIRData.command, HEX);
    IrReceiver.resume();  // Pronto para o próximo sinal
  }
}
ir_menu_joystick.ino
// Estrutura do menu: dispositivo → lista de comandos
struct Comando {
  const char* nome;
  uint16_t    endereco;
  uint16_t    codigo;
};

// Exemplo — substitui com os teus códigos capturados
const Comando cmds[] = {
  {"TV Power", 0x04, 0x08},
  {"TV Vol+",  0x04, 0x02},
  {"TV Vol-",  0x04, 0x03},
  {"TV CH+",   0x04, 0x00},
  {"AR On",    0xB2, 0x01},
  {"AR Off",   0xB2, 0x02},
};
#define N_CMDS  (sizeof(cmds)/sizeof(cmds[0]))

#define JOY_X  A0
#define JOY_SW 2
#define DZ     200   // Zona morta do joystick

int  sel = 0;
bool ultimoSW = HIGH;

bool joystickMoveu(int* delta) {
  int x = analogRead(JOY_X) - 512;
  if (x > DZ)  { *delta = +1; return true; }
  if (x < -DZ) { *delta = -1; return true; }
  return false;
}

void mostrarMenu() {
  Serial.print("["); Serial.print(sel+1); Serial.print("/");
  Serial.print(N_CMDS); Serial.print("] > ");
  Serial.println(cmds[sel].nome);
}

📤 Fase 3 — Emitir Comandos

ir_emitir.ino
#include <IRremote.hpp>
#define EMIT_PIN 3   // Pino PWM obrigatório

IrSender irSender;

void enviarComando(uint16_t endereco, uint16_t codigo) {
  irSender.sendNEC(endereco, codigo, 0);  // 0 = sem repetição
  delay(100);  // Pausa mínima entre envios
  Serial.print("Enviado: addr=0x");
  Serial.print(endereco, HEX);
  Serial.print(" cmd=0x");
  Serial.println(codigo, HEX);
}

// No loop(), ao premir SW do joystick:
// enviarComando(cmds[sel].endereco, cmds[sel].codigo);

💻 Código Integrado Completo

ℹ️
O sketch integrado combina captura, menu e emissão. Usa o joystick para navegar (esq/dir), o botão SW para enviar o comando seleccionado, e o LED RGB para indicar: azul = navegação, verde = enviado com sucesso, vermelho = erro.
proj_comando_universal.ino
#include <IRremote.hpp>

#define RECV_PIN 11
#define EMIT_PIN 3
#define JOY_X    A0
#define JOY_SW   2
#define LED_R    9
#define LED_G    10
#define LED_B    12
#define DZ       200

struct Cmd { const char* nome; uint16_t addr, code; };
const Cmd cmds[] = {
  {"TV Power", 0x04, 0x08},
  {"TV Vol+",  0x04, 0x02},
  {"TV Vol-",  0x04, 0x03},
  {"TV CH+",   0x04, 0x00},
  {"TV CH-",   0x04, 0x01},
};
#define N_CMDS (sizeof(cmds)/sizeof(cmds[0]))

int sel = 0;
IrSender irSender;

void setCor(int r,int g,int b){
  analogWrite(LED_R,r);analogWrite(LED_G,g);analogWrite(LED_B,b);
}

void setup() {
  Serial.begin(9600);
  pinMode(JOY_SW, INPUT_PULLUP);
  pinMode(LED_R,OUTPUT);pinMode(LED_G,OUTPUT);pinMode(LED_B,OUTPUT);
  setCor(0,0,80);  // Azul — aguardar
  Serial.println("Comando Universal IR — PRONTO");
  Serial.println(cmds[sel].nome);
}

void loop() {
  int x = analogRead(JOY_X) - 512;
  bool sw = (digitalRead(JOY_SW) == LOW);

  static unsigned long ultimoMov = 0;
  if (millis() - ultimoMov > 300) {
    if (x > DZ) {
      sel = (sel + 1) % N_CMDS;
      Serial.println(cmds[sel].nome);
      ultimoMov = millis();
    } else if (x < -DZ) {
      sel = (sel - 1 + N_CMDS) % N_CMDS;
      Serial.println(cmds[sel].nome);
      ultimoMov = millis();
    }
  }

  static bool ultimoSW = HIGH;
  if (sw && !ultimoSW) {
    setCor(0,255,0);  // Verde — a enviar
    irSender.sendNEC(cmds[sel].addr, cmds[sel].code, 0);
    Serial.print("Enviado: "); Serial.println(cmds[sel].nome);
    delay(500);
    setCor(0,0,80);  // Azul — aguardar
  }
  ultimoSW = sw;
}

🏆 Para ir mais longe

Kit B 37 · PR.FT6_15 · Arduino UNO · Raspberry Pi · Início · led.dge.medu.pt