Society of Robots - Robot Forum
Electronics => Electronics => Topic started 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
-
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.
-
Thanks for that Soeren :)
I'll have a go at this after school tomorrow, and I'll post the results
-HyperNerd
-
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
-
Here is the code to read the remote in Arduino:
//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.
-
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:
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.