Arduino Forum

Forum 2005-2010 (read only) => Hardware => Interfacing => Topic started by: pmalmsten on Apr 09, 2007, 08:00 am

Title: Arduino infrared problems
Post by: pmalmsten on Apr 09, 2007, 08:00 am
Hello,

I just got an Arduino board a few days ago and it is really awesome. I just recently started working on hooking up an infrared reciever, an old parallax one http://www.parallax.com/detail.asp?product_id=350-00014. The sensor is responding and Arduino can read it, but I get the same measurement pattern for every button I push on a remote! I'm using the pulseIn command to measure 12 pulses, but I have also tried measuring only 8 with no change. Does anyone have any ideas?

Code: [Select]
int pwr_high = 4;  //Sensor pin 1
int pwr_low = 3;    //Sensor pin 2
int ir_pin = 2;    //Sensor pin 3, the data pin
int data[12];
 
void setup() {
 pinMode(pwr_high, OUTPUT);    
 pinMode(pwr_low, OUTPUT);
 pinMode(ir_pin, INPUT);
 digitalWrite(pwr_high, HIGH);    //Sensor pin 1 always high
 digitalWrite(pwr_low, LOW);      //Sensor pin 2 always low
 Serial.begin(9600);
}

void loop() {
 data[0] = pulseIn(ir_pin, LOW);    //Start measuring bits --the sensor defaults high, goes low on infrared
 data[1] = pulseIn(ir_pin, LOW);
 data[2] = pulseIn(ir_pin, LOW);
 data[3] = pulseIn(ir_pin, LOW);
 data[4] = pulseIn(ir_pin, LOW);
 data[5] = pulseIn(ir_pin, LOW);
 data[6] = pulseIn(ir_pin, LOW);
 data[7] = pulseIn(ir_pin, LOW);
 data[8] = pulseIn(ir_pin, LOW);
 data[9] = pulseIn(ir_pin, LOW);
 data[10] = pulseIn(ir_pin, LOW);
 data[11] = pulseIn(ir_pin, LOW);
 
 Serial.println("-----");    //Send them all
 Serial.println(data[0]);
 Serial.println(data[1]);
 Serial.println(data[2]);
 Serial.println(data[3]);
 Serial.println(data[4]);
 Serial.println(data[5]);
 Serial.println(data[6]);
 Serial.println(data[7]);
 Serial.println(data[8]);
 Serial.println(data[9]);
 Serial.println(data[10]);
 Serial.println(data[11]);
}


For example, I only get:
Code: [Select]
-----
9842
787
9824
796
791
790
786
786
785
784
762
762


This is from a Tivo remote, every button reports the same with ~10-20 variance each time.
Title: Re: Arduino infrared problems
Post by: Daniel on Apr 09, 2007, 09:36 am
hi

try this: the gnd and power pins of the sensor should be driven from the GND and +5 pins of the Arduino respectively, rather than from the I/O pins as the code suggests.

D
Title: Re: Arduino infrared problems
Post by: pmalmsten on Apr 09, 2007, 06:21 pm
Thanks for the tip. I thought about doing that myself at first, but I figured Arduino would provide plenty of power for a little sensor. Anyways, I tried hooking it up properly to the +5 and GND connections, but I still got the same results as before, different buttons returning very similar codes with a small variance in timings. I have a basic stamp laying around, and I got a basic idea for the project from this guide (pdf) http://www.parallax.com/dl/docs/prod/sic/WebIR-%20v1.1.pdf.

Oops, I just read through the guide a little more and found that I needed a resistor between the IR receiver and the microcontroller. That's a little weird though, because the resistor didn't change anything...
Title: Re: Arduino infrared problems
Post by: pmalmsten on Apr 10, 2007, 01:22 am
Ah, finally I got everything to work properly. I decided to dump the Tivo remote for a universal remote, setting it up for a Sony TV like the parallax guide recommended. After switching to the Sony protocol everything fell into place and it works beautifully. I don't know what unholy things the Tivo remote has to do to get its signal across.

Pins:
-2 and 3 of the IR receiver are in GND and +5 respectively
-1 of the IR receiver is connected through a 220-ohm resistor to pin 2 of the Arduino
-A green led is placed across pin 13 and GND on the Arduino to show when it is waiting for data

A quick summary of the Sony TV protocol:
-The whole set is 13 pulses long
-The pulses are only measured while low (I'm sure there's a cool word for that but I don't know it)
-The first pulse, the start pulse, lasts about 2.4 ms (2400 microseconds)
-The following pulses are 1.2 ms (1200 microseconds) for a 1, 0.6 ms (600 microseconds) for a 0
-Each data pulse is about 0.3 ms (300 microseconds) apart
-Every set of 13 pulses is about 20-30 ms apart from each other, repeating when a button is held down

The code below will watch for a 13 pulse set and returns the set's integer equivalent, different for every button on the remote. If you want to try your own TV code you can always set the debug flag to 1 and see all of the pretty microsecond measurements.

Code: [Select]
int ir_pin = 2;                        //Sensor pin 1 wired through a 220 ohm resistor
int led_pin = 13;                      //"Ready to Recieve" flag, not needed but nice
int debug = 0;                         //Serial connection must be started to debug
int start_bit = 2000;                  //Start bit threshold (Microseconds)
int bin_1 = 1000;                      //Binary 1 threshold (Microseconds)
int bin_0 = 400;                       //Binary 0 threshold (Microseconds)

 
void setup() {
 pinMode(led_pin, OUTPUT);            //This shows when we're ready to recieve
 pinMode(ir_pin, INPUT);
 digitalWrite(led_pin, LOW);          //not ready yet
 Serial.begin(9600);
}

void loop() {
 int key = getIRKey();                //Fetch the key
 Serial.print("Key Recieved: ");      
 Serial.println(key);                
}


int getIRKey() {
 int data[12];
 digitalWrite(led_pin, HIGH);         //Ok, i'm ready to recieve
 while(pulseIn(ir_pin, LOW) < 2200) { //Wait for a start bit
 }
 data[0] = pulseIn(ir_pin, LOW);      //Start measuring bits, I only want low pulses
 data[1] = pulseIn(ir_pin, LOW);
 data[2] = pulseIn(ir_pin, LOW);
 data[3] = pulseIn(ir_pin, LOW);
 data[4] = pulseIn(ir_pin, LOW);
 data[5] = pulseIn(ir_pin, LOW);
 data[6] = pulseIn(ir_pin, LOW);
 data[7] = pulseIn(ir_pin, LOW);
 data[8] = pulseIn(ir_pin, LOW);
 data[9] = pulseIn(ir_pin, LOW);
 data[10] = pulseIn(ir_pin, LOW);
 data[11] = pulseIn(ir_pin, LOW);
 digitalWrite(led_pin, LOW);
 
 if(debug == 1) {
   Serial.println("-----");
 }
 for(int i=0;i<11;i++) {              //Parse them
   if (debug == 1) {
       Serial.println(data[i]);
   }            
   if(data[i] > bin_1) {              //is it a 1?
     data[i] = 1;
   }  else {
     if(data[i] > bin_0) {            //is it a 0?
       data[i] = 0;
     } else {
      data[i] = 2;                    //Flag the data as invalid; I don't know what it is!
     }
   }
 }
 
 for(int i=0;i<11;i++) {              //Pre-check data for errors
   if(data[i] > 1) {                
     return -1;                       //Return -1 on invalid data
   }
 }
 
 int result = 0;  
 int seed = 1;                                      
 for(int i=0;i<11;i++) {              //Convert bits to integer
   if(data[i] == 1) {
     result += seed;
   }
   seed = seed * 2;
 }
 return result;                       //Return key number
}


Now all I have to do is figure out what to do with it....
Title: Re: Arduino infrared problems
Post by: DojoDave on Dec 21, 2007, 05:50 pm
Hej,

this is my code for sender and receiver, note that the receiver is having a nasty hack to get the data out, but it sends and receives numbers from 1 to 8 with no problem :-)

