IR Custom Remote

Hello, I am currently trying to make an IR remote for a Lasko space heater. I have used the current remote with an IR receiving arduino to display the Hex codes for the remote, however it appears It has an unrecognized protocol. I understand that I have to send the code in RAW form instead, but I am having trouble doing that. I have browsed similar threads on how to do this and still haven’t been able to get it to work. I used the IRremote library built in script to obtain the RAW codes for my remote which contained a 24 number array, but some of the values were negative (-400). When I copied this into the built in RAW transmitter I got an error when compiling the code with the negative signs. I removed them and the code compiled properly, but the remote wouldn’t turn on the device. Any suggestions for how to get around this?

Well, you start by posting the cost that doesn’t compile. Be sure to read how to properly do that:

http://forum.arduino.cc/index.php/topic,148850.0.html

Its not compiling properly because of the RAW codes I have inserted, I am confused about how to properly code for them. When I fix the error and it compiles properly then the remote doesn't properly turn on my device.

Use the IRrecvDumpV2 sketch to get the RAW data in source code form.

biglemon29:
Its not compiling properly because of the RAW codes I have inserted, I am confused about how to properly code for them. When I fix the error and it compiles properly then the remote doesn't properly turn on my device.

That's why you POST your code. So we can see it. And help you fix it. Is the concept really that difficult to grasp?

Here is code I used a for IR receiver that allowed me to obtain the RAW codes

#include <ir_Lego_PF_BitStreamEncoder.h>
#include <boarddefs.h>
#include <IRremoteInt.h>
#include <IRremote.h>

// If one keypress results in multiple codes being output, then
// change in IRremoteInt.h:
// #define _GAP 50000
// This sketchThis sketch was obtained from:
//  For more info:
//  jason welsh
//   https://www.youtube.com/watch?v=eR8sQq3pl20
//  https://docs.google.com/document/d/1QgmFbFlB0aI3swrhQkacRe3C-cIS0p1t0TV36-i2lLo/edit

//   http://www.instructables.com/id/Arduino-Remote-Control-Less-10/?ALLSTEPS
/////////////////////////////////
//  I made a few small changes

#include <IRremote.h>

int RECV_PIN = 9;
IRrecv irrecv(RECV_PIN);
decode_results results;

void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
}

int c = 0;

void dump(decode_results *results) {
  int count = results->rawlen;
  Serial.println(c);
  c++;
  Serial.println("For IR Scope: ");
  for (int i = 1; i < count; i++) {
   
    if ((i % 2) == 1) {
      Serial.print("+");
      Serial.print(results->rawbuf[i]*USECPERTICK, DEC);
    }
    else {
      Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC);
    }
    Serial.print(" ");
  }
  Serial.println("");
  Serial.println("For Arduino sketch: ");
  Serial.print("unsigned int raw");
  Serial.print(c);
   Serial.print("[");
  Serial.print(count, DEC);
  Serial.print("] = {");
  for (int i = 1; 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.print("};");
  Serial.println("");
  Serial.print("irsend.sendRaw(");
  Serial.print("raw");
  Serial.print(c);
  Serial.print(",");
  Serial.print(count, DEC);
  Serial.print(",38);");
  Serial.println("");
  Serial.println("");
}

void loop() {
  if (irrecv.decode(&results)) {
    dump(&results);
    irrecv.resume(); // Receive the next value
  }
}

This gave me these IR codes

unsigned int raw1[24] = {1300,400,1250,450,400,1300,1250,450,1250,450,400,1250,450,1250,450,1250,450,1250,450,1250,400,1300,1250,};

unsigned int raw2[24] = {1200,450,1250,450,400,1300,1250,450,1250,450,400,1250,450,1250,400,1300,400,1300,400,1300,400,1300,1250,};

unsigned int raw3[24] = {1250,450,1250,400,450,1250,1300,400,1300,400,400,1300,400,1300,400,1300,400,1250,450,1250,450,1250,1300,};

unsigned int raw4[24] = {1300,400,1300,400,450,1250,1250,450,1250,450,400,1300,400,1250,450,1250,450,1250,400,1300,400,1300,1250,};

