Champion IR Remote Control (IR Codes)

I have been working for quite some time on a project to control my swamp cooler by IR. I have a Champion Swamp Cooler that will turn on the pump, low fan, high fan, or the entire unit by infra red remote control. There are 3 buttons on the remote. All attempts to get my Arduino Mega 2560 to receive and document IR codes have failed. I have attempted to use a Radio Shack Emitter and Detector (276-0142) yet can't get the Arduino to know I am pressing any buttons. Since this failed I took my Dish Network learning remote programmed it to control the swamp cooler. I then removed the IR LED and attached wires. Even having a direct connection was not detected when I attached the unit to the Arduino. I then attempted to read the signal using LabView. I am able to see a waveform yet can't seem to translate it to the Arduino. Does anybody have the IR codes for Champion swamp coolers. If not, what is the best program I could use on my Mega 2560 to record and playback remote codes? Attached is an output from LabView.

I am very new to Arduino thus any advice will be appreciated.

Scott

IR Remotes are typically modulated at 38 kHz. You should use a demodulating receiver to receive the signals. One such module is the Radio Shack 276-640:

You can also pull one out of almost any dead piece of AV equipment (VCR, DVD player, TV). Typically they have three pins: Power (+5) Ground and Signal.

Thanks for the information. I just received the IR Receiver from eBay (http://www.ebay.com/itm/320817501655?ssPageName=STRK:MEWNX:IT&_trksid=p3984.m1497.l2649). I had another sensor, from Raido Shack and I blew it up! I managed to get my Mega 2560 to receive input and it displays timings. When I playback the codes the cooler does nothing. What is the best software to record and playback IR codes? Somehow I have been working intermittently for about a month yet can't seem to find any working solutions. Being a beginner is also proving to be a challenge as this is my first project.

Scott

Ken Shirriff's IR Remote Library:

Thanks for the information. I guess this project is way over my head. I just accessed ken's program for arbitrary remotes. I find that mine is not one in the list. I get hash codes of E0984BB6, 143226DB, and A32AB931 thus my remote is un-supported. Looks like I may have to go the SSR route. I plan to keep trying but looks like success for me may be unlikely as I am very new to the Arduino environment.

Scott

When you receive an IR code you get the raw pulse lengths even if none of the four built-in decoders can decode the pulses. You can play the raw pulses back to emulate the remote. If you don't have many codes to store you can just store them in raw form.

Even if Ken Shirriff's IR Remote Library is VERY powerful and well written it has a major disadvantage: it uses a local very short buffer ( 76 state change samples ) to store variations in the received signal.
Now, some protocol works sending/receiving more complex signals than the ones u can fetch with that library, for instance, signals sent by my Daikin cooler are > 120 state-changes long.

You can try oversizing the buffer used to receive the signal hackin' IRremote.h:88 and increasing RAWBUF to something bigger, but be carefull doing so bucause if u set it to a to big value, ure kernel will simpy not run at all :wink:

I hope this will help you :slight_smile:

cunctator:
for instance, signals sent by my Daikin cooler are > 120 state-changes long.

Did you check to see if perhaps they were sending the same sequence several times? That's often done for noise immunity.

I just got my waveforms using LabView. My next task is to make the Arduino output the same waveform. Attached is a photo of the data captured.

Scott

I ended buying an el cheapo Universal Remote from a dollar store and programming it to emulate a Sony VCR. Once I got Ken's Remote Library running, it worked reliably, and I just mapped the output codes to the function I wanted to run.

In my case, I used a KSM-603LM photodiode as the receiver.

emm386:
I just got my waveforms using LabView. My next task is to make the Arduino output the same waveform. Attached is a photo of the data captured.

Did you remember to measure the pulse durations, too? The picture isn't much use without the timing.

I just downloaded the code from this site: tutorials:learn:sensors:ir.html [AdaWiki]

What I will be doing is adjusting my timings to match the photo's above and tweak as required. A good friend (Frank), of mine wrote the LabView code. It translates the waveform into a hex string. I don't think Arduino can transmit hex string pulses given my current programming experience. Anyways attached is the screen I am working with, the bottom output is the Nikon demo signal. I really appreciate the help. I know I can get this!!

Scott

Looks to me like each bit time is the same and is divided into four segments. If the segments are 0111 (1/4 LOW and 3/4 HIGH) you have a 1 and if they're 0001 (3/4 LOW and 1/4 HIGH) you have a 0. Since each bit starts with a HIGH to LOW transition the signal is self-clocking. Just sample 1/2 bit time from the HIGH to LOW transition.

johnwasser:

cunctator:
for instance, signals sent by my Daikin cooler are > 120 state-changes long.

Did you check to see if perhaps they were sending the same sequence several times? That's often done for noise immunity.

Yhea in fact it does, but the IRLibrary doesn't make any check on raw signals for redundancy, so it still could lead to a failed retransmission ( just like happened to me :smiley: )

[edit]

Ooops I wrote 2 wrong things in one sentence!
The signal is not > 200 state-change long, it's > 500!! Il lasts for more than 400ms, almost half a second :fearful:
I double checked the signal to find the repeat point, but I could not recognize a repeated pattern as all other sampled signals did ( hitachi, apple, philips ) :frowning:

emm386:
I don't think Arduino can transmit hex string pulses given my current programming experience.

Retransmitting hex strings is just a matter of how did u packed the stream info, in Manchester encoding ( while now i've seen just this on sampled signals ) it's quite easy to transform a number in a sequence of dent/holes, given a specific frequency, and a mimimum interval reconstructing the signal is on the way. But it could be messy to share the same "way of encoding"" between different IR protocols.

By the way tutorials:learn:sensors:ir.html [AdaWiki] was an interesting read, the way he checks for pin state with a single logical AND is really nice.

I don't understand how he can modulate the carrier frequency relying on delay() while disabling interrupts, wich should drive delay() itself :open_mouth:

Thank u for sharing :slight_smile:

Thanks everybody for all the help, I got it working. Here I am posting the modified code so others can control their Champion swamp cooler via Arduino.

Again, Thanks everybody.

emm386

/* Code modified by Scott M.

This code can control a Champion Swamp Cooler's via IR:

1. Turn blower to high, low, or off
2. Turn water pump on or off
3. Turn entire unit on or off

I plan to use photocells enabling detection of cooler switching from high to low or
pump being on or off.  Final project will use a few RHT03 Humidity & Temp sensor's enabling cooler
to operate more efficient.

Special thanks are in order for:

Website providing original code:
ladaya.net - Provided initial source code

Labview Programmer:
Frank S. - Labview specialist

Arduino.cc forum users:
johnwasser
cunctator
johnnycanuck

Original programmer's information and link follows:
*/

// This sketch will send out a Nikon D50 trigger signal (probably works with most Nikons)
// See the full tutorial at http://www.ladyada.net/learn/sensors/ir.html
// this code is public domain, please enjoy!


 
int IRledPin =  13;    // LED connected to digital pin 13
 
// The setup() method runs once, when the sketch starts
 
void setup()   {                
  // initialize the IR digital pin as an output:
  pinMode(13, OUTPUT);      
 
  Serial.begin(9600);
}
 
void loop()                     
{
  Serial.println("Sending IR signal");
 
  PowerCooler();//Turns entire swamp cooler on or off, requires minimum of 2 sets of code
  PowerCooler();
  delay(10000);//Delay, easier for troubleshooting.
  PowerFan();//Switches fan from High, Low, and off
  PowerFan();
  delay(10000);
  PowerPump();//Switches pump on or off
  PowerPump();
  delay(10000);
}
 
// This procedure sends a 38KHz pulse to the IRledPin 
// for a certain # of microseconds. We'll use this whenever we need to send codes
void pulseIR(long microsecs) {
  // we'll count down from the number of microseconds we are told to wait
 
  cli();  // this turns off any background interrupts
 
  while (microsecs > 0) {
    // 38 kHz is about 13 microseconds high and 13 microseconds low
   digitalWrite(IRledPin, HIGH);  // this takes about 3 microseconds to happen
   delayMicroseconds(10);         // hang out for 10 microseconds
   digitalWrite(IRledPin, LOW);   // this also takes about 3 microseconds
   delayMicroseconds(10);         // hang out for 10 microseconds
 
   // so 26 microseconds altogether
   microsecs -= 26;
  }
 
  sei();  // this turns them back on
}

void PowerFan() { 
      int p = 545;//p is used for both transmissions and delays, represents a period of time.
      int dp = p*2;//Provides double the value pf p
      int dly = p*14;//used as a spacer between IR transmissions
      //IR Signal, Switches fan (High, Low, Off)
            pulseIR(dp);
            delayMicroseconds(p);            
            pulseIR(dp);
            delayMicroseconds(p);            
            pulseIR(p);
            delayMicroseconds(dp);            
            pulseIR(dp); 
            delayMicroseconds(p);            
            pulseIR(dp);
            delayMicroseconds(p);            
            pulseIR(p); 
            delayMicroseconds(dp);            
            pulseIR(p); 
            delayMicroseconds(dp);            
            pulseIR(p); 
            delayMicroseconds(dp);            
            pulseIR(p);
            delayMicroseconds(dp);            
            pulseIR(p);
            delayMicroseconds(dp);            
            pulseIR(p);
            delayMicroseconds(dp);            
            pulseIR(dp);
            delayMicroseconds(p);
            delayMicroseconds(dly); 
}
 
void PowerCooler() {
 
      int p = 545;
      int dp = p*2;
      int dly = p*14;
      //IR Signal,  Turns Cooler on and Off
            pulseIR(dp);
            delayMicroseconds(p);  
            pulseIR(dp);
            delayMicroseconds(p);  
            pulseIR(p);
            delayMicroseconds(dp);  
            pulseIR(dp);
            delayMicroseconds(p);  
            pulseIR(dp);  
            delayMicroseconds(p);  
            pulseIR(p);
            delayMicroseconds(dp);  
            pulseIR(p);
            delayMicroseconds(dp);  
            pulseIR(p);
            delayMicroseconds(dp);  
            pulseIR(dp);
            delayMicroseconds(p);  
            pulseIR(p);
            delayMicroseconds(dp);  
            pulseIR(p);
            delayMicroseconds(dp);  
            pulseIR(p);
            delayMicroseconds(dly); 
}

void PowerPump() {
      int p = 545;
      int dp = p*2;
      int dly = p*14;
      //IR Signal, Turns pump on or off
            pulseIR(dp);
            delayMicroseconds(p);            
            pulseIR(dp);
            delayMicroseconds(p);            
            pulseIR(p);
            delayMicroseconds(dp);            
            pulseIR(dp);
            delayMicroseconds(p);            
            pulseIR(dp);
            delayMicroseconds(p);            
            pulseIR(p);
            delayMicroseconds(dp);            
            pulseIR(p);
            delayMicroseconds(dp);            
            pulseIR(p);
            delayMicroseconds(dp);            
            pulseIR(p);
            delayMicroseconds(dp);            
            pulseIR(p);
            delayMicroseconds(dp);            
            pulseIR(dp); 
            delayMicroseconds(p);            
            pulseIR(p);           
            delayMicroseconds(dly);
}