Code: [Select]

RECEIVER
-----------------

int ir_pin = 7;                         //Sensor pin 1 wired through a 220 ohm resistor
int led_pin = 13;                           //"Ready to Receive" flag, not needed but nice
int debug = 0;                           //Serial connection must be started to debug
int start_bit = 2000;                   //Start bit threshold (Microseconds)
int bin_1 = 1000;                           //Binary 1 threshold (Microseconds)
int bin_0 = 400;                             //Binary 0 threshold (Microseconds)


void setup() {
pinMode(led_pin, OUTPUT);             //This shows when we're ready to receive
pinMode(ir_pin, INPUT);
digitalWrite(led_pin, LOW);       //not ready yet
Serial.begin(9600);
}

void loop() {
int key = getIRKey();             //Fetch the key
if (key != -1) {
  Serial.print("Key Recieved: ");
  Serial.println(key);
}
}


int getIRKey() {
int data[12];
digitalWrite(led_pin, HIGH);     //Ok, i'm ready to recieve
while(pulseIn(ir_pin, LOW) < 2200) { //Wait for a start bit
}
data[0] = pulseIn(ir_pin, LOW);       //Start measuring bits, I only want low pulses
data[1] = pulseIn(ir_pin, LOW);
data[2] = pulseIn(ir_pin, LOW);
data[3] = pulseIn(ir_pin, LOW);
data[4] = pulseIn(ir_pin, LOW);
data[5] = pulseIn(ir_pin, LOW);
data[6] = pulseIn(ir_pin, LOW);
data[7] = pulseIn(ir_pin, LOW);
data[8] = pulseIn(ir_pin, LOW);
data[9] = pulseIn(ir_pin, LOW);
data[10] = pulseIn(ir_pin, LOW);
data[11] = pulseIn(ir_pin, LOW);
digitalWrite(led_pin, LOW);

if(debug == 1) {
  Serial.println("-----");
}
for(int i=0;i<11;i++) {                 //Parse them
  if (debug == 1) {
        Serial.println(data[i]);
  }
  if(data[i] > bin_1) {                 //is it a 1?
      data[i] = 1;
  }  else {
      if(data[i] > bin_0) {           //is it a 0?
        data[i] = 0;
      } else {
       data[i] = 2;                     //Flag the data as invalid; I don't know what it is!
      }
  }
}

for(int i=0;i<11;i++) {                 //Pre-check data for errors
  if(data[i] > 1) {
      return -1;                           //Return -1 on invalid data
  }
}

int result = 0;
int seed = 1;
for(int i=11;i>=0;i--) {                //Convert bits to integer
  if(data[i] == 1) {
      result |= seed;
  }
  seed = seed * 2;
}

//patch for the weird data result
//I wish I knew wtf is wrong
for (int j = 0; j <= 11; j++) {
int aux = result;
  aux -= pow(2, j);
  if (aux < 0) {
    result = j;
    break;
  }
}
if (result > 8) result = -1;
return result;                             //Return key number
}

SENDER
--------------

int ir_pin = 6;                         //Sensor pin 1 wired through a 220 ohm resistor
int led_pin = 13;                           //"Ready to Receive" flag, not needed but nice
int debug = 1;                           //Serial connection must be started to debug
int start_bit = 2400;                   //Start bit threshold (Microseconds)
int bin_1 = 1200;                           //Binary 1 threshold (Microseconds)
int bin_0 = 600;                             //Binary 0 threshold (Microseconds)
int dataOut = 0;
int guardTime = 300;


void setup() {
pinMode(led_pin, OUTPUT);             //This shows when we're ready to recieve
pinMode(ir_pin, OUTPUT);
digitalWrite(led_pin, LOW);       //not ready yet
digitalWrite(ir_pin, LOW);        //not ready yet
Serial.begin(9600);
}

void loop() {
if (Serial.available()) {
  int val = Serial.read();
  switch (val) {
  case '0':
    dataOut = val - 48;
    break;
  case '1':
    dataOut = val - 48;
    break;
  case '2':
    dataOut = val - 48;
    break;
  case '3':
    dataOut = val - 48;
    break;
  case '4':
    dataOut = val - 48;
    break;
  case '5':
    dataOut = val - 48;
    break;
  case '6':
    dataOut = val - 48;
    break;
  case '7':
    dataOut = val - 48;
    break;
  case '8':
    dataOut = val - 48;
    break;
  default:
    dataOut = 255;
    break;
  }
}
int key = sendIRKey(dataOut);             //Fetch the key
Serial.print("Key Sent: ");
Serial.println(key);
}


int sendIRKey(int dataOut) {
int data[12];
digitalWrite(led_pin, HIGH);     //Ok, i'm ready to send
for (int i=0; i<12; i++)
  data[i] = dataOut>i & B1;   //encode data as '1' or '0'

// send startbit
oscillationWrite(ir_pin, start_bit);
// send separation bit
digitalWrite(ir_pin, HIGH);
delayMicroseconds(guardTime);
// send the whole string of data
for (int i=11; i>=0; i--) {
  //digitalWrite(ir_pin, LOW);
  //if (data[i] == 0) delayMicroseconds(bin_0);
  //else delayMicroseconds(bin_1);
  if (data[i] == 0) oscillationWrite(ir_pin, bin_0);
  else oscillationWrite(ir_pin, bin_1);
  // send separation bit
  digitalWrite(ir_pin, HIGH);
  delayMicroseconds(guardTime);
}
delay(20);
return dataOut;                            //Return key number
}

// this will write an oscillation at 38KHz for a certain time in useconds
void oscillationWrite(int pin, int time) {
for(int i = 0; i <= time/26; i++) {
  digitalWrite(pin, HIGH);
  delayMicroseconds(13);
  digitalWrite(pin, LOW);
  delayMicroseconds(13);
}
}


/d
Title: Re: Arduino infrared problems
Post by: PlastBox on Jan 03, 2008, 03:20 pm
Pure genious! :D

I've been thinking of a way to control my tv and dvd-player from a computer for years now, and finally.. here it is in all it's glory! All hail pmalmsten!