Then I uploaded them to this IR sending sketch

/*
 * IRremote: IRsendDemo - demonstrates sending IR codes with IRsend
 * An IR LED must be connected to Arduino PWM pin 3.
 * Version 0.1 July, 2009
 * Copyright 2009 Ken Shirriff
 * http://arcfn.com
 */ //   http://www.instructables.com/id/Arduino-Remote-Control-Less-10/?ALLSTEPS

#include <IRremote.h>

#include <SoftwareSerial.h>

SoftwareSerial BT(10, 11); // TX, RX
String readdata;

IRsend irsend;  // An IR LED must be connected to Arduino PWM pin 3.
 //here put your raw code//

unsigned int raw1[24] = {1300,400,1250,450,400,1300,1250,450,1250,450,400,1250,450,1250,450,1250,450,1250,450,1250,400,1300,1250,};

unsigned int raw2[24] = {1200,450,1250,450,400,1300,1250,450,1250,450,400,1250,450,1250,400,1300,400,1300,400,1300,400,1300,1250,};

unsigned int raw3[24] = {1250,450,1250,400,450,1250,1300,400,1300,400,400,1300,400,1300,400,1300,400,1250,450,1250,450,1250,1300,};

unsigned int raw4[24] = {1300,400,1300,400,450,1250,1250,450,1250,450,400,1300,400,1250,450,1250,450,1250,400,1300,400,1300,1250,};




void setup()
{
  Serial.begin(9600);
   BT.begin(9600);
  
  
}



void loop() {
  

 
  while (BT.available() ) { //Check if there is an available byte to read
  delay(10); //Delay added to make thing stable
  char c = BT.read(); //Conduct aserial read
  readdata += c; //build the string "bật1" , "tắt1" , "bật2" , "tắt2 ".......
  }
  
  if (readdata.length()>0) {
    Serial.println(readdata);
/////////////////////////////////////////

  
     
     if(readdata=="1") {
    for (int i = 0; i < 1; i++) {
     irsend.sendRaw(raw1,24,38); delay(200); } 
     Serial.print("one");
     }


     if(readdata=="2") {
    for (int i = 0; i < 1; i++) {
     irsend.sendRaw(raw2,24,38); delay(200); } 
     Serial.print("two");
     }



     if(readdata=="3") {
    for (int i = 0; i < 1; i++) {
     irsend.sendRaw(raw3,24,38); delay(200); } 
     Serial.print("three");
     }


     if(readdata=="4") {
    for (int i = 0; i < 1; i++) {
     irsend.sendRaw(raw4,24,38); delay(200); } 
     Serial.print("four");
     }

     

     
      
     
     
    /* Example = irsend.sendRaw(raw,68,38); , If you unsigned int raw its different you need change irsendRaw line
    // irsend.sendRaw(PowerOn,68,38);  = unsigned int PowerOn[68] = {4600,4300.....
    // irsend.sendRaw(raw2,68,38);  = unsigned int raw2[68] = {4600,4300.....
    // irsend.sendRaw(PowerOn,68,38);  = unsigned int PowerOn[68] = {4600,4300.....  
      delay(40); */
   
        readdata=""; //Reset the variable
    }
    
}

When I try to send the RAW codes it doesn’t turn the heater on. I also understand that the IR sender must be attached to pin 3 but I am confused which part of the code dictates that? Those particular IR codes are to turn on the device. Is there anything I can edit in the code to make it function properly?

biglemon29:
I also understand that the IR sender must be attached to pin 3 but I am confused which part of the code dictates that?

The IRremote library uses Timer1 to generate the 38 kHz carrier frequency on Pin 3. I think SoftwareSerial is going to conflict with that by ALSO using Timer1. Try writing a sketch that does not use SoftwareSerial to see if the IRremote output works then.

Update: So I am positive the transmitter is working since my second arduino with a receiver code built in is detecting it perfectly. However, the transmitter will still not work properly to turn on the receiver on the heating unit. One thing I noticed is when I was capturing the codes from the remote, there were slight variations from each iteration I had recorded a button press. What steps can I take to have the transmitter pick it up properly?

