💬 Infrared Sender and Receiver


  • Admin

    This thread contains comments for the article "Infrared Sender and Receiver" posted on MySensors.org.



  • is this a learning mode module ?
    how use this module for learn my ir codes ?



  • @Reza said:

    is this a learning mode module ?
    how use this module for learn my ir codes ?

    This node decodes IR remote codes, print protocol and hex value to serial monitor and send it to gateway. Then controller can do logic on that to do some stuff.
    The sample code also receive on/off command from controller and emits IR signal depending on it.

    I use this node to turn on/off sony sound system (15bit sony protocol) and benq projector (NEC protocol) together beside htpc(via wol). Openhab rule send 8byte IR codes as V_IR_Send to node and node emits the required IR codes.



  • @Talat-Keleş
    I mean that every ir codes ( each brand for TV , audio . . . ) can learn to this node ( similar to zwave IR extender) and use OR in sketch we most write every codes that i will use ?!
    if this is a learning mode module !how many codes can learn to this ? ) for example zwave ir extender give 20 key ! or global cashe give many codes ?!



  • @Reza

    That node is simply IR to gateway (or vice versa) transfering medium. It doesn't learn just decodes or emits IR signals. This node is mostly dumb.

    To make it learn something like z-wave ir extender,

    Manually: Just manually decode and note down required codes then use them. Easy solution for known and used commands like on/off, vol +/-, numbers etc.

    • hard code it on node, however program space is tight. eeprom may be required.
    • hard code it on controller, easy for logic operations and automation needs.

    Automatic:

    • Write the code to learn and save it to eeprom. It requires some coding, at the end it might be a device like somehow z-wave ir extender. Howeer controller should know and send some kind of message to select right IR code. I didn't work on this solution yet.


  • @Talat-Keleş
    I am confused . i just want know if i want control my TV ( each switch for example on , off , vol + , vol - , number etc) with a domoticz and a IR sensor (mysensors) how i do it ?



  • @Reza

    Below is node sketch (v1.5.4) and openhab sitemap&items for simple control. More advanced control needs rules/scripts to make it more automation like.

    Set up the circuit, load below code or example code given and open serial monitor. Press buttons on IR remote and read hex values on serial. Note down values for buttons you need. (i.e. power off 0x184C, power on 0x104C, chanel up 0x1860 etc, RC5 protocol) If below sketch is uploaded to node, then adapt domoticz to send needed IR codes like i did in sitemaps part or use automation rules to send required commands to node to tv.

    Simple button based TV Control with OH

    Here is my node sketch:

    /**
     * The MySensors Arduino library handles the wireless radio link and protocol
     * between your home built sensors/actuators and HA controller of choice.
     * The sensors forms a self healing radio network with optional repeaters. Each
     * repeater and gateway builds a routing tables in EEPROM which keeps track of the
     * network topology allowing messages to be routed to nodes.
     *
     * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
     * Copyright (C) 2013-2015 Sensnology AB
     * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
     *
     * Documentation: http://www.mysensors.org
     * Support Forum: http://forum.mysensors.org
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * version 2 as published by the Free Software Foundation.
     *
     *******************************
     *
     * REVISION HISTORY
     * Version 1.0 - Henrik EKblad
     * Version 1.1 - V_IR_SEND / _RECEIVE 16.08.2016 Any hex command received over NRF is send with IR led
     * Version 1.2 - Don't send repeting codes - 19.08.2016 T. Keles
     * Version 1.3 - Repeating code blocking correction - 01.09.2016 T.Keles
     * 
     * DESCRIPTION
     * This sketch decodes IR remote and send to gateway.
     * Rules can interpret this or simpleused to find out button codes.
     * Controller sends string code values as V_IR_Send and incoming message is emitted by IR led.
     * An IR LED must be connected to Arduino PWM pin 3.
     * An optional ir receiver can be connected to PWM pin 8. 
     * All receied ir signals will be sent to gateway device stored in V_IR_RECEIVE
     *  http://www.mysensors.org/build/ir
     */
    
    #include <MySensor.h>
    #include <SPI.h>
    #include <IRLib.h>
    
    int RECV_PIN = 8;
    
    #define CHILD_1  3  // childId
    
    IRsend irsend;
    IRrecv irrecv(RECV_PIN);
    IRdecode decoder;
    unsigned int Buffer[RAWBUF];
    unsigned long prevMillis=0;
    MySensor gw;
    MyMessage msg(CHILD_1, V_IR_RECEIVE); //send decoded ir code
    
    void setup()  
    {  
      irrecv.enableIRIn(); // Start the ir receiver
      decoder.UseExtnBuf(Buffer);
      gw.begin(incomingMessage,2);
    
      // Send the sketch version information to the gateway and Controller
      gw.sendSketchInfo("IR Remote", "1.3");
    
      // Register a sensors to gw. Use binary light for test purposes.
      gw.present(CHILD_1, S_IR);
    }
    
    
    void loop() 
    {
      gw.process();
      if (irrecv.GetResults(&decoder)) {
        unsigned long curMillis=millis();
        irrecv.resume(); 
        decoder.decode();
        decoder.DumpResults(); // dumresults print values to serial monitor
        
        if(curMillis-prevMillis>900){ // if last IR received less than 900ms pass it, otherwise send it to GW
        							  //This value is experimental and added to bypass rapidly repeating codes 
          prevMillis=curMillis;
          if(!(decoder.value==0 || decoder.value==0xffffff)){ // if value is valid
            char buffer[10];
            sprintf(buffer, "%08lX", decoder.value); //format it to 8byte Uppercase Hex format
            gw.send(msg.set(buffer));  // Send ir result to gw
          }
          
        }
      }
    }
    
    void incomingMessage(const MyMessage &message) {
    char ircode[11] = {0};  // in case your code takes the form of 0xE0E0FF0F
    //incoming ir code is string, however IRSend need unsigned long Below codes do the work 
       if (message.type == V_IR_SEND) {
          String hexstring = message.getString();
          hexstring.toCharArray(ircode, sizeof(ircode));
          // get the code as an unsigned long
          unsigned long code = strtoul(ircode, NULL, 0);
          if(code==0 || code ==0xFFFFFFFF) {} //if code is not valid, do nothing        
          irsend.send(RC5,code,13); // blast incoming hex code to IR device 
        }
        // Start receiving ir again...
        irrecv.enableIRIn(); 
    }
    

    In openhab .items file:

    String TV_power "TV" <television> (gHomeMedia) {mysensors="2;3;V_IR_SEND"}
    String TV_channel "Channel" <television> (gHomeMedia) {mysensors="2;3;V_IR_SEND"}
    String TV_volume "Volume" <television> (gHomeMedia) {mysensors="2;3;V_IR_SEND"}
    String IR_Receive "IR Code [%s]" <television> (gHomeMedia) {mysensors="2;3;V_IR_RECEIVE"}
    

    In openhab sitemap:

    Frame label="TV Control" {
    	Switch item=TV_power label="TV Power" mappings=[0x184C=OFF, 0x104C=ON]
    	Switch item=TV_channel label="Channel" mappings=[0x1860=UP, 0x1061=DOWN] visibility=[TV_power==0x104C]
    	Switch item=TV_volume label="Volume" mappings=[0x1850="V+", 0x1051="V-"] visibility=[TV_power==0x104C]
    	Text item=IR_Receive
    


  • @Talat-Keleş
    thank you my friend



  • This post is deleted!


  • is it possible to use with domoticz?



  • this module ( ir transmitter ) is weak in transmit . for more than 2 or 3 meter distance dont work . also for less than 1 meter we must direct connection exactly.
    i think this is related to power or noise or problem of module ?!
    can you guidance me ?



  • domoticz doesn't support this ?! i test this and i see domoticz wont detect this node



  • Hi @Reza ,
    Did you solve this problem?



  • @zhangzc

    hi , no . i can not use this device with domoticz



  • @Reza said:

    this module ( ir transmitter ) is weak in transmit . for more than 2 or 3 meter distance dont work . also for less than 1 meter we must direct connection exactly.
    i think this is related to power or noise or problem of module ?!
    can you guidance me ?

    I'm thinking of building this but am concerned about limited range. I'd like it to work 10ft/3m. Can someone confirm that this does not work at these distances? If so, is there a way to increase the range?



  • So how can is set this node in learnmode?? V_IR_RECORD in the Serial of Arduino?
    How do i store codes in the Eprom. SO i can use them in Domoticz



  • @Wackid

    I know how to read out the IR signals. And to put it in the sketch manually. But I really like to make use of the record function.
    Where and how do I make the node to set it in learn function.



  • I send command from remote control arduino read this command (i can see this in serial monitor) but this commands are not sending to gateway, my radio is working the sensor connect to gateway and controller. I use example Sketch given up in this page without changing anything.
    Any idea whats wrong in my setup?



  • This post is deleted!


  • I use this IR transmitter toward my LG Tv and it works at a distance of ~3.5 m, but IR LED must be well pointed to the Tv, otherwise it doesn't work.



  • @Talat-Keleş
    Hi, I am having an issue compiling the sketch and was wondering if you had any input or could help me out, This is what I get back when I try to compile;
    0_1483733093476_upload-fba9c55f-1a02-4b17-b7ff-bc75aadb47d1



  • @ramoncarranza
    Compiler complains about not understanding decode_type_t. It should be defined in .h file or maybe you defined it in sketch but there is a problem definetly.
    Can you post whole sketch and IR library and error message if any other so we can check and test.

    By the way, I installed IRremote.h (v2.1.0) via library manager, and default sketch compiled without error on IDE 1.6.5 win7 and IDE 1.6.10 linux mint 17.



  • Re: 💬 Infrared Sender and Receiver

    How do you enter the raw IR codes, i.e. those that aren't covered in the sketch? I have one through the receiver in the format - 23784 1800 -800 950 -1700 1800 -850 900 -850 950 -1700 1800 -850 900 -850 900 -850 950 -800 950 -850 900



  • @ramoncarranza When I went and looked where the library manager installed the IRremote lib(for me C:\Users\User\Documents\Arduino\libraries), it had given it an odd name like arduino_294267. I renamed it to IRremote and the issue went away.



  • I am confused i see the decode in my com monitor and i see the ir node in my domoticz but there is no data???



  • Can I use MQTT & Node Red to make this work, if yes can somebody show me how



  • ok i record ir code 240E4F17 from my AC remote hov can i sent this code from my controler to IR node and request from node to sent that code (on/off) AC i was trying with raw mesage but i dot know what to send (Type/ Sub type , Acknowledge/ Payload)



  • So, I am thinking of building this and I noticed that the documentation says that you may need a mega to do this. Is a mega required, or will the code work with a nano or an uno?



  • Hi Running this code I get the following errors anyone know why?
    Arduino: 1.6.5 (Windows 8.1), Board: "Arduino Nano, ATmega328"

    Build options changed, rebuilding all

    Using library SPI in folder: C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\SPI

    Using library MySensors in folder: C:\Users\Audrey\Documents\libraries\MySensors

    Using library Robot IR Remote in folder: C:\Program Files (x86)\Arduino\libraries\RobotIRremote

    C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avr-g++ -c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10605 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR -IC:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino -IC:\Program Files (x86)\Arduino\hardware\arduino\avr\variants\eightanaloginputs -IC:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\SPI -IC:\Users\Audrey\Documents\libraries\MySensors -IC:\Program Files (x86)\Arduino\libraries\RobotIRremote\src C:\Users\Audrey\AppData\Local\Temp\build2205553450015260610.tmp\IRSendRec.cpp -o C:\Users\Audrey\AppData\Local\Temp\build2205553450015260610.tmp\IRSendRec.cpp.o

    IRSendRec.ino:95:5: error: 'decode_type_t' does not name a type
    IRSendRec.ino:114:1: error: 'IRsend' does not name a type
    IRSendRec.ino:135:1: error: too many initializers for 'IRCode::<anonymous struct>'
    IRSendRec.ino:135:1: error: too many initializers for 'IRCode::<anonymous struct>'
    IRSendRec.ino:135:1: error: too many initializers for 'IRCode::<anonymous struct>'
    IRSendRec.ino:135:1: error: too many initializers for 'IRCode::<anonymous struct>'
    IRSendRec.ino:135:1: error: too many initializers for 'IRCode::<anonymous struct>'
    IRSendRec.ino:135:1: error: too many initializers for 'IRCode::<anonymous struct>'
    IRSendRec.ino:135:1: error: too many initializers for 'IRCode::<anonymous struct>'
    IRSendRec.ino:135:1: error: too many initializers for 'IRCode::<anonymous struct>'
    IRSendRec.ino:135:1: error: too many initializers for 'IRCode::<anonymous struct>'
    IRSendRec.ino:135:1: error: too many initializers for 'IRCode::<anonymous struct>'
    IRSendRec.ino: In function 'byte lookUpPresetCode(decode_results*)':
    IRSendRec.ino:246:38: error: 'struct IRCode::<anonymous>' has no member named 'type'
    IRSendRec.ino:256:38: error: 'struct IRCode::<anonymous>' has no member named 'type'
    IRSendRec.ino: In function 'bool storeRCCode(byte)':
    IRSendRec.ino:300:30: error: 'struct IRCode::<anonymous>' has no member named 'type'
    IRSendRec.ino:302:49: error: 'class decode_results' has no member named 'address'
    IRSendRec.ino: In function 'void sendRCCode(byte)':
    IRSendRec.ino:322:39: error: 'struct IRCode::<anonymous>' has no member named 'type'
    IRSendRec.ino:84:38: note: in definition of macro 'Type2String'
    IRSendRec.ino:322:39: error: 'struct IRCode::<anonymous>' has no member named 'type'
    IRSendRec.ino:84:50: note: in definition of macro 'Type2String'
    IRSendRec.ino:323:18: error: 'struct IRCode::<anonymous>' has no member named 'type'
    IRSendRec.ino:328:10: error: 'irsend' was not declared in this scope
    IRSendRec.ino:331:24: error: 'struct IRCode::<anonymous>' has no member named 'type'
    IRSendRec.ino:338:10: error: 'irsend' was not declared in this scope
    IRSendRec.ino:341:23: error: 'struct IRCode::<anonymous>' has no member named 'type'
    IRSendRec.ino:342:8: error: 'irsend' was not declared in this scope
    IRSendRec.ino:344:24: error: 'struct IRCode::<anonymous>' has no member named 'type'
    IRSendRec.ino:345:8: error: 'irsend' was not declared in this scope
    IRSendRec.ino:347:24: error: 'struct IRCode::<anonymous>' has no member named 'type'
    IRSendRec.ino:348:8: error: 'irsend' was not declared in this scope
    IRSendRec.ino:352:24: error: 'struct IRCode::<anonymous>' has no member named 'type'
    IRSendRec.ino:353:8: error: 'irsend' was not declared in this scope
    IRSendRec.ino:355:24: error: 'struct IRCode::<anonymous>' has no member named 'type'
    IRSendRec.ino:355:32: error: 'SAMSUNG' was not declared in this scope
    IRSendRec.ino:356:8: error: 'irsend' was not declared in this scope
    IRSendRec.ino:358:24: error: 'struct IRCode::<anonymous>' has no member named 'type'
    IRSendRec.ino:358:32: error: 'WHYNTER' was not declared in this scope
    IRSendRec.ino:359:8: error: 'irsend' was not declared in this scope
    IRSendRec.ino:361:24: error: 'struct IRCode::<anonymous>' has no member named 'type'
    IRSendRec.ino:361:32: error: 'AIWA_RC_T501' was not declared in this scope
    IRSendRec.ino:362:8: error: 'irsend' was not declared in this scope
    IRSendRec.ino:364:24: error: 'struct IRCode::<anonymous>' has no member named 'type'
    IRSendRec.ino:364:32: error: 'LG' was not declared in this scope
    IRSendRec.ino:364:48: error: 'struct IRCode::<anonymous>' has no member named 'type'
    IRSendRec.ino:364:75: error: 'struct IRCode::<anonymous>' has no member named 'type'
    IRSendRec.ino:368:24: error: 'struct IRCode::<anonymous>' has no member named 'type'
    IRSendRec.ino:372:12: error: 'irsend' was not declared in this scope
    IRSendRec.ino:375:24: error: 'struct IRCode::<anonymous>' has no member named 'type'
    IRSendRec.ino:376:8: error: 'irsend' was not declared in this scope
    IRSendRec.ino:380:24: error: 'struct IRCode::<anonymous>' has no member named 'type'
    IRSendRec.ino:380:32: error: 'DENON' was not declared in this scope
    IRSendRec.ino:381:8: error: 'irsend' was not declared in this scope
    IRSendRec.ino: In function 'void dump(decode_results*)':
    IRSendRec.ino:403:29: error: 'class decode_results' has no member named 'address'
    'decode_type_t' does not name a type


  • Mod

    @Newzwaver see @pete1450's post above (5 posts above yours).


  • Hero Member

    Trying to compile the Infrared Sender and Receiver sketch to be used on a WeMos D1 Mini Pro (ESP8266) but I get the following error:

    Seems like the saving/reading to/from Eeprom is handled differently when it comes to ESP8266.
    So what do I need to change in order to get the sketch to compile?

    Sketch:

    /**
     * The MySensors Arduino library handles the wireless radio link and protocol
     * between your home built sensors/actuators and HA controller of choice.
     * The sensors forms a self healing radio network with optional repeaters. Each
     * repeater and gateway builds a routing tables in EEPROM which keeps track of the
     * network topology allowing messages to be routed to nodes.
     *
     * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
     * Copyright (C) 2013-2015 Sensnology AB
     * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
     *
     * Documentation: http://www.mysensors.org
     * Support Forum: http://forum.mysensors.org
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * version 2 as published by the Free Software Foundation.
     *
     *******************************
     *
     * REVISION HISTORY
     * Version 1.0 - Changed for MySensors usage by Bart Eversdijk
     * Version 1.1 - Added option to record manual presets up to 240
     * Version 2.0 - Migrated to MySensrors version 2.0
     * 
     * DESCRIPTION
     *
     * IRrecord: record and play back IR signals as a minimal 
     * An IR detector/demodulator must be connected to the input RECV_PIN.
     * An IR LED must be connected to the output PWM pin 3.
     *
     *
     * The logic is:
     * If a V_IR_RECORD is received the node enters in record mode and once a valid IR message has been received 
     * it is stored in EEPROM. The first byte of the V_IR_RECORD message will be used as preset ID 
     * 
     * If a V_IR_SEND the IR message beloning to the preset number of the first message byte is broadcasted
     *
     *
     * Version 0.11 September, 2009
     * Copyright 2009 Ken Shirriff
     * http://arcfn.com
     */
    
    // Enable debug prints
    #define MY_DEBUG
    
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    
    #define MY_NODE_ID      5
    
    #include <SPI.h>
    #include <MySensors.h>
    
    //#include <IRremote.h>  // https://github.com/z3t0/Arduino-IRremote/releases   
    // OR install IRRemote via "Sketch" -> "Include Library" -> "Manage Labraries..."
    // Search for IRRemote b shirif and press the install button
    
    #include <IRremoteESP8266.h>  // From https://github.com/markszabo/IRremoteESP8266/
    #include <IRsend.h>  // Needed if you want to send IR commands.
    #include <IRrecv.h>  // Needed if you want to receive IR commands.
    #include <IRutils.h>
    
    // Define IR pins
    uint16_t SEND_PIN = D1; //an IR LED is connected to D1
    uint16_t RECV_PIN = D4; //an IR detector/demodulator is connected to D4
    
    // Arduino pin to connect the IR receiver to
    //int RECV_PIN     = 8;
    //int SEND_PIN     = 3;
    
    #define CHILD_ID  2  
    
    #define MY_RAWBUF  50
    const char * TYPE2STRING[] = {
        "UNKONWN",
        "RC5",
        "RC6",
        "NEC",
        "Sony",
        "Panasonic",
        "JVC",
        "SAMSUNG",
        "Whynter",
        "AIWA RC T501",
        "LG",
        "Sanyo",
        "Mitsubishi",
        "Dish",
        "Sharp",
        "Denon"
    };
    #define Type2String(x)   TYPE2STRING[x < 0 ? 0 : x]
    #define AddrTxt          F(" addres: 0x")
    #define ValueTxt         F(" value: 0x")
    #define NATxt            F(" - not implemented/found")
    
    // Raw or unknown codes requires an Arduino with a larger memory like a MEGA and some changes to store in EEPROM (now max 255 bytes)
    // #define IR_SUPPORT_UNKNOWN_CODES
    typedef union
    {
      struct
      {
        decode_type_t type;            // The type of code
        uint32_t      value;           // The data bits if type is not raw
        uint8_t      len;             // The length of the code in bits
        uint8_t      address;         // Used by Panasonic & Sharp [16-bits]
      } code;
    #ifdef IR_SUPPORT_UNKNOWN_CODES      
      struct
      {
        decode_type_t type;             // The type of code
        uint16_t  codes[MY_RAWBUF];
        byte          count;           // The number of interval samples
      } raw;
    #endif
    } IRCode;
    
    #define           MAX_STORED_IR_CODES     10
    IRCode            StoredIRCodes[MAX_STORED_IR_CODES];
    
    IRrecv            irrecv(RECV_PIN);
    IRsend            irsend(SEND_PIN);
    decode_results    ircode;
    
    #define           NO_PROG_MODE 0xFF
    byte              progModeId       = NO_PROG_MODE;
    
    // Manual Preset IR values -- these are working demo values
    // VERA call: luup.call_action("urn:schemas-arduino-cc:serviceId:ArduinoIr1", "SendIrCode", {Index=15}, <device number>)
    // One can add up to 240 preset codes (if your memory lasts) to see to correct data connect the Arduino with this plug in and
    // look at the serial monitor while pressing the desired RC button
    IRCode PresetIRCodes[] = {
        { { RC5, 0x01,       12, 0 }},  // 11 - RC5 key "1" 
        { { RC5, 0x02,       12, 0 }},  // 12 - RC5 key "2"
        { { RC5, 0x03,       12, 0 }},  // 13 - RC5 key "3"
        { { NEC, 0xFF30CF,   32, 0 }},  // 14 - NEC key "1"
        { { NEC, 0xFF18E7,   32, 0 }},  // 15 - NEC key "2"
        { { NEC, 0xFF7A85,   32, 0 }},  // 16 - NEC key "3"
        { { NEC, 0xFF10EF,   32, 0 }},  // 17 - NEC key "4"
        { { NEC, 0xFF38C7,   32, 0 }},  // 18 - NEC key "5"
        { { RC6, 0x800F2401, 36, 0 }},  // 19 - RC6 key "1" MicroSoft Mulitmedia RC
        { { RC6, 0x800F2402, 36, 0 }}   // 20 - RC6 key "2" MicroSoft Mulitmedia RC
    };
    #define MAX_PRESET_IR_CODES  (sizeof(PresetIRCodes)/sizeof(IRCode))
    #define MAX_IR_CODES (MAX_STORED_IR_CODES + MAX_PRESET_IR_CODES)
    
    MyMessage msgIrReceive(CHILD_ID, V_IR_RECEIVE);
    MyMessage msgIrRecord(CHILD_ID, V_IR_RECORD); 
    
    void setup()  
    {  
      // Tell MYS Controller that we're NOT recording
      send(msgIrRecord.set(0));
      
      Serial.println(F("Recall EEPROM settings"));
      recallEeprom(sizeof(StoredIRCodes), (byte *)&StoredIRCodes);
    
      // Start the ir receiver
      irrecv.enableIRIn(); 
      
      Serial.println(F("Init done..."));
    }
    
    void presentation () 
    {
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("IR Rec/Playback", "2.0");
    
      // Register a sensors to gw. Use binary light for test purposes.
      present(CHILD_ID, S_IR);
    }
    
    void loop() 
    {
      if (irrecv.decode(&ircode)) {
          dump(&ircode);
          if (progModeId != NO_PROG_MODE) {
             // If we are in PROG mode (Recording) store the new IR code and end PROG mode
             if (storeRCCode(progModeId)) {
                Serial.println(F("Stored "));
              
                // If sucessfull RC decode and storage --> also update the EEPROM
                storeEeprom(sizeof(StoredIRCodes), (byte *)&StoredIRCodes);
                progModeId = NO_PROG_MODE;
               
                // Tell MYS Controller that we're done recording
                send(msgIrRecord.set(0));
             }
          } else {
             // If we are in Playback mode just tell the MYS Controller we did receive an IR code
             if (ircode.decode_type != UNKNOWN) {
                 if (ircode.value != REPEAT) {
                   // Look if we found a stored preset 0 => not found
                   byte num = lookUpPresetCode(&ircode);
                   if (num) {
                       // Send IR decode result to the MYS Controller
                       Serial.print(F("Found code for preset #"));
                       Serial.println(num);
                       send(msgIrReceive.set(num));
                   }
                 }
             }
        }
        // Wait a while before receive next IR-code (also block MySensors receiver so it will not interfere with a new message)
        delay(500);
        
        // Start receiving again
        irrecv.resume();
      }
    }
    
    void receive(const MyMessage &message) {
        //Serial.print(F("New message: "));
        //Serial.println(message.type);
       
       if (message.type == V_IR_RECORD) { // IR_RECORD V_VAR1
          // Get IR record requets for index : paramvalue
          progModeId = message.getByte() % MAX_STORED_IR_CODES;
          
          // Tell MYS Controller that we're now in recording mode
          send(msgIrRecord.set(1));
          
          Serial.print(F("Record new IR for: "));
          Serial.println(progModeId);
       }
      
       if (message.type == V_IR_SEND) {
          // Send an IR code from offset: paramvalue - no check for legal value
          Serial.print(F("Send IR preset: "));
          byte code = message.getByte() % MAX_IR_CODES;
          if (code == 0) {
            code = MAX_IR_CODES;
          }
          Serial.print(code);
          sendRCCode(code);
       }
    
       // Start receiving ir again...
       irrecv.enableIRIn(); 
    }
    
    
    byte lookUpPresetCode (decode_results *ircode)
    {
        // Get rit of the RC5/6 toggle bit when looking up
        if (ircode->decode_type == RC5)  {
            ircode->value = ircode->value & 0x7FF;
        }
        if (ircode->decode_type == RC6)  {
            ircode->value = ircode->value & 0xFFFF7FFF;
        }
        for (byte index = 0; index < MAX_STORED_IR_CODES; index++)
        {
          if ( StoredIRCodes[index].code.type  == ircode->decode_type &&
               StoredIRCodes[index].code.value == ircode->value       &&
               StoredIRCodes[index].code.len   == ircode->bits)      {
              // The preset number starts with 1 so the last is stored as 0 -> fix this when looking up the correct index
              return (index == 0) ? MAX_STORED_IR_CODES : index;
          }  
        }
        
        for (byte index = 0; index < MAX_PRESET_IR_CODES; index++)
        {
          if ( PresetIRCodes[index].code.type  == ircode->decode_type &&
               PresetIRCodes[index].code.value == ircode->value       &&
               PresetIRCodes[index].code.len   == ircode->bits)      {
              // The preset number starts with 1 so the last is stored as 0 -> fix this when looking up the correct index
              return ((index == 0) ? MAX_PRESET_IR_CODES : index) + MAX_STORED_IR_CODES;
          }  
        }
        // not found so return 0
        return 0;
    }
        
    // Stores the code for later playback
    bool storeRCCode(byte index) {
    
      if (ircode.decode_type == UNKNOWN) {
    #ifdef IR_SUPPORT_UNKNOWN_CODES  
          Serial.println(F("Received unknown code, saving as raw"));
          // To store raw codes:
          // Drop first value (gap)
          // As of v1.3 of IRLib global values are already in microseconds rather than ticks
          // They have also been adjusted for overreporting/underreporting of marks and spaces
          byte rawCount = min(ircode.rawlen - 1, MY_RAWBUF);
          for (int i = 1; i <= rawCount; i++) {
            StoredIRCodes[index].raw.codes[i - 1] = ircode.rawbuf[i]; // Drop the first value
          };
          return true;
    #else 
          return false;
        }
    #endif
    
       if (ircode.value == REPEAT) {
           // Don't record a NEC repeat value as that's useless.
           Serial.println(F("repeat; ignoring."));
           return false;
       }
       // Get rit of the toggle bit when storing RC5/6 
       if (ircode.decode_type == RC5)  {
            ircode.value = ircode.value & 0x07FF;
       }
       if (ircode.decode_type == RC6)  {
            ircode.value = ircode.value & 0xFFFF7FFF;
       }
    
       StoredIRCodes[index].code.type      = ircode.decode_type;
       StoredIRCodes[index].code.value     = ircode.value;
       StoredIRCodes[index].code.address   = ircode.address;      // Used by Panasonic & Sharp [16-bits]
       StoredIRCodes[index].code.len       = ircode.bits;
       Serial.print(F(" value: 0x"));
       //Serial.println(ircode.value, HEX);
       return true;
    }
    
    void sendRCCode(byte index) {
       IRCode *pIr = ((index <= MAX_STORED_IR_CODES) ? &StoredIRCodes[index % MAX_STORED_IR_CODES] : &PresetIRCodes[index - MAX_STORED_IR_CODES - 1]);
       
    #ifdef IR_SUPPORT_UNKNOWN_CODES  
       if(pIr->code.type == UNKNOWN) {
          // Assume 38 KHz
          irsend.sendRaw(pIr->raw.codes, pIr->raw.count, 38);
          Serial.println(F("Sent raw"));
          return;
       }
    #endif
    
       Serial.print(F(" - sent "));
       Serial.print(Type2String(pIr->code.type));
       if (pIr->code.type == RC5) {
           // For RC5 and RC6 there is a toggle bit for each succesor IR code sent alway toggle this bit, needs to repeat the command 3 times with 100 mS pause
           pIr->code.value ^= 0x0800;
           for (byte i=0; i < 3; i++) {
             if (i > 0) { delay(100); } 
             irsend.sendRC5(pIr->code.value, pIr->code.len);
           }
        } 
        else if (pIr->code.type == RC6) {
           // For RC5 and RC6 there is a toggle bit for each succesor IR code sent alway toggle this bit, needs to repeat the command 3 times with 100 mS pause
           if (pIr->code.len == 20) {
                  pIr->code.value ^= 0x10000;
           }
           for (byte i=0; i < 3; i++) {
             if (i > 0) { delay(100); } 
             irsend.sendRC6(pIr->code.value, pIr->code.len);
           }
       }
       else if (pIr->code.type == NEC) {
           irsend.sendNEC(pIr->code.value, pIr->code.len);
        } 
        else if (pIr->code.type == SONY) {
           irsend.sendSony(pIr->code.value, pIr->code.len);
        } 
        else if (pIr->code.type == PANASONIC) {
           irsend.sendPanasonic(pIr->code.address, pIr->code.value);
           Serial.print(AddrTxt);
           Serial.println(pIr->code.address, HEX);
        }
        else if (pIr->code.type == JVC) {
           irsend.sendJVC(pIr->code.value, pIr->code.len, false);
        }
        else if (pIr->code.type == SAMSUNG) {
           irsend.sendSAMSUNG(pIr->code.value, pIr->code.len);
        }
        else if (pIr->code.type == WHYNTER) {
           irsend.sendWhynter(pIr->code.value, pIr->code.len);
        }
        else if (pIr->code.type == AIWA_RC_T501) {
           irsend.sendAiwaRCT501(pIr->code.value);
        }
        else if (pIr->code.type == LG || pIr->code.type == SANYO || pIr->code.type == MITSUBISHI) {
           Serial.println(NATxt);
           return;
        }
        else if (pIr->code.type == DISH) {
          // need to repeat the command 4 times with 100 mS pause
          for (byte i=0; i < 4; i++) {
             if (i > 0) { delay(100); } 
               irsend.sendDISH(pIr->code.value, pIr->code.len);
          }
        }
        else if (pIr->code.type == SHARP) {
           irsend.sendSharp(pIr->code.address, pIr->code.value);
           Serial.print(AddrTxt);
           Serial.println(pIr->code.address, HEX);
        }
        else if (pIr->code.type == DENON) {
           irsend.sendDenon(pIr->code.value, pIr->code.len);
        }
        else {
          // No valid IR type, found it does not make sense to broadcast
          Serial.println(NATxt);
          return; 
        }
        Serial.print(" ");
        Serial.println(pIr->code.value, HEX);
    }    
    
    // Dumps out the decode_results structure.
    void dump(decode_results *results) {
        int count = results->rawlen;
        
        Serial.print(F("Received : "));
        Serial.print(results->decode_type, DEC);
        Serial.print(F(" "));
        Serial.print(Type2String(results->decode_type));
      
        if (results->decode_type == PANASONIC) {  
          Serial.print(AddrTxt);
          Serial.print(results->address,HEX);
          Serial.print(ValueTxt);
        }
        Serial.print(F(" "));
        //Serial.print(results->value, HEX);
        Serial.print(F(" ("));
        Serial.print(results->bits, DEC);
        Serial.println(F(" bits)"));
      
        if (results->decode_type == UNKNOWN) {
          Serial.print(F("Raw ("));
          Serial.print(count, DEC);
          Serial.print(F("): "));
      
          for (int i = 0; i < count; i++) {
            if ((i % 2) == 1) {
              Serial.print(results->rawbuf[i]*USECPERTICK, DEC);
            } 
            else {
              Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC);
            }
            Serial.print(" ");
          }
          Serial.println("");
        }
    }
    
    // Store IR record struct in EEPROM   
    void storeEeprom(byte len, byte *buf)
    {
        saveState(0, len);
        for (byte i = 1; i < min(len, 100); i++, buf++)
        {
           saveState(i, *buf);
        }
    }
    
    void recallEeprom(byte len, byte *buf)
    {
        if (loadState(0) != len)
        {
           Serial.print(F("Corrupt EEPROM preset values and Clear EEPROM"));
           for (byte i = 1; i < min(len, 100); i++, buf++)
           {
               *buf = 0;
               storeEeprom(len, buf);
           }
           return;
        }
        for (byte i = 1; i < min(len, 100); i++, buf++)
        {
           *buf = loadState(i);
        }
    }
    

    Error:

    C:\Users\Tomas\Documents\Arduino\WeMosIRRemote\WeMosIRRemote.ino: In function 'void storeEeprom(byte, byte*)':
    
    WeMosIRRemote:444: error: 'min' was not declared in this scope
    
         for (byte i = 1; i < min(len, 100); i++, buf++)
    
                                          ^
    
    C:\Users\Tomas\Documents\Arduino\WeMosIRRemote\WeMosIRRemote.ino:444:38: note: suggested alternative:
    
    In file included from c:\users\tomas\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\bits\char_traits.h:39:0,
    
                     from c:\users\tomas\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\string:40,
    
                     from c:\users\tomas\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\stdexcept:39,
    
                     from c:\users\tomas\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\array:38,
    
                     from c:\users\tomas\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\tuple:39,
    
                     from c:\users\tomas\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\functional:55,
    
                     from C:\Users\Tomas\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/Schedule.h:4,
    
                     from C:\Users\Tomas\Documents\Arduino\libraries\MySensors/core/MyMainESP8266.cpp:22,
    
                     from C:\Users\Tomas\Documents\Arduino\libraries\MySensors/MySensors.h:340,
    
                     from C:\Users\Tomas\Documents\Arduino\WeMosIRRemote\WeMosIRRemote.ino:54:
    
    c:\users\tomas\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\bits\stl_algobase.h:239:5: note:   'std::min'
    
         min(const _Tp& __a, const _Tp& __b, _Compare __comp)
    
         ^
    
    C:\Users\Tomas\Documents\Arduino\WeMosIRRemote\WeMosIRRemote.ino: In function 'void recallEeprom(byte, byte*)':
    
    WeMosIRRemote:455: error: 'min' was not declared in this scope
    
            for (byte i = 1; i < min(len, 100); i++, buf++)
    
                                             ^
    
    C:\Users\Tomas\Documents\Arduino\WeMosIRRemote\WeMosIRRemote.ino:455:41: note: suggested alternative:
    
    In file included from c:\users\tomas\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\bits\char_traits.h:39:0,
    
                     from c:\users\tomas\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\string:40,
    
                     from c:\users\tomas\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\stdexcept:39,
    
                     from c:\users\tomas\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\array:38,
    
                     from c:\users\tomas\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\tuple:39,
    
                     from c:\users\tomas\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\functional:55,
    
                     from C:\Users\Tomas\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/Schedule.h:4,
    
                     from C:\Users\Tomas\Documents\Arduino\libraries\MySensors/core/MyMainESP8266.cpp:22,
    
                     from C:\Users\Tomas\Documents\Arduino\libraries\MySensors/MySensors.h:340,
    
                     from C:\Users\Tomas\Documents\Arduino\WeMosIRRemote\WeMosIRRemote.ino:54:
    
    c:\users\tomas\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\bits\stl_algobase.h:239:5: note:   'std::min'
    
         min(const _Tp& __a, const _Tp& __b, _Compare __comp)
    
         ^
    
    WeMosIRRemote:462: error: 'min' was not declared in this scope
    
         for (byte i = 1; i < min(len, 100); i++, buf++)
    
                                          ^
    
    C:\Users\Tomas\Documents\Arduino\WeMosIRRemote\WeMosIRRemote.ino:462:38: note: suggested alternative:
    
    In file included from c:\users\tomas\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\bits\char_traits.h:39:0,
    
                     from c:\users\tomas\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\string:40,
    
                     from c:\users\tomas\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\stdexcept:39,
    
                     from c:\users\tomas\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\array:38,
    
                     from c:\users\tomas\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\tuple:39,
    
                     from c:\users\tomas\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\functional:55,
    
                     from C:\Users\Tomas\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/Schedule.h:4,
    
                     from C:\Users\Tomas\Documents\Arduino\libraries\MySensors/core/MyMainESP8266.cpp:22,
    
                     from C:\Users\Tomas\Documents\Arduino\libraries\MySensors/MySensors.h:340,
    
                     from C:\Users\Tomas\Documents\Arduino\WeMosIRRemote\WeMosIRRemote.ino:54:
    
    c:\users\tomas\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\bits\stl_algobase.h:239:5: note:   'std::min'
    
         min(const _Tp& __a, const _Tp& __b, _Compare __comp)
    
         ^
    
    exit status 1
    'min' was not declared in this scope
    
    


  • This sketch does't work. I have tried it with arduino nano and arduino mega. It works only as a ir reader with monitor.



  • In this code domoticz says that there is a problem with presenting the child. I have change the code in order to present it properly in domoticz.
    //MyMessage msgIrReceive(CHILD_ID, V_IR_RECEIVE);
    //MyMessage msgIrRecord(CHILD_ID, V_IR_RECORD);
    MyMessage msgIrReceive(CHILD_ID, S_IR);
    MyMessage msgIrRecord(CHILD_ID, S_IR);

    All dependencys of V_IR_RECEIVE and V_IR_RECORD should also be changed. Just search the code for V_IR_RECEIVE and V_IR_RECORD, then replace it with S_IR.



  • I am having trouble doing IRSensor with domoticz.
    After pouring the scketch into the arduino, saved my codes and
    to check that it worked well with MYSController, here's what
    I obey when I activate the device under Domoticz:

    "error sending command to the switch, please verify device/hardware"

    My material in place:
    Domoticz V. 3.8153 sur Raspberry PI 3
    Gateway USB MySensor V. 2.1.1 on Arduino Nano
    IRSensor V. 2.0.0 on Arduino Nano

    For information in the domoticz log:

    -The node is well detected

    2017-12-28 09:07:12.553 MySensors: Node: 7, Sketch Name: IR Rec/Playback
    2017-12-28 09:07:12.554 MySensors: Node: 7, Sketch Version: 2.0

    -When I send a pre-recorded order with the remote control

    2017-12-28 09:07:59.346 (MySensor) Light/Switch (IR Command)

    -When I activate the device in Domoticz

    2017-12-28 09:08:29.835 User: Admin initiated a switch command (149/IR Command/Off)
    2017-12-28 09:08:29.836 Error: MySensors: Light command received for unknown node_id: 6

    Someone would have any idea?

    Thanks for your help.

    Mash

    sorry for my English


  • Mod

    @mash please don't post the same question in multiple places. Posting in multiple places will divide the discussion, causing people to waste their time.

    If anyone has any ideas on how to help @mash, do not reply here. Reply in https://forum.mysensors.org/topic/8793/problem-with-irsensor-and-domoticz instead.



  • sorry, forgave me I would not do it again



  • Hello
    Using the example sketch from the main thread, I managed to program a few pilot buttons in the domotic. (IR codes are of course entered in the section: IRCode PresetIRCodes [] = (...).
    I would, however, "upload" a few IR codes to Domoticz, which would control my TV and AV via the IR diode from the Domoticz level.

    In this example, there is the sendRCCode () function, which, in theory, sends an IR code (previously uploaded to Domoticz) via IR diode, if of course it will get
    message.type == V_IR_SEND.

    I added an additional declaration:
    MyMessage msgIrSend (CHILD_ID, V_IR_SEND);
    but in Domoticz there was no additional Device that would be responsible for sending IR codes.
    I think I probably need to do an additional Dummy Switch, which will send an IR signal transmission command to the gateway / node using JSON.
    I'm thinking about it for a long time and I have no idea how to do it in DOMOTICZ.
    Please help me how to do it.



  • Hi All, has anyone had any success porting this IR sketch example to work with the IRremoteESP8266 library? I am not getting much further than @korttoma.

    Thanks CV8R.



  • Hi everyone I am trying to setup a node to control my A/C unit and am having some trouble.

    I am using these libraries
    MySensors at version 2.3.2
    IRremote at version 2.2.3

    My hardware is
    Arduino mega 2560
    Nrf24

    The problem is if i press a button on the remote i get this on the console

    Received : -1 UNKONWN B5E9B811 (32 bits)
    Raw (38): -17746 8350 -4250 500 -1600 550 -1550 550 -1550 550 -500 450 -1650 550 -600 500 -1550 500 -1550 600 -4100 550 -1550 600 -1500 500 -550 600 -1500 550 -550 550 -500 550 -500 550 -500 650
    

    So i uncommitted this

    // Raw or unknown codes requires an Arduino with a larger memory like a MEGA and some changes to store in EEPROM (now max 255 bytes)
    // #define IR_SUPPORT_UNKNOWN_CODES
    

    to this

    // Raw or unknown codes requires an Arduino with a larger memory like a MEGA and some changes to store in EEPROM (now max 255 bytes)
     #define IR_SUPPORT_UNKNOWN_CODES
    

    but now if i compile the code i get this error

    exit status 1
    'recallEeprom' was not declared in this scope
    

    this is the full sketch

    // Enable debug prints
    #define MY_DEBUG
    
    // Enable and select radio type attached
    #define MY_RADIO_RF24
    
    #define MY_RF24_DATARATE RF24_1MBPS
    #define MY_RF24_PA_LEVEL RF24_PA_MAX
    
    #define MY_RF24_CE_PIN 9
    #define MY_RF24_CS_PIN 10
    
    #define MY_NODE_ID      5
    
    #include <SPI.h>
    #include <MySensors.h>
    
    #include <IRremote.h>  // https://github.com/z3t0/Arduino-IRremote/releases   
    // OR install IRRemote via "Sketch" -> "Include Library" -> "Manage Labraries..."
    // Search for IRRemote b shirif and press the install button
    
    // Arduino pin to connect the IR receiver to
    int RECV_PIN     = 8;
    
    #define CHILD_ID  2  
    
    #define MY_RAWBUF  50
    const char * TYPE2STRING[] = {
    		"UNKONWN",
    		"RC5",
    		"RC6",
    		"NEC",
    		"Sony",
    		"Panasonic",
    		"JVC",
    		"SAMSUNG",
    		"Whynter",
    		"AIWA RC T501",
    		"LG",
    		"Sanyo",
    		"Mitsubishi",
    		"Dish",
    		"Sharp",
    		"Denon"
    };
    #define Type2String(x)   TYPE2STRING[x < 0 ? 0 : x]
    #define AddrTxt          F(" addres: 0x")
    #define ValueTxt         F(" value: 0x")
    #define NATxt            F(" - not implemented/found")
    
    // Raw or unknown codes requires an Arduino with a larger memory like a MEGA and some changes to store in EEPROM (now max 255 bytes)
     #define IR_SUPPORT_UNKNOWN_CODES
    typedef union
    {
      struct
      {
        decode_type_t type;            // The type of code
        unsigned long value;           // The data bits if type is not raw
        int           len;             // The length of the code in bits
        unsigned int  address;         // Used by Panasonic & Sharp [16-bits]
      } code;
    #ifdef IR_SUPPORT_UNKNOWN_CODES      
      struct
      {
        decode_type_t type;             // The type of code
        unsigned int  codes[MY_RAWBUF];
        byte          count;           // The number of interval samples
      } raw;
    #endif
    } IRCode;
    
    #define           MAX_STORED_IR_CODES     10
    IRCode            StoredIRCodes[MAX_STORED_IR_CODES];
    
    IRrecv            irrecv(RECV_PIN);
    IRsend            irsend;
    decode_results    ircode;
    
    #define           NO_PROG_MODE 0xFF
    byte              progModeId       = NO_PROG_MODE;
    
    // Manual Preset IR values -- these are working demo values
    // VERA call: luup.call_action("urn:schemas-arduino-cc:serviceId:ArduinoIr1", "SendIrCode", {Index=15}, <device number>)
    // One can add up to 240 preset codes (if your memory lasts) to see to correct data connect the Arduino with this plug in and
    // look at the serial monitor while pressing the desired RC button
    IRCode PresetIRCodes[] = {
        { { RC5, 0x01,       12, 0 }},  // 11 - RC5 key "1" 
        { { RC5, 0x02,       12, 0 }},  // 12 - RC5 key "2"
        { { RC5, 0x03,       12, 0 }},  // 13 - RC5 key "3"
        { { NEC, 0xFF30CF,   32, 0 }},  // 14 - NEC key "1"
        { { NEC, 0xFF18E7,   32, 0 }},  // 15 - NEC key "2"
        { { NEC, 0xFF7A85,   32, 0 }},  // 16 - NEC key "3"
        { { NEC, 0xFF10EF,   32, 0 }},  // 17 - NEC key "4"
        { { NEC, 0xFF38C7,   32, 0 }},  // 18 - NEC key "5"
        { { RC6, 0x800F2401, 36, 0 }},  // 19 - RC6 key "1" MicroSoft Mulitmedia RC
        { { RC6, 0x800F2402, 36, 0 }}   // 20 - RC6 key "2" MicroSoft Mulitmedia RC
    };
    #define MAX_PRESET_IR_CODES  (sizeof(PresetIRCodes)/sizeof(IRCode))
    #define MAX_IR_CODES (MAX_STORED_IR_CODES + MAX_PRESET_IR_CODES)
    
    MyMessage msgIrReceive(CHILD_ID, V_IR_RECEIVE);
    MyMessage msgIrRecord(CHILD_ID, V_IR_RECORD); 
    
    void setup()  
    {  
      // Tell MYS Controller that we're NOT recording
      send(msgIrRecord.set(0));
      
      Serial.println(F("Recall EEPROM settings"));
      recallEeprom(sizeof(StoredIRCodes), (byte *)&StoredIRCodes);
    
      // Start the ir receiver
      irrecv.enableIRIn(); 
      
      Serial.println(F("Init done..."));
    }
    
    void presentation () 
    {
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("IR Rec/Playback", "2.0");
    
      // Register a sensors to gw. Use binary light for test purposes.
      present(CHILD_ID, S_IR);
    }
    
    void loop() 
    {
      if (irrecv.decode(&ircode)) {
          dump(&ircode);
          if (progModeId != NO_PROG_MODE) {
             // If we are in PROG mode (Recording) store the new IR code and end PROG mode
             if (storeRCCode(progModeId)) {
                Serial.println(F("Stored "));
              
                // If sucessfull RC decode and storage --> also update the EEPROM
                storeEeprom(sizeof(StoredIRCodes), (byte *)&StoredIRCodes);
                progModeId = NO_PROG_MODE;
               
                // Tell MYS Controller that we're done recording
                send(msgIrRecord.set(0));
             }
          } else {
             // If we are in Playback mode just tell the MYS Controller we did receive an IR code
             if (ircode.decode_type != UNKNOWN) {
                 if (ircode.value != REPEAT) {
                   // Look if we found a stored preset 0 => not found
                   byte num = lookUpPresetCode(&ircode);
                   if (num) {
                       // Send IR decode result to the MYS Controller
                       Serial.print(F("Found code for preset #"));
                       Serial.println(num);
                       send(msgIrReceive.set(num));
                   }
                 }
             }
        }
        // Wait a while before receive next IR-code (also block MySensors receiver so it will not interfere with a new message)
        delay(500);
        
        // Start receiving again
        irrecv.resume();
      }
    }
    
    void receive(const MyMessage &message) {
        //Serial.print(F("New message: "));
        //Serial.println(message.type);
       
       if (message.type == V_IR_RECORD) { // IR_RECORD V_VAR1
          // Get IR record requets for index : paramvalue
          progModeId = message.getByte() % MAX_STORED_IR_CODES;
          
          // Tell MYS Controller that we're now in recording mode
          send(msgIrRecord.set(1));
          
          Serial.print(F("Record new IR for: "));
          Serial.println(progModeId);
       }
      
       if (message.type == V_IR_SEND) {
          // Send an IR code from offset: paramvalue - no check for legal value
          Serial.print(F("Send IR preset: "));
          byte code = message.getByte() % MAX_IR_CODES;
          if (code == 0) {
            code = MAX_IR_CODES;
          }
          Serial.print(code);
          sendRCCode(code);
       }
    
       // Start receiving ir again...
       irrecv.enableIRIn(); 
    }
    
    
    byte lookUpPresetCode (decode_results *ircode)
    {
        // Get rit of the RC5/6 toggle bit when looking up
        if (ircode->decode_type == RC5)  {
            ircode->value = ircode->value & 0x7FF;
        }
        if (ircode->decode_type == RC6)  {
            ircode->value = ircode->value & 0xFFFF7FFF;
        }
        for (byte index = 0; index < MAX_STORED_IR_CODES; index++)
        {
          if ( StoredIRCodes[index].code.type  == ircode->decode_type &&
               StoredIRCodes[index].code.value == ircode->value       &&
               StoredIRCodes[index].code.len   == ircode->bits)      {
              // The preset number starts with 1 so the last is stored as 0 -> fix this when looking up the correct index
              return (index == 0) ? MAX_STORED_IR_CODES : index;
          }  
        }
        
        for (byte index = 0; index < MAX_PRESET_IR_CODES; index++)
        {
          if ( PresetIRCodes[index].code.type  == ircode->decode_type &&
               PresetIRCodes[index].code.value == ircode->value       &&
               PresetIRCodes[index].code.len   == ircode->bits)      {
              // The preset number starts with 1 so the last is stored as 0 -> fix this when looking up the correct index
              return ((index == 0) ? MAX_PRESET_IR_CODES : index) + MAX_STORED_IR_CODES;
          }  
        }
        // not found so return 0
        return 0;
    }
        
    // Stores the code for later playback
    bool storeRCCode(byte index) {
    
      if (ircode.decode_type == UNKNOWN) {
    #ifdef IR_SUPPORT_UNKNOWN_CODES  
          Serial.println(F("Received unknown code, saving as raw"));
          // To store raw codes:
          // Drop first value (gap)
          // As of v1.3 of IRLib global values are already in microseconds rather than ticks
          // They have also been adjusted for overreporting/underreporting of marks and spaces
          byte rawCount = min(ircode.rawlen - 1, MY_RAWBUF);
          for (int i = 1; i <= rawCount; i++) {
            StoredIRCodes[index].raw.codes[i - 1] = ircode.rawbuf[i]; // Drop the first value
          };
          return true;
    #else 
          return false;
        }
    #endif
    
       if (ircode.value == REPEAT) {
           // Don't record a NEC repeat value as that's useless.
           Serial.println(F("repeat; ignoring."));
           return false;
       }
       // Get rit of the toggle bit when storing RC5/6 
       if (ircode.decode_type == RC5)  {
            ircode.value = ircode.value & 0x07FF;
       }
       if (ircode.decode_type == RC6)  {
            ircode.value = ircode.value & 0xFFFF7FFF;
       }
    
       StoredIRCodes[index].code.type      = ircode.decode_type;
       StoredIRCodes[index].code.value     = ircode.value;
       StoredIRCodes[index].code.address   = ircode.address;      // Used by Panasonic & Sharp [16-bits]
       StoredIRCodes[index].code.len       = ircode.bits;
       Serial.print(F(" value: 0x"));
       Serial.println(ircode.value, HEX);
       return true;
    }
    
    void sendRCCode(byte index) {
       IRCode *pIr = ((index <= MAX_STORED_IR_CODES) ? &StoredIRCodes[index % MAX_STORED_IR_CODES] : &PresetIRCodes[index - MAX_STORED_IR_CODES - 1]);
       
    #ifdef IR_SUPPORT_UNKNOWN_CODES  
       if(pIr->code.type == UNKNOWN) {
          // Assume 38 KHz
          irsend.sendRaw(pIr->raw.codes, pIr->raw.count, 38);
          Serial.println(F("Sent raw"));
          return;
       }
    #endif
    
       Serial.print(F(" - sent "));
       Serial.print(Type2String(pIr->code.type));
       if (pIr->code.type == RC5) {
           // For RC5 and RC6 there is a toggle bit for each succesor IR code sent alway toggle this bit, needs to repeat the command 3 times with 100 mS pause
           pIr->code.value ^= 0x0800;
           for (byte i=0; i < 3; i++) {
             if (i > 0) { delay(100); } 
             irsend.sendRC5(pIr->code.value, pIr->code.len);
           }
        } 
        else if (pIr->code.type == RC6) {
           // For RC5 and RC6 there is a toggle bit for each succesor IR code sent alway toggle this bit, needs to repeat the command 3 times with 100 mS pause
           if (pIr->code.len == 20) {
                  pIr->code.value ^= 0x10000;
           }
           for (byte i=0; i < 3; i++) {
             if (i > 0) { delay(100); } 
             irsend.sendRC6(pIr->code.value, pIr->code.len);
           }
       }
       else if (pIr->code.type == NEC) {
           irsend.sendNEC(pIr->code.value, pIr->code.len);
        } 
        else if (pIr->code.type == SONY) {
           irsend.sendSony(pIr->code.value, pIr->code.len);
        } 
        else if (pIr->code.type == PANASONIC) {
           irsend.sendPanasonic(pIr->code.address, pIr->code.value);
           Serial.print(AddrTxt);
           Serial.println(pIr->code.address, HEX);
        }
        else if (pIr->code.type == JVC) {
           irsend.sendJVC(pIr->code.value, pIr->code.len, false);
        }
        else if (pIr->code.type == SAMSUNG) {
           irsend.sendSAMSUNG(pIr->code.value, pIr->code.len);
        }
        else if (pIr->code.type == WHYNTER) {
           irsend.sendWhynter(pIr->code.value, pIr->code.len);
        }
        else if (pIr->code.type == AIWA_RC_T501) {
           irsend.sendAiwaRCT501(pIr->code.value);
        }
        else if (pIr->code.type == LG || pIr->code.type == SANYO || pIr->code.type == MITSUBISHI) {
           Serial.println(NATxt);
           return;
        }
        else if (pIr->code.type == DISH) {
          // need to repeat the command 4 times with 100 mS pause
          for (byte i=0; i < 4; i++) {
             if (i > 0) { delay(100); } 
               irsend.sendDISH(pIr->code.value, pIr->code.len);
          }
        }
        else if (pIr->code.type == SHARP) {
           irsend.sendSharp(pIr->code.address, pIr->code.value);
           Serial.print(AddrTxt);
           Serial.println(pIr->code.address, HEX);
        }
        else if (pIr->code.type == DENON) {
           irsend.sendDenon(pIr->code.value, pIr->code.len);
        }
        else {
          // No valid IR type, found it does not make sense to broadcast
          Serial.println(NATxt);
          return; 
        }
        Serial.print(" ");
        Serial.println(pIr->code.value, HEX);
    }    
    
    // Dumps out the decode_results structure.
    void dump(decode_results *results) {
        int count = results->rawlen;
        
        Serial.print(F("Received : "));
        Serial.print(results->decode_type, DEC);
        Serial.print(F(" "));
        Serial.print(Type2String(results->decode_type));
      
        if (results->decode_type == PANASONIC) {	
          Serial.print(AddrTxt);
          Serial.print(results->address,HEX);
          Serial.print(ValueTxt);
        }
        Serial.print(F(" "));
        Serial.print(results->value, HEX);
        Serial.print(F(" ("));
        Serial.print(results->bits, DEC);
        Serial.println(F(" bits)"));
      
        if (results->decode_type == UNKNOWN) {
          Serial.print(F("Raw ("));
          Serial.print(count, DEC);
          Serial.print(F("): "));
      
          for (int i = 0; i < count; i++) {
            if ((i % 2) == 1) {
              Serial.print(results->rawbuf[i]*USECPERTICK, DEC);
            } 
            else {
              Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC);
            }
            Serial.print(" ");
          }
          Serial.println("");
        }
    }
    
    // Store IR record struct in EEPROM   
    void storeEeprom(byte len, byte *buf)
    {
        saveState(0, len);
        for (byte i = 1; i < min(len, 100); i++, buf++)
        {
           saveState(i, *buf);
        }
    }
    
    void recallEeprom(byte len, byte *buf)
    {
        if (loadState(0) != len)
        {
           Serial.print(F("Corrupt EEPROM preset values and Clear EEPROM"));
           for (byte i = 1; i < min(len, 100); i++, buf++)
           {
               *buf = 0;
               storeEeprom(len, buf);
           }
           return;
        }
        for (byte i = 1; i < min(len, 100); i++, buf++)
        {
           *buf = loadState(i);
        }
    }
    

  • Mod

    @catchra in bool storeRCCode(byte index) you need to change

    #else
        return false;
      }
    #endif
    

    to

    #else
        return false;
    #endif
      }
    

    The clue was in the verification output:

    
    C:\Users\Micke\AppData\Local\Temp\arduino_modified_sketch_286541\sketch_may25a.ino: In function 'bool storeRCCode(byte)':
    
    sketch_may25a:271:31: error: a function-definition is not allowed here before '{' token
    
       void sendRCCode(byte index) {
    
                                   ^
    
    sketch_may25a:424:3: error: expected '}' at end of input
    
       }
    
       ^
    
    C:\Users\Micke\AppData\Local\Temp\arduino_modified_sketch_286541\sketch_may25a.ino:424:3: warning: control reaches end of non-void function [-Wreturn-type]
    
       }
    
       ^
    

    Also, pressing ctrl+t to auto-format the sketch can help a lot.



  • Following (I think) the instructions to the letter:

    • Using a Pro Mini
    • Installed the IRremote library (current version through Arduino Libraries Manager: 2.8.0)
    • Copied exactly the sample code

    When I come to compile, I get the following error:

    /home/pc/Arduino/IrSensor/IrSensor.ino: In function 'void sendRCCode(byte)':
    IrSensor:361:32: error: 'AIWA_RC_T501' was not declared in this scope
         else if (pIr->code.type == AIWA_RC_T501) {
                                    ^~~~~~~~~~~~
    IrSensor:362:15: error: 'class IRsend' has no member named 'sendAiwaRCT501'; did you mean 'sendRC5'?
            irsend.sendAiwaRCT501(pIr->code.value);
                   ^~~~~~~~~~~~~~
                   sendRC5
    IrSensor:364:83: error: 'MITSUBISHI' was not declared in this scope
         else if (pIr->code.type == LG || pIr->code.type == SANYO || pIr->code.type == MITSUBISHI) {
                                                                                       ^~~~~~~~~~
    /home/adams-pc/Arduino/IrSensor/IrSensor.ino: In function 'void dump(decode_results*)':
    IrSensor:419:43: error: 'USECPERTICK' was not declared in this scope
               Serial.print(results->rawbuf[i]*USECPERTICK, DEC);
                                               ^~~~~~~~~~~
    IrSensor:422:49: error: 'USECPERTICK' was not declared in this scope
               Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC);
                                                     ^~~~~~~~~~~
    exit status 1
    'AIWA_RC_T501' was not declared in this scope
    

    Am I missing something?



  • @bollarcreets, I am afraid that the script has never been adapted to the evolution of the IRRemote library.
    If you take library version 2.2.3, the script will compile.

    If you take the source code from the latest version 2.8.1 you will also see that the typedef enums AIWA_RC_T501 and MITSUBISHI are commented out.

    If you want to run this example script with the latest version of the library, you will need to analyse and understand the script in order to modify it...



  • @evb said in 💬 Infrared Sender and Receiver:

    If you take library version 2.2.3, the script will compile.

    That does indeed work - thanks!

    What's the best way to get the tutorial edited to include this information?


  • Mod

    @bollarcreets I've added a note in the instructions. Please let me know if you think it could be reworded or put someplace else to make it clearer.



  • @mfalkvidd thanks, that change is all that's needed I think. Thanks to you and @evb for the prompt help!


Log in to reply
 

Suggested Topics

  • 3
  • 347
  • 2
  • 584
  • 5
  • 164

1
Online

11.4k
Users

11.1k
Topics

112.7k
Posts