I just need to adapt this code to work with my Phillips dvd-player (tricky bastard, using Manchester coding, and kidney shots too probably! -_-' ) Then, write some backend-stuff with VB and a php frontend, and voilá! I can control my tv and dvd-player, as well as lights and such, from my comuter and cellphone!

If I get this working, you, sire, will have my everlasting gratitude!

Oh, and by the way... why on earth hasn't this thread been made sticky?
Title: Re: Arduino infrared problems
Post by: DojoDave on Jan 10, 2008, 01:46 pm
Oh,

I fixed my code ... it was having plenty of bugs in it:

Code: [Select]

SENDER
----------
int ir_pin = 10;                         //Sensor pin 1 wired through a 220 ohm resistor
int led_pin = 13;                           //"Ready to Receive" flag, not needed but nice
int debug = 1;                           //Serial connection must be started to debug
int start_bit = 2400;                   //Start bit threshold (Microseconds)
int bin_1 = 1200;                           //Binary 1 threshold (Microseconds)
int bin_0 = 600;                             //Binary 0 threshold (Microseconds)
int dataOut = 0;
int guardTime = 300;


void setup() {
 pinMode(led_pin, OUTPUT);             //This shows when we're ready to recieve
 pinMode(ir_pin, OUTPUT);
 digitalWrite(led_pin, LOW);       //not ready yet
 digitalWrite(ir_pin, LOW);        //not ready yet
 Serial.begin(9600);
}

void loop() {
 if (Serial.available()) {
   int val = Serial.read();
   dataOut = val;
   int key = 0;
   for (int j = 0; j<10; j++) {
     key = sendIRKey(dataOut);             //Fetch the key
   }
     Serial.print("Key Sent: ");
     Serial.println(key);
 }
}


int sendIRKey(int dataOut) {
 int data[12];
 digitalWrite(led_pin, HIGH);     //Ok, i'm ready to send
 for (int i=0; i<12; i++) {
   data[i] = dataOut>>i & B1;   //encode data as '1' or '0'
   }
 // send startbit
 oscillationWrite(ir_pin, start_bit);
 // send separation bit
 digitalWrite(ir_pin, HIGH);
 delayMicroseconds(guardTime);
 // send the whole string of data
 for (int i=11; i>=0; i--) {
   if (data[i] == 0) oscillationWrite(ir_pin, bin_0);
   else oscillationWrite(ir_pin, bin_1);
   // send separation bit
   digitalWrite(ir_pin, HIGH);
   delayMicroseconds(guardTime);
 }
 delay(20);
 return dataOut;                            //Return key number
}

// this will write an oscillation at 38KHz for a certain time in useconds
void oscillationWrite(int pin, int time) {
 for(int i = 0; i <= time/26; i++) {
   digitalWrite(pin, HIGH);
   delayMicroseconds(13);
   digitalWrite(pin, LOW);
   delayMicroseconds(13);
 }
}


Code: [Select]

RECEIVER
------------
int ir_pin = 7;                         //Sensor pin 1 wired through a 220 ohm resistor
int led_pin = 13;                           //"Ready to Receive" flag, not needed but nice
int debug = 1;                           //Serial connection must be started to debug
int start_bit = 2000;                   //Start bit threshold (Microseconds)
int bin_1 = 1000;                           //Binary 1 threshold (Microseconds)
int bin_0 = 400;                             //Binary 0 threshold (Microseconds)


void setup() {
pinMode(led_pin, OUTPUT);             //This shows when we're ready to receive
pinMode(ir_pin, INPUT);
digitalWrite(led_pin, LOW);       //not ready yet
Serial.begin(9600);
}

void loop() {
int key = getIRKey();             //Fetch the key
if (key != -1) {
  Serial.print("Key Recieved: ");
  Serial.println(key);
}
}


int getIRKey() {
int data[12];
digitalWrite(led_pin, HIGH);     //Ok, i'm ready to recieve
while(pulseIn(ir_pin, LOW) < 2200) { //Wait for a start bit
}
data[0] = pulseIn(ir_pin, LOW);       //Start measuring bits, I only want low pulses
data[1] = pulseIn(ir_pin, LOW);
data[2] = pulseIn(ir_pin, LOW);
data[3] = pulseIn(ir_pin, LOW);
data[4] = pulseIn(ir_pin, LOW);
data[5] = pulseIn(ir_pin, LOW);
data[6] = pulseIn(ir_pin, LOW);
data[7] = pulseIn(ir_pin, LOW);
data[8] = pulseIn(ir_pin, LOW);
data[9] = pulseIn(ir_pin, LOW);
data[10] = pulseIn(ir_pin, LOW);
data[11] = pulseIn(ir_pin, LOW);
digitalWrite(led_pin, LOW);

if(debug == 1) {
  Serial.println("-----");
}
for(int i=0;i<=11;i++) {                 //Parse them
  if (debug == 1) {
        Serial.println(data[i]);
  }
  if(data[i] > bin_1) {                 //is it a 1?
      data[i] = 1;
  }  else {
      if(data[i] > bin_0) {           //is it a 0?
        data[i] = 0;
      } else {
       data[i] = 2;                     //Flag the data as invalid; I don't know what it is!
      }
  }
}

for(int i=0;i<=11;i++) {                 //Pre-check data for errors
  if(data[i] > 1) {
      return -1;                           //Return -1 on invalid data
  }
}

int result = 0;
int seed = 1;
for(int i=11;i>=0;i--) {                //Convert bits to integer
  if(data[i] == 1) {
      result += seed;
  }
  seed = seed * 2;
}

return result;                             //Return key number
}


/d
Title: Re: Arduino infrared problems
Post by: death on Jan 30, 2008, 11:45 am
Quote

...snip...
I get the same measurement pattern for every button I push on a remote!

..snip..


For what its worth, I'd say what was happening was your circuit was pulling low by default, and measuring the peaks (not the troughs) of the transmission..

this picture would help to illistrate the point:

(http://www.ustr.net/infrared/nec2.gif)

except for the header, the peaks will always be the same, its the troughs that will vary (signifying 1's and 0's)
Title: Re: Arduino infrared problems
Post by: jds on Feb 07, 2008, 11:35 am
David,

I just found your code, I think I am going to use it (maybe it needs some modification) for sending an RC5 signal to a Philips TV. I found a good description of RC5 here: http://www.ustr.net/infrared/infrared1.shtml

My TV needs to have it's brightness and contrast adjusted sometimes. I don't have the original remote anymore and so far haven't been able to find a remote that has the button (off button) to leave the main menu. So, I hope to be able to do this by sending code 83 (menu off) from my Arduino with IR tx led and 220ohm resistor to the TV set.

If you think there something I should be aware of before starting with this, please let me know! Thanks in advance!

I will post here if I have results...

Edit: It seems that your code doesn't take care of sending the AGV, CHK and ADDRESS bits as shown in this picture (Philips way of working):
(http://www.ustr.net/infrared/tr7.jpg)
Title: Re: Arduino infrared problems
Post by: jules on Mar 20, 2008, 01:01 pm
Hello,

i am searching for a RC5 control with the arduino.. but diddn´t find anything yet. Did you manage it ?


thanks jules
Title: Re: Arduino infrared problems
Post by: Rudforce on Mar 25, 2008, 08:31 am
Thanks for the code! This was almost exactly what I was looking for to use my old sony VCR guts for my little project. Now I can switch between LED patterns wireless-ly.

I did have to change a wee bit though, so I thought I'd post back here with my tweak. I wanted the getIRKey() function to be run from an interrupt, but it seemed to be hanging the rest of the processing, and never quite getting to the loop(). It looked to me like the while loop at the beginning waited forever for input > 2200. I ended up changing that to "if ... < 2200, return -1", then testing for key values greater than 0 in a wrapper. The wrapper is called via the interrupt. So, here's a bit of the modified code;

Code: [Select]

int ir_pin = 2;              //Sensor pin wired through a 220 ohm resistor
int start_bit = 2000;   //Start bit threshold (Microseconds)
int bin_1 = 1000;       //Binary 1 threshold (Microseconds)
int bin_0 = 400;        //Binary 0 threshold (Microseconds)

volatile int key = 137;    // key 137 is "0", default to off

void setup() {
 pinMode(ir_pin, INPUT);
 attachInterrupt(0, setOpts, LOW);    // interrupt 0, run setOpts(), interrupt when ir_pin goes LOW
}

void loop() {
 //do pretty flashy lights here
}

void setOpts() {
 int tempKey = getIRKey();
 if(tempKey > 1){
   key = tempKey;
 }
}

int getIRKey() {
 int data[12];
 if(pulseIn(ir_pin, LOW) < 2200) { //Wait for a start bit
   return -1;
 }
 data[0] = pulseIn(ir_pin, LOW);      //Start measuring bits, I only want low pulses
 data[1] = pulseIn(ir_pin, LOW);
 data[2] = pulseIn(ir_pin, LOW);
 data[3] = pulseIn(ir_pin, LOW);
 data[4] = pulseIn(ir_pin, LOW);
 data[5] = pulseIn(ir_pin, LOW);
 data[6] = pulseIn(ir_pin, LOW);
 data[7] = pulseIn(ir_pin, LOW);
 data[8] = pulseIn(ir_pin, LOW);
 data[9] = pulseIn(ir_pin, LOW);
 data[10] = pulseIn(ir_pin, LOW);
 data[11] = pulseIn(ir_pin, LOW);

 for(int i=0;i<11;i++) {              //Parse them            
   if(data[i] > bin_1) {              //is it a 1?
     data[i] = 1;
   }  else {
     if(data[i] > bin_0) {            //is it a 0?
       data[i] = 0;
     } else {
      data[i] = 2;                    //Flag the data as invalid; I don't know what it is!
     }
   }
 }
 
 for(int i=0;i<11;i++) {              //Pre-check data for errors
   if(data[i] > 1) {                  
     return -1;                       //Return -1 on invalid data
   }
 }
 
 int result = 0;  
 int seed = 1;                                      
 for(int i=0;i<11;i++) {              //Convert bits to integer
   if(data[i] == 1) {
     result += seed;
   }
   seed = seed * 2;
 }
 return result;                       //Return key number
}


Seems to work for me, I can punch a button any time on the remote and it will reset the value of 'key', even in the middle of a delay(). I still have some work to go on it though, fiddling with my timings and such.

Thanks again.
Title: Re: Arduino infrared problems
Post by: jmknapp on Apr 30, 2008, 05:40 pm
Quote
David,
I just found your code, I think I am going to use it (maybe it needs some modification) for sending an RC5 signal to a Philips TV. I found a good description of RC5 here: http://www.ustr.net/infrared/infrared1.shtml


Check my post on implementing an RC5 transmitter (seems like it should do what you want):

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1209565937
Title: Re: Arduino infrared problems
Post by: Kronoticas on Sep 29, 2008, 05:13 pm
i tore the ir from a vcr ihad laying around and managed to get a reading from my rca remote, but im havin some trouble, the data isnt the same each time i hit a button on he remote, and i get 16 lines instead of the 11? any thoughts?
Title: Re: Arduino infrared problems
Post by: awasson on Dec 12, 2008, 08:16 am
pmalmsten:
That is a fantastic piece of code to begin an IR Remote project with... I also started with the BOE Stamp kit and a few of those Panasonic sensors, then got bogged down with SX chips but today is my second day with the Arduino and your sketch (from your second code posting) just works perfectly.

I wonder... Has anyone has thought of creating a library based on it?

My project (for the last couple of years) has been to build a remote controlled attenuator so I can run the direct audio out of my TV/Media Center through an attenuator into the power amps. The attenuator uses a microcontroller (Arduino) to receive the remote control signal and set the volume up down + mute. I have the TI Burr Brown chips that attenuate and with this receiver code I now have a great foundation.

Thanks!  
Title: Re: Arduino infrared problems
Post by: awasson on Dec 28, 2008, 08:33 am
Is anyone still following this thread with interest in developing it further?

I've made some refinements to the code to make it a tiny bit more efficient and added code to the main loop for my needs but there are some other things I'm not so sure about like:


Other than that, I wonder if we could extend the code to recognize other remotes and have a setup mode that would allow us to choose Sony, Hitachi, Panasonic, etc...

My version of the code only recognizes power, mute, volume up and volume down but could be extended to recognize other keys. At the moment it sends the state of the volume, mute and on/off to the serial monitor and saves those values to the EEPROM. My next step is to use shiftOut() to send values to a Texas Instruments PGA2311 stereo volume control chip as well as sending the values to a digital display of some sort.

Here's what I have so far:
(I moved all of the fixed variables into constants to reduce the footprint and use a loop to create the data[] array.)
Code: [Select]
/**
* Receives signal from IR remote control on pin 2 and displays the function to the serial monitor.
* Writes state of control to EEPROM for recall when power is turned off.
* Reads state of control from EEPROM when power is turned on.
*/

#include <EEPROM.h>

//CONSTANTS
#define btnPower   149
#define btnMute    148
#define btnDown    147
#define btnUp      146
#define rate       4
#define start_bit  2000                //Start bit threshold (Microseconds)
#define bin_1      1000                //Binary 1 threshold (Microseconds)
#define bin_0      400                //Binary 0 threshold (Microseconds)
#define ir_pin     2                //Sensor pin 1 wired through a 220 ohm resistor
#define led_pin    13                //"Ready to Recieve" flag, not needed but nice
#define debug      0                 //Serial connection must be started to debug

//VARIABLES
int power  = EEPROM.read(0);  
int mute   = EEPROM.read(1);  
int volume = EEPROM.read(2);
int i      = 0;                    //general purpose counter



void setup() {
 pinMode(led_pin, OUTPUT);          //This shows when we're ready to recieve
 pinMode(ir_pin, INPUT);
 digitalWrite(led_pin, LOW);          //not ready yet
 Serial.begin(9600);
 if(volume == 255) volume = 0;    //Don't start up at full volume
}

void loop() {
 //Fetch the key  
 int key = getIRKey();
 
 //Switch to print insructions to Serial Monitor
  switch (key) {    
   case btnPower:
     if(power == 0){
       power = 1;
       Serial.println("Turn On");
     } else {
       power = 0;
       Serial.println("Turn Off");
     }
     EEPROM.write(0, power);
     delay (500); //Debounce switch
     break;
     
   case btnMute:    
     if(mute == 0){
       mute = 1;
       Serial.println("Mute On");
     } else {
       mute = 0;
       Serial.println("Mute Off");
     }
     EEPROM.write(1, mute);
     delay (500); //Debounce switch
     break;
     
   case btnDown:
     if(volume > 0 && volume - rate > 0) {
       volume -= rate;
     } else {
       volume = 0;
     }
     Serial.print("Volume: ");
     Serial.println(volume);
     EEPROM.write(2, volume);
     break;  
     
   case btnUp:
     if(volume < 255 && volume + rate <= 255) {
       volume += rate;
     } else {
       volume = 255;
     }
     Serial.print("Volume: ");
     Serial.println(volume);
     EEPROM.write(2, volume);
     break;
 }

}


int getIRKey() {
 int data[12];
 digitalWrite(led_pin, HIGH);         //Ok, i'm ready to recieve  
 
 while(pulseIn(ir_pin, LOW) < 2200) {
   //Wait for a start bit
 }
 
 for(i=0;i<11;i++){
   data[i] = pulseIn(ir_pin, LOW);   //Start measuring bits, I only want low pulses
 }
 
 digitalWrite(led_pin, LOW);

 if(debug == 1) {
   Serial.println("-----");
 }
 
 for(int i=0;i<11;i++) {          //Parse them
   
   if (debug == 1) {
     Serial.println(data[i]);
   }
   
   if(data[i] > bin_1) {          //is it a 1?
     data[i] = 1;
   } else {
     if(data[i] > bin_0) {        //is it a 0?
       data[i] = 0;
     } else {
       data[i] = 2;              //Flag the data as invalid; I don't know what it is!
     }
   }
   
 }

 for(i=0;i<11;i++) {              //Pre-check data for errors
   if(data[i] > 1) {
     return -1;                //Return -1 on invalid data
   }
 }

 int result = 0;
 int seed = 1;
 for(int i=0;i<11;i++) {      //Convert bits to integer
   if(data[i] == 1) {
     result += seed;
   }
   seed = seed * 2;
 }
 return result;             //Return key number
}
Title: Re: Arduino infrared problems
Post by: richardw347 on Feb 28, 2009, 03:24 am
THanks for sharing your code guys, I am working on a robot at the moment and am working on using my tv remote to control it (when its not controlling itself that is!)
Title: Re: Arduino infrared problems
Post by: Nauge on Apr 13, 2009, 10:02 pm
David,

Thank you for the excellent piece of code. It worked well for me. If I might make a suggestion. When I connected O-scope to the send portion of the code I noticed that i was getting some intermittent gaps between the carrier frequency. It turns out they were some kind of interrupts perhaps from the UART. For a time sensitive code, I placed "noInterrupts()" before it sends out the whole string of data and placed an "interrupts()" after that portion of the code. After placing those functions I was able to recieve the data flawlessly. Thanks again for the great code :)
Title: Re: Arduino infrared problems
Post by: glt on Apr 20, 2009, 04:53 am
My thanks for the code too!. It worked as-is: copied, compiled uploaded and done!.  Works with sony remote, but Samsung remote returned 1 and -1...  In fact it is too fast. I get 3 codes per button press. With a delay(50), I get one code per press.

Excellent piece of software, compact and clean.

Update: duh! It says "for sony remote" :-)
Title: Re: Arduino infrared problems
Post by: glt on Apr 21, 2009, 11:44 pm
Hi,

I want to use the code inside a while loop. Because I have other code I would like the remote code to remain in a loop while there is still activity in the remote control (sort of to make it more efficient and maybe more responsive)

So my question is: what event would I use in the while loop?  I thought of having an interrupt update a flag, but since there are many pulses, there would be many interrupts, and I only need one interrupt per sequence of pulses. Thought about reading HIGH on the input pin, but these are pulses and sometimes will be LOW. What else can I use?

Thanks.
Title: Re: Arduino infrared problems
Post by: PlastBox on Apr 22, 2009, 12:05 am
glt: You want to run two different processes at the same time, is that is? One reading the remote, another doing whatever else needs to be done?

Sorry to say, as far as I know multithreading (multiple simultaneous processes) is not possible on the Atmega microcontrollers. It should still be doable though, having the arduino do two things fast enough for it to seem like they are happening at the same time.

What is the other process, other than monitoring the IR-signal, that you need the arduino to do?
Title: Re: Arduino infrared problems
Post by: BroHogan on Apr 22, 2009, 12:06 am
If you are looking for a non-blocking IR receiver, I'm using the following code which works pretty well.
Code: [Select]
//  attachInterrupt(1,IR_ISR,FALLING);  // Add to setup()

#define ir_pin 3                       // IR sensor on pin 3 - ISR1

// key types returned from get_remote()
#define ENTER 12    
#define OK    21
#define POWER 22
#define UP    17
#define DOWN  18
#define RIGHT 19
#define LEFT  20
#define SLEEP 55
#define INFO  59

// vars for IR_ISR() (must be global)
volatile boolean IR_Avail;             // flag set if IR has been  read
volatile unsigned int IR_Return;       // returns IR code received
volatile unsigned long ir_mask;        // Loads variable ir_string
volatile unsigned int ir_bit_seq;      // Records bit sequence in ir string
volatile unsigned int ir_string;       // Stores ir string

// Functions begin here . . . . . . .
void IR_ISR(){ // This ISR is called for EACH pulse of the IR sensor
 if(ir_bit_seq == 0){                 // it is the long start pulse
   for(int i = 0; i<20; i++){         // see if it lasts at least 2 ms
     delayMicroseconds(100); // 100
     if(digitalRead(ir_pin)) return;  // it's doesn't so get out (low active)
   }  
   ir_bit_seq = 1;                    // mark that the start pulse was received
   ir_mask = 1;                       // set up a mask for the next bits
   return;
 }

 delayMicroseconds(900);              // wait 900 us and test
 if(!digitalRead(ir_pin)) ir_string = ir_string | ir_mask;  // Stores 1 in bit
 ir_mask = ir_mask << 1;              // shifts ir_mask by one to the left
 ir_bit_seq++;                        // ir_bit_seq is incrimented by one
 if(ir_bit_seq == 12){                // after remote sends 12 bits it's done
   ir_mask = 63;                     // only want the last 6 bits - the command
   ir_string = ir_string & ir_mask;  // only keep last 6 bits
   IR_Return = ir_string;             // final result
   IR_Avail = true;                   // indicate new command received
   //digitalWrite(led_pin,HIGH);
   ir_bit_seq = 0;                    // clean up
   ir_string = 0;
   ir_mask = 0;
   for(int i = 0; i<25; i++){         // delay to stop repeat 10ms / loop ~250ms about right
     delayMicroseconds(10000);        // 16383 is maximum value so need to repeat
   }
 }
}


I wish I could properly credit the guy who posted it originally - it was in Exhibition a few months ago. I made some minor mods to it.

Perhaps it will help.
[edit] Then use something like
if(IR_Avail){
. . .
}

and check IR_Return
[/edit]

Title: Re: Arduino infrared problems
Post by: glt on Apr 22, 2009, 02:23 am
I guess I wasn't too clear in my question, but BroHogan answered it.  I need a non blocking IR receiver because the code in this thread just sits there and waits for a low pulse.  But I like this code very much, can it be made not to block?

Thanks.
Title: Re: Arduino infrared problems
Post by: BroHogan on Apr 22, 2009, 03:35 am
The sample I gave you is for a Sony remote BTW.

I've tried making the code in this thread non-blocking by using an ISR on the IR pin. I never had much luck. Maybe some smarter guy can make it work.

What I found is that once the ISR triggers you have to wait and process each pulse using pulsein(). If you get noise, the ISR can hang.

The code I posted doesn't work that way. Each pulse triggers the ISR and the function does not use pulsein() to wait on the pulse.

Again, maybe someone can get GetIRKey working non-blocking. I liked it too - it's a classic. However, I'm pretty satisfied with the code I posted. YMMV
Title: Re: Arduino infrared problems
Post by: glt on Apr 22, 2009, 07:47 am
I tried the following to make the code not block:

Interrupt when a pulse is detected. The ISR sets a flag and disables interrupts. The while loop sees that flat is set and calls getIRKey(). After printing, it enables interrupts.

It works but sometimes it gets stuck in the while loop waiting for the long pulse. disabling interrupts inside the ISR doesn't seem to disable interrupts. I can get out of the while loop by pressing the remote. But I can't think of a way to time out the while loop...

Title: Re: Arduino infrared problems
Post by: glt on Apr 22, 2009, 04:30 pm
I figured I get stuck in the while loop waiting for the long pulse, so even if it times out, the statement remains true (<2200). So I need a way to get out of the loop when it times out, something like <2200&&!=0  but this did not work...

I'll try

int longpulse=1;
while((longpulse=pulseIn(ir_pin))<2200)
{
 if longpulse=0 //timeout
 {
   break;
 }
}
Title: Re: Arduino infrared problems
Post by: glt on Apr 23, 2009, 06:49 am
Well I modified the code to work as non-blocking. It uses an interrupt service routine to set a flag.

When it times out because there are no long pulses, it takes 12 seconds to get out of the routine. This can be greatly optimized by specifying the timeout in the pulseIn calls, or using an if statement to skip them all.

Any suggestions to improve the code is appreciated.

One more thing: I removed the resistor from the IR receiver to pin2 and enabled the pull up resistor for pin2. This is how it is specified in the data sheet. The IR receiver is effectively a switch to Gnd when IR is detected and thus you need the pull-up resistor. (The data sheet says that the pull up is optional, but since it is there, I enabled it)

Here is the code:

Code: [Select]

#define ir_pin 2      //Sensor pin 1 wired through a 220 ohm resistor#define led_pin 13      

int debug = 0;            //Serial connection must be started to debug
int start_bit = 2000;      //Start bit threshold (Microseconds)
int bin_1 = 1000;      //Binary 1 threshold (Microseconds)
int bin_0 = 400;      //Binary 0 threshold (Microseconds)
int longpulse=1;        //If longpulse==0 it means pulseIn() timed out

volatile byte remoteOn = 0;  // ==1, means remote has been pressed

void setup() {
 // pinMode(led_pin, OUTPUT);      //No using
 pinMode(ir_pin, INPUT);
 digitalWrite(ir_pin, HIGH);      //We are not using a resistor in IR detector. Pull up
 pinMode(6, INPUT);            //Testing a button on pin 6 ensures remote code did not block
 digitalWrite(6, HIGH);        //Enable pull up for button. Button is a switch to GND
 Serial.begin(9600);
}

void loop() {
 while (remoteOn==1)
 {
   int key = getIRKey();                //Fetch the key
   Serial.print("Key Recieved: ");
   Serial.println(key);
   remoteOn=0;  //reset flag
   longpulse=1;  //reset longpulse
 }
 // The following code is test code to see if remote code did not block
 if (digitalRead(6)==0)
 {
   Serial.println("Button Pressed");
   delay (100);
 }
 attachInterrupt (0, remoting, RISING);
}

int getIRKey() {
 int data[12];
 while((longpulse=pulseIn(ir_pin, LOW)) < 2200)
 {
   if(longpulse==0) // if timed out
   {
     break;
   }
 }
 
 data[0] = pulseIn(ir_pin, LOW);      //Start measuring bits, I only want low pulses
 data[1] = pulseIn(ir_pin, LOW);
 data[2] = pulseIn(ir_pin, LOW);
 data[3] = pulseIn(ir_pin, LOW);
 data[4] = pulseIn(ir_pin, LOW);
 data[5] = pulseIn(ir_pin, LOW);
 data[6] = pulseIn(ir_pin, LOW);
 data[7] = pulseIn(ir_pin, LOW);
 data[8] = pulseIn(ir_pin, LOW);
 data[9] = pulseIn(ir_pin, LOW);
 data[10] = pulseIn(ir_pin, LOW);
 data[11] = pulseIn(ir_pin, LOW);

 delay(50); // to slow down the loop if needed

 if(debug == 1) {
   Serial.println("-----");
 }
 for(int i=0;i<11;i++) {              //Parse them
   if (debug == 1) {
       Serial.println(data[i]);
   }
   if(data[i] > bin_1) {              //is it a 1?
     data[i] = 1;
   }  else {
     if(data[i] > bin_0) {            //is it a 0?
       data[i] = 0;
     } else {
      data[i] = 2;                    //Flag the data as invalid; I don't know what it is!
     }
   }
 }

 for(int i=0;i<11;i++) {              //Pre-check data for errors
   if(data[i] > 1) {
     return -1;                       //Return -1 on invalid data
   }
 }

 int result = 0;
 int seed = 1;
 for(int i=0;i<11;i++) {              //Convert bits to integer
   if(data[i] == 1) {
     result += seed;
   }
   seed = seed * 2;
 }
 return result;                       //Return key number
}

void remoting()  // The ISR
{
 remoteOn=1;
}


Title: Re: Arduino infrared problems
Post by: nighto on Sep 28, 2009, 05:16 pm
Hello,

A little more general question how to send infrared commands to a DVD player? In other words how to blink the IR-LED propperly :)?