biglemon29:
One thing I noticed is when I was capturing the codes from the remote, there were slight variations from each iteration

The IRremote library only samples the input every 50 microseconds (20 kHz). It is normal for the RAW numbers to vary between two values that differ by 50. A 'slight variation' like that should not bother the receiving device.
Some air conditioners use codes that are far longer than typical AV equipment and the IRremote library can't handle codes that long. Maybe your heater has a similar coding scheme. In IRremoteInt.h try making RAWBUF larger.

Thanks for the suggestion.

#define RAWBUF  101  // Maximum length of raw duration buffer

I edited this line to have values of 200, 300, 500, and 700. Each time I saved and recompiled the receiving sketch. Then I recaptured the RAW codes and tried transmitting again and It still didn't work. Any other suggestions on how I can get it to work?

I'm running out of ideas.

When you try controlling the heater, is the IR LED close to and point at the heater's receiver?

Actually I noticed something sort of strange. I tried using 2 different IR receiving sketches and I got 2 different sized arrays, one 23 bits and another 24

Here is the first sketch I used

//------------------------------------------------------------------------------
// Include the IRremote library header
//
#include <IRremote.h>

//------------------------------------------------------------------------------
// Tell IRremote which Arduino pin is connected to the IR Receiver (TSOP4838)
//
int recvPin = 11;
IRrecv irrecv(recvPin);

//+=============================================================================
// Configure the Arduino
//
void  setup ( )
{
  Serial.begin(9600);   // Status message will be sent to PC at 9600 baud
  irrecv.enableIRIn();  // Start the receiver
}

//+=============================================================================
// Display IR code
//
void  ircode (decode_results *results)
{
  // Panasonic has an Address
  if (results->decode_type == PANASONIC) {
    Serial.print(results->address, HEX);
    Serial.print(":");
  }

  // Print Code
  Serial.print(results->value, HEX);
}

//+=============================================================================
// Display encoding type
//
void  encoding (decode_results *results)
{
  switch (results->decode_type) {
    default:
    case UNKNOWN:      Serial.print("UNKNOWN");       break ;
    case NEC:          Serial.print("NEC");           break ;
    case SONY:         Serial.print("SONY");          break ;
    case RC5:          Serial.print("RC5");           break ;
    case RC6:          Serial.print("RC6");           break ;
    case DISH:         Serial.print("DISH");          break ;
    case SHARP:        Serial.print("SHARP");         break ;
    case JVC:          Serial.print("JVC");           break ;
    case SANYO:        Serial.print("SANYO");         break ;
    case MITSUBISHI:   Serial.print("MITSUBISHI");    break ;
    case SAMSUNG:      Serial.print("SAMSUNG");       break ;
    case LG:           Serial.print("LG");            break ;
    case WHYNTER:      Serial.print("WHYNTER");       break ;
    case AIWA_RC_T501: Serial.print("AIWA_RC_T501");  break ;
    case PANASONIC:    Serial.print("PANASONIC");     break ;
    case DENON:        Serial.print("Denon");         break ;
  }
}

//+=============================================================================
// Dump out the decode_results structure.
//
void  dumpInfo (decode_results *results)
{
  // Check if the buffer overflowed
  if (results->overflow) {
    Serial.println("IR code too long. Edit IRremoteInt.h and increase RAWBUF");
    return;
  }

  // Show Encoding standard
  Serial.print("Encoding  : ");
  encoding(results);
  Serial.println("");

  // Show Code & length
  Serial.print("Code      : ");
  ircode(results);
  Serial.print(" (");
  Serial.print(results->bits, DEC);
  Serial.println(" bits)");
}

//+=============================================================================
// Dump out the decode_results structure.
//
void  dumpRaw (decode_results *results)
{
  // Print Raw data
  Serial.print("Timing[");
  Serial.print(results->rawlen-1, DEC);
  Serial.println("]: ");

  for (int i = 1;  i < results->rawlen;  i++) {
    unsigned long  x = results->rawbuf[i] * USECPERTICK;
    if (!(i & 1)) {  // even
      Serial.print("-");
      if (x < 1000)  Serial.print(" ") ;
      if (x < 100)   Serial.print(" ") ;
      Serial.print(x, DEC);
    } else {  // odd
      Serial.print("     ");
      Serial.print("+");
      if (x < 1000)  Serial.print(" ") ;
      if (x < 100)   Serial.print(" ") ;
      Serial.print(x, DEC);
      if (i < results->rawlen-1) Serial.print(", "); //',' not needed for last one
    }
    if (!(i % 8))  Serial.println("");
  }
  Serial.println("");                    // Newline
}

