Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. Announcements
  3. 💬 Infrared Sender and Receiver

💬 Infrared Sender and Receiver

Scheduled Pinned Locked Moved Announcements
45 Posts 26 Posters 15.0k Views 26 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    Mash
    wrote on last edited by
    #36

    sorry, forgave me I would not do it again

    1 Reply Last reply
    1
    • C Offline
      C Offline
      czosnekltd
      wrote on last edited by
      #37

      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.

      1 Reply Last reply
      0
      • C Offline
        C Offline
        CV8R
        wrote on last edited by
        #38

        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.

        1 Reply Last reply
        0
        • C Offline
          C Offline
          catchra
          wrote on last edited by catchra
          #39

          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);
              }
          }
          
          mfalkviddM 1 Reply Last reply
          0
          • C catchra

            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);
                }
            }
            
            mfalkviddM Offline
            mfalkviddM Offline
            mfalkvidd
            Mod
            wrote on last edited by
            #40

            @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.

            1 Reply Last reply
            0
            • B Offline
              B Offline
              bollarcreets
              wrote on last edited by
              #41

              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?

              E 1 Reply Last reply
              0
              • B bollarcreets

                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?

                E Offline
                E Offline
                evb
                wrote on last edited by
                #42

                @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...

                B 1 Reply Last reply
                1
                • E evb

                  @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...

                  B Offline
                  B Offline
                  bollarcreets
                  wrote on last edited by
                  #43

                  @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?

                  mfalkviddM 1 Reply Last reply
                  0
                  • B bollarcreets

                    @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?

                    mfalkviddM Offline
                    mfalkviddM Offline
                    mfalkvidd
                    Mod
                    wrote on last edited by
                    #44

                    @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.

                    B 1 Reply Last reply
                    1
                    • mfalkviddM mfalkvidd

                      @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.

                      B Offline
                      B Offline
                      bollarcreets
                      wrote on last edited by
                      #45

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

                      1 Reply Last reply
                      1
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      20

                      Online

                      11.7k

                      Users

                      11.2k

                      Topics

                      113.0k

                      Posts


                      Copyright 2019 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • MySensors
                      • OpenHardware.io
                      • Categories
                      • Recent
                      • Tags
                      • Popular