Regards,

Hannes
Title: Re: Arduino infrared problems
Post by: Things on Nov 03, 2009, 07:16 am
I have a panasonic remote here, and the power button seems to output 2 sets of data, but the problem is, I don't understand what its doing. The values seem to change each time I press the button  :o

This is the code I am using:

Code: [Select]
// 0.1 by pmalmsten http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1176098434
// 0.2 by farkinga
// 0.3 by farkinga - adds cool behaviors

#define IR_BIT_LENGTH 12    // number of bits sent by IR remote
#define BIT_1 1000       // Binary 1 threshold (Microseconds)
#define BIT_0 400           // Binary 0 threshold (Microseconds)
#define BIT_START 2000      // Start bit threshold (Microseconds)

#define IR_PIN 7            // Sensor pin 1 wired through a 220 ohm resistor
#define LED_PIN 10           // first LED output
#define POWER_PIN 11        // second LED output, corresponds to power button

#define DEBUG 1             // Serial connection must be started to debug

int runtime_debug = 0;      // flag to output raw IR pulse data
int output_key = 0;         // flag to print decoded key integers
int power_button = 0;       // flag to indicate if power LED is on
int power_level = 128;      // value (0-255) for power LED intensity

void setup() {
 pinMode(LED_PIN, OUTPUT);      //This shows when we're ready to recieve
 pinMode(POWER_PIN, OUTPUT);      //This is the "power on" indicator
 pinMode(IR_PIN, INPUT);
 digitalWrite(LED_PIN, LOW);
 Serial.begin(9600);
}

