Society of Robots - Robot Forum

Electronics => Electronics => Topic started by: HyperNerd on February 28, 2010, 03:16:26 PM

Title: IR Robot - Figuring out the protcol
Post by: HyperNerd on February 28, 2010, 03:16:26 PM
I'm trying to add IR control to a basic Arduino robot with this (http://www.radioshack.com/product/index.jsp?sr=1&cp=&kw=ir&productId=2049727&parentPage=search&origkw=ir&tab=support) IR Receiver which I bought when I was on holiday in Florida last summer.

I'm far too poor to buy a remote specifically for this project, so I will NOT be using the Sharp protocol, which is the most popular for some reason.

I will instead be using the remote to my stereo, which is a Morphy Richards (never heard of them). I connected the receiver to a PICKit 2 set as a logic analyser, and I captured the attached outputs.

The pictures are of the 1 to 5 buttons pressed (in that order).

I need some help figuring out the protocol this remote uses, so I can write some code to decipher it.

 -HyperNerd
Title: Re: IR Robot - Figuring out the protcol
Post by: Soeren on February 28, 2010, 03:57:07 PM
I need some help figuring out the protocol this remote uses, so I can write some code to decipher it.
Not much of a code breaker, are you?  ;D

I don't recognise the protocol from memory, but it's quite easy.
First comes the extra wide start bit, then 8 narrow pulses (let's call them "0"s) followed by 10 wide pulses ("1"s).
This you just scan and drop.
Then comes the interesting bits, part 1, in the next 3 bits
Then five bits that you can discard like the first 19 (probably address codes/device ID).
Then 3 bits which is part 2 of the code, or rather the complementary of the "part 1" 3 bits.
And finally, 3 "stop" bits to throw away as well.

Looking at "Part 1" it is
000
100
010
110
001

Now if you read that backwards (you could turn them in software), they reads:
000 (0 = button 1)
001 (1 = button 2)
010 (2 = button 3)
011 (3 = button 4)
100 (4 = button 5)

I don't know if you intend to use more buttons, or if that's the case, whether they all oblige to that, but you should be able to verify that in a couple of minutes.
Title: Re: IR Robot - Figuring out the protcol
Post by: HyperNerd on February 28, 2010, 04:14:19 PM
Thanks for that Soeren :)

I'll have a go at this after school tomorrow, and I'll post the results

-HyperNerd
Title: Re: IR Robot - Figuring out the protcol
Post by: HyperNerd on March 01, 2010, 11:44:36 AM
Okie doke,

I've now gone through and recorded the binary output of all 32 buttons on the remote (it took like, half an hour) ;D

You can see the document here: http://spreadsheets.google.com/ccc?key=0Aujlo5wOvotIdDZTbTJNcmdIVUhMR1FtN2h4Vms0dFE&hl=en (http://spreadsheets.google.com/ccc?key=0Aujlo5wOvotIdDZTbTJNcmdIVUhMR1FtN2h4Vms0dFE&hl=en)

As you can see, each code starts with 8 '0's followed by 8 '1's. Each code ends with '101'.

EDIT: Added a third column to the spreadsheet, with the header and stop bits chopped off.

EDIT 2: Added 4th column with decimal value of 3rd column.

 -HyperNerd
Title: Re: IR Robot - Figuring out the protcol
Post by: Ro-Bot-X on March 01, 2010, 08:43:31 PM
Here is the code to read the remote in Arduino:
Code: [Select]
//original code from Arduino Forum, users pmalmsten and David Cuartielles
// link: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1176098434/0#0

#define IR_Pin  4 // digital pin 4
#define ledPin 13       // digital pin 13                          

#define btnDown    145
#define btnUp      144
#define btnLeft    146
#define btnRight   147
#define btnStop    1432

// remote control variables
#define start_bit  2200 // Start bit threshold (Microseconds)
#define bin_1  1000        // Binary 1 threshold (Microseconds)
#define bin_0  400              // Binary 0 threshold (Microseconds)

void setup(){
  pinMode(ledPin, OUTPUT);
  pinMode(IR_Pin, INPUT);

  //hardware serial
  Serial.begin(9600);
}

void loop(){
  Get_IR_Command();

}

void Get_IR_Command() {
  int key = getIRKey();    //Fetch the key
  if (key != -1) {
      Serial.print("Key: ");
      Serial.print(key, DEC);
  }
  // do something with the key...
  switch (key) {    
    case btnLeft:
      TurnLeft();
      break;
      
    case btnRight:    
      TurnRight();
      break;
      
    case btnUp:
      Forward();
      break;  
      
    case btnDown:
      Reverse();
      break;

    case btnStop:
      Stop();
      break;
  }  
}

//--------------------------
int getIRKey() {
  int data[12]; //adjust this to match the number of bits your remote sends
  digitalWrite(ledPin, HIGH);   //Ok, i'm ready to recieve  
  while(pulseIn(IR_Pin, LOW) < start_bit) { //Wait for a start bit
  }
  for(int i=0;i<11;i++){
    data[i] = pulseIn(IR_Pin, LOW);   //Start measuring bits, we only want low pulses
  }
  digitalWrite(ledPin, LOW);          //Done receiving
 
  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
}
 


Of course, you need to add your Forward, Reverse, Left, Right, Stop functions. You will see on the Serial Monitor the values each remote button sends, you need to modify the buttons defines accordingly.
Title: Re: IR Robot - Figuring out the protcol
Post by: Soeren on March 02, 2010, 03:53:27 PM
Hi,

I've now gone through and recorded the binary output of all 32 buttons on the remote (it took like, half an hour) ;D
Oh, I meant that you should make the application and then scan the codes. That scan would have been a few minutes.


As you can see, each code starts with 8 '0's followed by 8 '1's. Each code ends with '101'.

EDIT: Added a third column to the spreadsheet, with the header and stop bits chopped off.

EDIT 2: Added 4th column with decimal value of 3rd column.
You should have gone further, like following the pattern I outlined.
This shows the column "Unique code" parted up with the middle "010" dropped:
Code: [Select]
Button     UC1 Decimal          UC2       Decimal
Standby   10001    17          01110     14
Timer     10101    21          01010     10
Sleep     10011    19          01100     12
Mode      10111    23          01000      8
Function  00000     0          11111     31
1         11000    24          00111      7
2         11100    28          00011      3
3         11010    26          00101      5
Band      00100     4          11011     27
4         11110    30          00001      1
5         11001    25          00110      6
6         11101    29          00010      2
Mute      00001     1          11110     30
7         11011    27          00100      4
8         11111    31          00000      0
9         01000     8          10111     23
Tray      00110     6          11001     25
0         01100    12          10011     19
Add 10    01010    10          10101     21
Memory    01110    14          10001     17
Down      01001     9          10110     22
Up        01101    13          10010     18
Play      01011    11          10100     20
Stop      01111    15          10000     16
Auto Scan 10000    16          01111     15
Select    10100    20          01011     11
Info      10010    18          01101     13
Setup     10110    22          01001      9
Bass      00010     2          11101     29
EQ        00101     5          11010     26
Vol-      00011     3          11100     28
Vol+      00111     7          11000     24
Whether you use the left side or its complement ("1"s are made "0"s and v.v.) right side doesn't matter. Perhaps the way to go is scan and then only keep the last 5 bits.

The reason for the complement is error checking and discarding of codes that don't match up.
By EXOR'ing a 5 bit number and its complement, you get 31 if there's no error.

IOW, you don't need to work on numbers above 31.