//+=============================================================================
// Dump out the decode_results structure.
//
void  dumpCode (decode_results *results)
{
  // Start declaration
  Serial.print("unsigned int  ");          // variable type
  Serial.print("rawData[");                // array name
  Serial.print(results->rawlen - 1, DEC);  // array size
  Serial.print("] = {");                   // Start declaration

  // Dump data
  for (int i = 1;  i < results->rawlen;  i++) {
    Serial.print(results->rawbuf[i] * USECPERTICK, DEC);
    if ( i < results->rawlen-1 ) Serial.print(","); // ',' not needed on last one
    if (!(i & 1))  Serial.print(" ");
  }

  // End declaration
  Serial.print("};");  // 

  // Comment
  Serial.print("  // ");
  encoding(results);
  Serial.print(" ");
  ircode(results);

  // Newline
  Serial.println("");

  // Now dump "known" codes
  if (results->decode_type != UNKNOWN) {

    // Some protocols have an address
    if (results->decode_type == PANASONIC) {
      Serial.print("unsigned int  addr = 0x");
      Serial.print(results->address, HEX);
      Serial.println(";");
    }

    // All protocols have data
    Serial.print("unsigned int  data = 0x");
    Serial.print(results->value, HEX);
    Serial.println(";");
  }
}

//+=============================================================================
// The repeating section of the code
//
void  loop ( )
{
  decode_results  results;        // Somewhere to store the results

  if (irrecv.decode(&results)) {  // Grab an IR code
    dumpInfo(&results);           // Output the results
    dumpRaw(&results);            // Output the results in RAW format
    dumpCode(&results);           // Output the results as source code
    Serial.println("");           // Blank line between entries
    irrecv.resume();              // Prepare for the next value
  }
}

This gave me a 23 bit array

Encoding  : UNKNOWN
Code      : A32AB931 (32 bits)
Timing[23]: 
     +1250, - 450     +1250, - 450     + 400, -1300     +1200, - 500
     +1200, - 500     + 350, -1300     + 400, -1300     + 400, -1300
     + 400, -1300     + 400, -1300     + 350, -1300     +1250
unsigned int  rawData[23] = {1250,450, 1250,450, 400,1300, 1200,500, 1200,500, 350,1300, 400,1300, 400,1300, 400,1300, 400,1300, 350,1300, 1250};  // UNKNOWN A32AB931

This was the next sketch

#include <IRremoteInt.h>
#include <IRremote.h>

// If one keypress results in multiple codes being output, then
// change in IRremoteInt.h:
// #define _GAP 50000
// This sketchThis sketch was obtained from:
//  For more info:
//  jason welsh
//   https://www.youtube.com/watch?v=eR8sQq3pl20
//  https://docs.google.com/document/d/1QgmFbFlB0aI3swrhQkacRe3C-cIS0p1t0TV36-i2lLo/edit

//   http://www.instructables.com/id/Arduino-Remote-Control-Less-10/?ALLSTEPS
/////////////////////////////////
//  I made a few small changes

#include <IRremote.h>

int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;

void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
}

int c = 0;

void dump(decode_results *results) {
  int count = results->rawlen;
  Serial.println(c);
  c++;
  Serial.println("For IR Scope: ");
  for (int i = 1; i < count; i++) {
   
    if ((i % 2) == 1) {
      Serial.print("+");
      Serial.print(results->rawbuf[i]*USECPERTICK, DEC);
    }
    else {
      Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC);
    }
    Serial.print(" ");
  }
  Serial.println("");
  Serial.println("For Arduino sketch: ");
  Serial.print("unsigned int raw");
  Serial.print(c);
   Serial.print("[");
  Serial.print(count, DEC);
  Serial.print("] = {");
  for (int i = 1; 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.print("};");
  Serial.println("");
  Serial.print("irsend.sendRaw(");
  Serial.print("raw");
  Serial.print(c);
  Serial.print(",");
  Serial.print(count, DEC);
  Serial.print(",38);");
  Serial.println("");
  Serial.println("");
}