void loop() {
 digitalWrite(LED_PIN, HIGH);
 int key = get_ir_key();
 
 digitalWrite(LED_PIN, LOW);  // turn LED off while processing response
 do_response(key);
 delay(100);                  // short delay to cancel duplicate keypresses
}

/*
 wait for a keypress from the IR remote, and return the
 integer mapping of that key (e.g. power button on remote returns
 the integer 1429)
*/

int get_ir_key()
{
 int pulse[IR_BIT_LENGTH];
 int bits[IR_BIT_LENGTH];  

 do {} //Wait for a start bit
 while(pulseIn(IR_PIN, LOW) < BIT_START);

 read_pulse(pulse, IR_BIT_LENGTH);
 pulse_to_bits(pulse, bits, IR_BIT_LENGTH);
 return bits_to_int(bits, IR_BIT_LENGTH);
}

/*
 respond to specific remote-control keys with different behaviors
*/

void do_response(int key)
{  
 switch (key)
 {
   case 1437:  // record button
     Serial.println("toggle debug pulse");
     runtime_debug = 1 - runtime_debug;
     break;
   case 1498:  // display button
     Serial.println("Toggle key output");
     output_key = 1 - output_key;
     break;
   case 1429:  // power button
     Serial.println("Power");
     power_button = 1 - power_button;
     set_power();
     break;
   case 1424:  // channel up button
     Serial.println("Channel Up");
     break;      
   case 1425:  // channel down button
     Serial.println("Channel Down");
     break;
   case 3342:  // up rocker/pause
     power_level+=1;
     set_power();
     break;
   case 3343:  // down rocker/stop
     power_level-=1;
     set_power();
     break;      
   case 3344:  // left rocker/rewind
     if (power_level < 50)
     {
       power_level-=3;
     }
     else
     {
       power_level-=10;
     }
     set_power();
     break;
   case 3345:  // right rocker/fast forward
     if (power_level < 50)
     {
       power_level+=3;
     }
     else
     {
       power_level+=10;
     }
     set_power();
     break;
   case 3352:  // play button
     blip_power();
     break;      
   default:
     if (output_key)
     {
       Serial.print("Key ");
       Serial.print(key);
       Serial.println(" not programmed");
     }
     break;
 }
}

