User avatar
joan
Posts: 14876
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Decoding remote control infrared pulses

Fri Sep 28, 2012 9:58 pm

I found a spare IR receiver from some I bought years ago for a LIRC board.

It was surprisingly easy to interface to the Pi and may be useful as a remote control in robotics type applications.

Mine is a http://uk.rs-online.com/web/p/ir-remote ... r/6548930/ but any similarly specified device should work.

Pin 1 to a gpio input, pin 2 to ground, pin 3 to 5V. Originally I fed the gpio input via a voltage divider (resistor pair) but that didn't work so I made a direct connection.

Code: Select all

/* -----------------------------------------------------------------------
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <sys/time.h>

#include <wiringPi.h>

#define IR_PULSES 11

#define MS10 10000 /* 10 ms timeout value */
#define STARTBIT 2200
#define BIT1     1000
#define BIT0      400

#define IR_PIN    23

int pulseIn(int pin, int level, int timeout)
{
   struct timeval tn, t0, t1;

   long micros;

   gettimeofday(&t0, NULL);

   micros = 0;

   while (digitalRead(pin) != level)
   {
      gettimeofday(&tn, NULL);

      if (tn.tv_sec > t0.tv_sec) micros = 1000000L; else micros = 0;
      micros += (tn.tv_usec - t0.tv_usec);

      if (micros > timeout) return 0;
   }

   gettimeofday(&t1, NULL);

   while (digitalRead(pin) == level)
   {
      gettimeofday(&tn, NULL);

      if (tn.tv_sec > t0.tv_sec) micros = 1000000L; else micros = 0;
      micros = micros + (tn.tv_usec - t0.tv_usec);

      if (micros > timeout) return 0;
   }

   if (tn.tv_sec > t1.tv_sec) micros = 1000000L; else micros = 0;
   micros = micros + (tn.tv_usec - t1.tv_usec);

   return micros;
}

int getIRkey()
{
   int pulse[IR_PULSES];
   int i;
   int result;

   while (pulseIn(IR_PIN, LOW, MS10) < STARTBIT); /* wait for a start bit */
  
   for (i = 0 ; i < IR_PULSES ; i++) pulse[i] = pulseIn(IR_PIN, LOW, MS10);
  
   result = 0;

   for (i = 0 ; i < IR_PULSES ; i++)
   {	    
      if      (pulse[i] > BIT1) result |= (1<<i);
      else if (pulse[i] < BIT0) return -1;
   }

   return result;
} 

int main (int argc, char *argv[])
{
   int key;

   if (wiringPiSetupGpio () == -1)
   {
      fprintf (stderr, "Can't initialise wiringPi: %s\n", strerror (errno)) ;
      return 1 ;
   }

   pinMode(IR_PIN, INPUT);
 
   while (1)
   {
      key = getIRkey();
      printf("%d\n", key);
   }
}
I got results from some remote controls but not others. I don't know why, but I'm not familiar with IR protocols. For my needs I only need to find one remote control which works.

thisoldgeek
Posts: 5
Joined: Mon Oct 29, 2012 2:20 am

Re: Decoding remote control infrared pulses

Mon Oct 29, 2012 2:27 am

I have the wiringPi Library from git://git.drogon.net/wiringPi installed. When I try to compile your code, I get the following:

Code: Select all

gcc -o remote remote.c
/tmp/ccYw5C6J.o: In function `pulseIn':
remote.c:(.text+0x1a0): undefined reference to `digitalRead'
/tmp/ccYw5C6J.o: In function `main':
remote.c:(.text+0x2f4): undefined reference to `wiringPiSetupGpio'
remote.c:(.text+0x384): undefined reference to `pinMode'
collect2: ld returned 1 exit status
I/m a n00b on the Pi and compiling C in Linux, previous experience was a lot of arduino. Something I'm doing wrong? Pulled the wrong wiringPi Library?

-TIA

User avatar
joan
Posts: 14876
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Decoding remote control infrared pulses

Mon Oct 29, 2012 8:23 am

The linker is reporting it can't find various functions from the wiringPi library. You need to tell gcc to link in the library.

You do that by

gcc -o remote remote.c -lwiringPi

That will compile remote.c, link it with the wiringPi library and produce an executable called remote.

thisoldgeek
Posts: 5
Joined: Mon Oct 29, 2012 2:20 am

Re: Decoding remote control infrared pulses

Mon Oct 29, 2012 5:33 pm

Thanks, the compiler directive worked a treat!

rotflcopter
Posts: 2
Joined: Wed Aug 01, 2012 7:01 pm

Re: Decoding remote control infrared pulses

Sat Nov 10, 2012 7:34 pm

Hello, I have one question.

I am getting the same output on every button I press... Is that normal? How can I recognize which button was pressed?

User avatar
joan
Posts: 14876
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Decoding remote control infrared pulses

Sat Nov 10, 2012 7:55 pm

No, unless you want a one command remote controller.

As I originally said it worked with some remotes but not others. All I can suggest is you muck about with the code and print diagnostics about the pulses actually being received.

amfasis
Posts: 2
Joined: Sun Jul 28, 2019 9:35 pm

Re: Decoding remote control infrared pulses

Sun Jan 26, 2020 7:26 pm

Allthough it's been 8 years since this post, I needed a simple code like this using wiringPi (don't like pigpio), but had to fiddle a bit with it. It prints the pulse lengths and the converted key. It's not 100% percent accurate for each button press, but if you get the same number multiple times, you know you got it.

This is my result:

Code: Select all


/* -----------------------------------------------------------------------
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <sys/time.h>

#include <wiringPi.h>

#define IR_PULSES 35

#define TIMEOUT 20000 /* 20 ms timeout value (first pulse should be shorter) */
#define BIT1     1000

#define IR_PIN    22

int pulseIn(int pin, int timeout, long *us_zero, long *us_one)
{
   long start = micros();
   *us_zero = 0;
   *us_one = 0;

   while (digitalRead(pin) == LOW)
   {
      if(micros() - start > timeout)
         return 0;
   }
   *us_one = micros() - start;

   start = micros();
   while (digitalRead(pin) == HIGH)
   {
      if(micros() - start > timeout)
         return 0;
   }
   *us_zero = micros() - start;

   return 1;
}

int getIRkey()
{
   long high[IR_PULSES];
   long low[IR_PULSES];
   int i;
   int result;

   while(digitalRead(IR_PIN) == HIGH)
      ;

   for (i = 0; i < IR_PULSES; i++)
   {
      pulseIn(IR_PIN, TIMEOUT, &low[i], &high[i]);
   }


   for(i = 0;i < IR_PULSES;++i)
   {
      printf("H=%ld, L=%ld\n", high[i], low[i]);
   }

   result = 0;
   for (i = 1; i < IR_PULSES;++i)
   {
      if(low[i] > BIT1)
         result |= (1 << (32 - i));
   }

   return result;
} 

int main (int argc, char *argv[])
{
   int key;

   if (wiringPiSetupGpio () == -1)
   {
      fprintf (stderr, "Can't initialise wiringPi: %s\n", strerror (errno)) ;
      return 1 ;
   }

   pinMode(IR_PIN, INPUT);
 
   while (1)
   {
      key = getIRkey();
      printf("key: %X\n", key);
   }
}


Return to “Automation, sensing and robotics”