void loop() {
  if (irrecv.decode(&results)) {
    dump(&results);
    irrecv.resume(); // Receive the next value
  }
}

This gave me a 24 bit array

For IR Scope: 
+1250 -450 +1250 -450 +350 -1300 +1250 -450 +1250 -450 +400 -1300 +400 -1300 +350 -1300 +450 -1250 +400 -1300 +400 -1300 +1250 
For Arduino sketch: 
unsigned int raw4[24] = {1250,450,1250,450,350,1300,1250,450,1250,450,400,1300,400,1300,350,1300,450,1250,400,1300,400,1300,1250,};
irsend.sendRaw(raw4,24,38);

Which sketch would be most accurate for receiving the RAW codes? Could this 1 bit difference be effecting the remote not working properly?

Update: I have finally got it to properly turn on the heater. I would like to thank everyone that helped me. I found another sketch online that is particularly good at decoding long RAW values. I will post it below for anyone to use in the future .

This Software was written by AnalysIR.

Usage: Free to use, subject to conditions posted on blog below.
Please credit AnalysIR and provide a link to our website/blog, where possible.

Copyright AnalysIR 2014

Please refer to the blog posting for conditions associated with use.

/*
Author: AnalysIR
Revision: 1.0

This code is provided to overcome an issue with Arduino IR libraries
It allows you to capture raw timings for signals longer than 255 marks & spaces.
Typical use case is for long Air conditioner signals.

You can use the output to plug back into IRremote, to resend the signal.

This Software was written by AnalysIR.

Usage: Free to use, subject to conditions posted on blog below.
Please credit AnalysIR and provide a link to our website/blog, where possible.

Copyright AnalysIR 2014

Please refer to the blog posting for conditions associated with use.
http://www.analysir.com/blog/2014/03/19/air-conditioners-problems-recording-long-infrared-remote-control-signals-arduino/

Connections:
IR Receiver      Arduino
V+          ->  +5v
GND          ->  GND
Signal Out   ->  Digital Pin 2
(If using a 3V Arduino, you may connect V+ to +3V)
  */

#define LEDPIN 13
//you may increase this value on Arduinos with greater than 2k SRAM
#define maxLen 800

volatile  unsigned int irBuffer[maxLen]; //stores timings - volatile because changed by ISR
volatile unsigned int x = 0; //Pointer thru irBuffer - volatile because changed by ISR

void setup() {
  Serial.begin(115200); //change BAUD rate as required
  attachInterrupt(0, rxIR_Interrupt_Handler, CHANGE);//set up ISR for receiving IR signal
}

void loop() {
  // put your main code here, to run repeatedly:

  Serial.println(F("Press the button on the remote now - once only"));
  delay(5000); // pause 5 secs
  if (x) { //if a signal is captured
    digitalWrite(LEDPIN, HIGH);//visual indicator that signal received
    Serial.println();
    Serial.print(F("Raw: (")); //dump raw header format - for library
    Serial.print((x - 1));
    Serial.print(F(") "));
    detachInterrupt(0);//stop interrupts & capture until finshed here
    for (int i = 1; i < x; i++) { //now dump the times
      if (!(i & 0x1)) Serial.print(F("-"));
      Serial.print(irBuffer[i] - irBuffer[i - 1]);
      Serial.print(F(", "));
    }
    x = 0;
    Serial.println();
    Serial.println();
    digitalWrite(LEDPIN, LOW);//end of visual indicator, for this time
    attachInterrupt(0, rxIR_Interrupt_Handler, CHANGE);//re-enable ISR for receiving IR signal
  }

}

void rxIR_Interrupt_Handler() {
  if (x > maxLen) return; //ignore if irBuffer is already full
  irBuffer[x++] = micros(); //just continually record the time-stamp of signal transitions

}