/*
 use pulseIn to receive IR pulses from the remote.
 Record the length of these pulses (in ms) in an array
*/

void read_pulse(int pulse[], int num_bits)
{
 for (int i = 0; i < num_bits; i++)
 {
   pulse[i] = pulseIn(IR_PIN, LOW);
 }
}

/*
 IR pulses encode binary "0" as a short pulse, and binary "1"
 as a long pulse.  Given an array containing pulse lengths,
 convert this to an array containing binary values
*/

void pulse_to_bits(int pulse[], int bits[], int num_bits)
{
 if (DEBUG || runtime_debug) { Serial.println("-----"); }
 
 for(int i = 0; i < num_bits ; i++)
 {
   if (DEBUG || runtime_debug) { Serial.println(pulse[i]); }
   
   if(pulse[i] > BIT_1) //is it a 1?
   {
     bits[i] = 1;
   }  
   else if(pulse[i] > BIT_0) //is it a 0?
   {
     bits[i] = 0;
   }
   else //data is invalid...
   {
     Serial.println("Error");
   }
 }
}

/*
 convert an array of binary values to a single base-10 integer
*/

int bits_to_int(int bits[], int num_bits)
{
 int result = 0;
 int seed = 1;
 
 //Convert bits to integer
 for(int i = 0 ; i < num_bits ; i++)
 {              
   if(bits[i] == 1)
   {
     result += seed;
   }
   
   seed *= 2;
 }
 
 return result;
}

