IR to Z-Wave

IR receiver on Z-Uno allows to send Z-Wave commands on IR command. Reuse your TV remote control in Z-Wave home automation!

In most cases receiver have a built-in demodulator. If you have one of them, please check that your receiver frequency and fraquency of your IR-controller matches. The most popular is 38 KHz used by SAMSUNG/NEC/LG/... SONY uses 40KHz, but in most cases its commands can be detected on 38KHz too.

There are two ways to define IR commands: by raw (mark & space) sequence or by pre-defined commands and protocol (vendor command).

To get raw sequence use IRScanner.ino sketch from examples as IR-sniffer.
  • Z-Uno board
  • Breadboard
  • TSOP312xx, TSOP314xx, TSOP382xx, TSOP384xx or similiar. xx depends on your remote operating frequency (check the datasheet. Like this or this.
  • 3 wires

Download Fritzing project
// Receives data from built-in IR-controller of Z-Uno and sends command to specified group via Z-Wave

#include "IRController.h"

// Setup associations - we have 2 groups for on/off on raw command and on vendor command
ZUNO_SETUP_ASSOCIATIONS(ZUNO_ASSOCIATION_GROUP_SET_VALUE, ZUNO_ASSOCIATION_GROUP_SET_VALUE); 

// Traditionally IR-receivers like VISHAY TSOP312xx have inverted output. 
// It means that received MARK has LOW level and SPACE has HIGH level.
IRReceiverParams ir_receiver(IR_FLAGS_IO_INVERTED);
IRCommand_t ir_cmd;
byte ir_state;
word raw_data[200];

#define SWITCH_ON 0xff
#define SWITCH_OFF 0

#define RAW_GROUP CTRL_GROUP_1      // RAW GROUP
#define VENDOR_GROUP CTRL_GROUP_2   // VENDOR GROUP

// Use IRScanner.ino from examples as IR-sniffer
// This codes were sniffed from Apple IR Controller
word raw_command_on[] = {0x43, 0x2392, 0x1171, 0x24E, 0x219, 0x249, 0x66F, 0x248, 0x66F, 0x249, 0x66F, 0x249, 0x21E, 0x24E, 0x66A,
  0x24E, 0x66A, 0x24D, 0x66A, 0x24D, 0x66B, 0x24D, 0x66B, 0x24C, 0x66C, 0x24C, 0x21B, 0x246, 0x221, 0x24C, 0x21B, 0x247, 0x220,
  0x24D, 0x66B, 0x24C, 0x66B, 0x24C, 0x66B, 0x24C, 0x21A, 0x247, 0x670, 0x247, 0x21F, 0x24D, 0x219, 0x248, 0x21E, 0x24F, 0x218,
  0x24A, 0x21C, 0x245, 0x221, 0x24B, 0x66C, 0x24B, 0x21C, 0x246, 0x220, 0x24C, 0x21A, 0x247, 0x671, 0x246, 0x231, 0x247};
word raw_command_off[] = {0x43, 0x239C, 0x1165, 0x250, 0x231, 0x231, 0x66C, 0x24B, 0x66C, 0x24B, 0x66C, 0x24C, 0x235, 0x22C, 0x670,
  0x247, 0x66F, 0x248, 0x66E, 0x249, 0x66D, 0x24A, 0x66C, 0x24B, 0x66B, 0x24D, 0x234, 0x22D, 0x239, 0x234, 0x232, 0x22F, 0x237,
  0x236, 0x666, 0x247, 0x670, 0x247, 0x23A, 0x232, 0x66A, 0x24D, 0x669, 0x24E, 0x233, 0x22E, 0x238, 0x235, 0x232, 0x230, 0x236,
  0x22B, 0x23B, 0x231, 0x235, 0x22D, 0x66F, 0x249, 0x238, 0x234, 0x232, 0x230, 0x236, 0x236, 0x666, 0x246, 0x24B, 0x22D};

// Detected vendor 
#define MY_IR_VENDOR IR_VENDOR_NEC // NEC protocol in most cases
// Decoded commands	
#define MY_IR_VENDOR_CMD_ON  0x77E1E022   
#define MY_IR_VENDOR_CMD_OFF 0x77E11022		

void setup() {
  // Setup IR-controller as receiver
  IR.begin(&ir_receiver);
  IR.scan();
}

void loop() {
  // Check state of IR-controller
  ir_state = IR.getState();

  if (!(ir_state & IR_STATUS_BUSY)) {
    // IR-Controller received data 
    
    if (IR.equals_raw16(raw_command_on)) {                          // Control via RAW DATA
      zunoSendToGroupSetValueCommand(RAW_GROUP, SWITCH_ON);
    } else if (IR.equals_raw16(raw_command_off)) {
      zunoSendToGroupSetValueCommand(RAW_GROUP, SWITCH_OFF);
    } else if (IR.detectCommand(&ir_cmd)) {                         // Control via detected / known vedor specific command
      if (ir_cmd.vendor == MY_IR_VENDOR) {
        if (ir_cmd.data[0] == MY_IR_VENDOR_CMD_ON) {
            zunoSendToGroupSetValueCommand(VENDOR_GROUP, SWITCH_ON);
        } else if (ir_cmd.data[0] == MY_IR_VENDOR_CMD_OFF) {
            zunoSendToGroupSetValueCommand(VENDOR_GROUP, SWITCH_OFF);
      	}
      }
    }
    
    // restart scan process
    IR.scan();
  }
  delay(500);
}
Download this sketch