/*
 set the brightness of the "power LED" depending on the power_level
 variable.
*/

void set_power()
{
 power_level = constrain(power_level, 0, 200);
 
 analogWrite(POWER_PIN, power_level * power_button);
 
 // if the power level is above the max or below the min...
 if ((power_level == 200) || (power_level == 0))
 {
   blink_led();
 }
}

/*
 make LED blink rapidly
*/

void blink_led()
{
 for (int i = 0; i < 5; i++)
 {
   analogWrite(LED_PIN, 0);
   delay(50);
   analogWrite(LED_PIN, 1);
   delay(50);
 }
}

/*
 neat little routine to fade both LEDs in a sequence.  Currently,
 this is called by do_response() when the "play" button is pressed.
*/

void blip_power()
{
 int max_val = 100;
 
 for (int i = 0; i < max_val; i++)
 {
   analogWrite(POWER_PIN, max_val-i);
   analogWrite(LED_PIN, i);
   delay(15);
 }

 for (int i = max_val; i >= 0; i--)
 {
   analogWrite(POWER_PIN, max_val-i);
   analogWrite(LED_PIN, i);
   delay(15);
 }

 set_power();  
}


And I get a few different results from the power button on my remote:
Code: [Select]
-----
543
544
541
537
537
537
543
543
544
543
538
537
-----
544
544
538
538
538
544
544
544
538
537
538
538

Code: [Select]
-----
538
538
539
544
543
544
538
537
538
538
544
544
-----
538
538
545
544
538
538
538
538
545
544
544
538


Any idea's how I can make it work with my remote?

Thanks :)


Title: Re: Arduino infrared problems
Post by: jrfitzny on Apr 08, 2010, 08:12 pm
I am successfully getting the remote to output a value for each button I press; however, I need to use the output to change the output PWM voltage.

For example: The PWM command for motor control is:
int motor_input = #  //the number being a value from 0-255

How do I get the IR output value to change the # in the motor input command?
Title: Re: Arduino infrared problems
Post by: Jeremyvnc on Apr 09, 2010, 12:06 am
Use something like this:
motor_input = valueFromIR/MAX_IR_VALUE_POSSIBLE * 255;  //scales ir value to 0-255
analogWrite(PWM_OUTPUT,motor_input);  uses PWM of Arduino to change motor speed.

Caution: Motors connected directly to the arduino should be very small!
Title: Re: Arduino infrared problems
Post by: jrfitzny on Apr 09, 2010, 12:32 am
I'm actually using the arduino to drive a MOSFET, which which control the motor. Thanks for the help!
Title: Re: Arduino infrared problems
Post by: jrfitzny on Apr 09, 2010, 10:02 pm
I'm using pmalmsten's code on pg 1 of this thread.

I added the following to the end; it uploads, but doesn't output any PWM voltage



int motor_pin = 10;  // define the pin which will send the motor commands
int motor_input = result;


void setup ();

 
pinMode (motor_pin, OUTPUT);

void loop ();

analogWrite(motor_pin,motor_input);} //uses PWM of Arduino to change motor speed.


Even if I change int_motor pin = (to a value 0-255) it still doesn't output a voltage. Any idea what I'm doing wrong?
Title: Re: Arduino infrared problems
Post by: gbulmer on Apr 09, 2010, 10:25 pm
If you Serial.println(motor_input);
what value do you get?

Have you tried using an LED+resistor in place of the MOSFET to debug it?
Does the LED come on?

GB
Title: Re: Arduino infrared problems
Post by: jrfitzny on Apr 10, 2010, 12:37 am
I tried Serial.PrintIn(motor_input)....the serial monitor is only reading the IR values

which shows Key Received: (number from 219-500+); depends on what button I'm pressing.

I'm actually trying the LED + resistor, but it's not coming on. I'll just insert the code, and if you could please troubleshoot it, i'd be in your debt. I put the //////////////// where the IR programming stops and the PWM programming begins

Code: [Select]

int ir_pin = 2;                        //Sensor pin 1 wired through a 220 ohm resistor
int led_pin = 13;                      //"Ready to Recieve" flag, not needed but nice
int debug = 0;                         //Serial connection must be started to debug
int start_bit = 2000;                  //Start bit threshold (Microseconds)
int bin_1 = 1000;                      //Binary 1 threshold (Microseconds)
int bin_0 = 400;                       //Binary 0 threshold (Microseconds)


void setup() {
 pinMode(led_pin, OUTPUT);            //This shows when we're ready to recieve
 pinMode(ir_pin, INPUT);
 digitalWrite(led_pin, LOW);          //not ready yet
 Serial.begin(9600);
}

void loop() {
 int key = getIRKey();                //Fetch the key
 Serial.print("Key Recieved: ");
 Serial.println(key);
}


int getIRKey() {
 int data[12];
 digitalWrite(led_pin, HIGH);         //Ok, i'm ready to recieve
 while(pulseIn(ir_pin, LOW) < 2200) { //Wait for a start bit
 }
 data[0] = pulseIn(ir_pin, LOW);      //Start measuring bits, I only want low pulses
 data[1] = pulseIn(ir_pin, LOW);
 data[2] = pulseIn(ir_pin, LOW);
 data[3] = pulseIn(ir_pin, LOW);
 data[4] = pulseIn(ir_pin, LOW);
 data[5] = pulseIn(ir_pin, LOW);
 data[6] = pulseIn(ir_pin, LOW);
 data[7] = pulseIn(ir_pin, LOW);
 data[8] = pulseIn(ir_pin, LOW);
 data[9] = pulseIn(ir_pin, LOW);
 data[10] = pulseIn(ir_pin, LOW);
 data[11] = pulseIn(ir_pin, LOW);
 digitalWrite(led_pin, LOW);

 if(debug == 1) {
   Serial.println("-----");
 }
 for(int i=0;i<11;i++) {              //Parse them
   if (debug == 1) {
       Serial.println(data[i]);
   }
   if(data[i] > bin_1) {              //is it a 1?
     data[i] = 1;
   }  else {
     if(data[i] > bin_0) {            //is it a 0?
       data[i] = 0;
     } else {
      data[i] = 2;                    //Flag the data as invalid; I don't know what it is!
     }
   }
 }

 for(int i=0;i<11;i++) {              //Pre-check data for errors
   if(data[i] > 1) {
     return -1;                       //Return -1 on invalid data
   }
 }

 int result = 0;
 int seed = 1;
 for(int i=0;i<11;i++) {              //Convert bits to integer
   if(data[i] == 1) {
     result += seed;
   }
   seed = seed * 2;
 }
 return result;                       //Return key number



/////////////////////////////////////////////////////////////////////

int motor_pin = 10;  // define the pin which will send the motor commands
int motor_input = result;


void setup ();

 
pinMode (motor_pin, OUTPUT);

void loop ();

analogWrite(motor_pin,motor_input); //uses PWM of Arduino to change motor speed.

Serial.println(motor_input);
}

Title: Re: Arduino infrared problems
Post by: gbulmer on Apr 16, 2010, 02:40 am
jrfitzny - sorry for the slow response, the email alert got lost in some other stuff.

Is this exactly the code, or have you changed it before posting it here?

Nothing after the ///////////////////////// will be run.
Is that what you meant to happen?

You might want to make a copy of the code, and then trim out the stuff you don't want. It's a bit confusing to decide whether there is a mistake, and it should be executed or not.

Have I misunderstood something?

The only code I can see which would control the motor is after the return statement, so it will never get done.
Code: [Select]
 return result;                       //Return key number



/////////////////////////////////////////////////////////////////////

int motor_pin = 10;  // define the pin which will send the motor commands
int motor_input = result;


void setup ();

 
pinMode (motor_pin, OUTPUT);

void loop ();

analogWrite(motor_pin,motor_input); //uses PWM of Arduino to change motor speed.

Serial.println(motor_input);


I suggest tidy up the code, and take all the code after return, delete what you dont want, and put the rest wherever it should be.

You almost certainly don't want this code in getIRKey
Code: [Select]
void setup ();

 
pinMode (motor_pin, OUTPUT);

void loop ();


pinMode should be set in the setup function.

HTH
GB
Title: Re: Arduino infrared problems
Post by: jrfitzny on Apr 16, 2010, 06:31 pm
Gbulmer,

Did exactly what you said...code now works like a charm!
Thanks for the help :)
Title: IR sensor works well withmega 8 & dn't  with 328 /168
Post by: prashant.park on Jun 04, 2010, 10:42 am
I am using TSOP 1838 IR receiver sensor to receive the signal,
surprisingly it gives readings with mega8 mcu, but it dosent work
with mega 328 or 168. however it dosent show any error while uploading the code. need support desperatly . . . . . :-?

Code: [Select]
int ir_pin = 2;    //Sensor pin 1, the data pin
unsigned long data[12];

void setup() {

 pinMode(ir_pin, INPUT);
  Serial.begin(9600);
}

void loop() {
 data[0] = pulseIn(ir_pin, LOW);    //Start measuring bits --the sensor defaults high, goes low on infrared
 data[1] = pulseIn(ir_pin, LOW);
 data[2] = pulseIn(ir_pin, LOW);
 data[3] = pulseIn(ir_pin, LOW);
 data[4] = pulseIn(ir_pin, LOW);
 data[5] = pulseIn(ir_pin, LOW);
 data[6] = pulseIn(ir_pin, LOW);
 data[7] = pulseIn(ir_pin, LOW);
 data[8] = pulseIn(ir_pin, LOW);
 data[9] = pulseIn(ir_pin, LOW);
 data[10] = pulseIn(ir_pin, LOW);
 data[11] = pulseIn(ir_pin, LOW);
 

 Serial.println("-----");    //Send them all
 Serial.println(data[0]);
 Serial.println(data[1]);
 Serial.println(data[2]);
 Serial.println(data[3]);
 Serial.println(data[4]);
 Serial.println(data[5]);
 Serial.println(data[6]);
 Serial.println(data[7]);
 Serial.println(data[8]);
 Serial.println(data[9]);
 Serial.println(data[10]);
 Serial.println(data[11]);
 
}