In the first article of the series, I explained how to break the code of a standard infrared remote control. In this article, we will use these results to control real world devices. The so called “real world devices” are, at this point of the project, three LEDs. I’ll keep lamps and washing machines control for the next article about X-10 control.
The first step is to convert the pulses we receive into streams of bits. The remote we will use for this project is an old air conditioning remote control. Following are the results for the remote control protocol:
- Threshold start pulse duration: 4000 micro seconds
- Threshold “1” bit pulse duration: 1500 micro seconds
- Threshold “0” bit pulse duration: 400 micro seconds
- Threshold repeat pulse duration: 2000 micro seconds
- Bit stream length: 32 bits
These values are used to build binary streams to reconstruct the 32 bit commands emitted by the remote control. Once the code values are known, we can add behavior in our micro controller. The command code is built using X-Or operations with the bits received from the remote.
The power-on/power-off command of our remote control match the decimal number 279939191. When the button is pressed, the red LED is toggled on/off. The green LED is turned off during the time the Arduino is processing a command. If a new command is sent while the green LED is off, the program wont be able to catch it. Finally, the yellow led is flashes ON for 50 milliseconds every time a repeat command is received.
Using this code you can control about anything you want using an infrared remote control. In the next article we will control lamps through X-10 power line protocol.
Philippe Chrétien
#define DEBUG 0 #define IR_LED 7 #define GREEN_LED 6 #define RED_LED 5 #define YELLOW_LED 4 #define MAX 128 #define MICRO_STEP 10 #define IDLE_PULSE 10000 #define START_PULSE 4000 #define REPEAT_PULSE 2000 #define ONE_PULSE 1500 #define ZERO_PULSE 400 unsigned long pulses[MAX]; unsigned long code = 0; int red_led_state = 0; void setup() { pinMode(IR_LED, INPUT); pinMode(RED_LED, OUTPUT); pinMode(GREEN_LED, OUTPUT); pinMode(YELLOW_LED, OUTPUT); digitalWrite(RED_LED, LOW); digitalWrite(GREEN_LED, HIGH); digitalWrite(YELLOW_LED, LOW); // For debug Serial.begin(115200); } void loop() { // The IR receiver output is set HIGH until a signal comes in ... if( digitalRead(IR_LED) == LOW) { // No command can be received while the green LED is off digitalWrite(GREEN_LED, LOW); //Start receiving data ... int count = 0; // Number of pulses int exit = 0; while(!exit) { while( digitalRead(IR_LED) == LOW ) delayMicroseconds(MICRO_STEP); // Store the time when the pulse begin unsigned long start = micros(); int max_high = 0; while( digitalRead(IR_LED) == HIGH ) { delayMicroseconds(MICRO_STEP); max_high += MICRO_STEP; if( max_high > IDLE_PULSE ) { exit = 1; break; } } unsigned long duration = micros() - start; pulses[count++] = duration; } // Build code from pulses int repetitions = 0; int bit_position = 0; unsigned long bit = 2147483648; // 10000000000000000000000000000000 in binary unsigned long new_code = 0; for(int i=0; i<count; i++) { if(pulses[i] > IDLE_PULSE) { // Ignore very long pulses continue; } else if(pulses[i] > START_PULSE) { // Start pulse received ... start counting bits new_code = 0; bit_position = 0; } else if(pulses[i] > REPEAT_PULSE) { // Repetition command ... no bit pulses here. repetitions++; } else if(pulses[i] > ONE_PULSE) { // Receives "1" if(DEBUG) Serial.print("1"); new_code |= bit >> bit_position++; } else if(pulses[i] > ZERO_PULSE) { // Receives "0" if(DEBUG) Serial.print("0"); bit_position++; } } if( new_code ) { // This was not a repeat command code = new_code; } // Display the code received and number of bits or, repetitions. if(DEBUG) { if( !new_code) { Serial.print(" "); } Serial.print(" "); Serial.print(bit_position, DEC); Serial.print(" bits "); Serial.print(repetitions, DEC); Serial.print(" repetition(s) code = "); Serial.print(code, BIN); Serial.print(" ("); Serial.print(code, DEC); Serial.print(")"); Serial.println(""); } // Flashes the yellow LED for every repeat commands if( repetitions > 0 ) { for( int i=0; i<repetitions; i++) { digitalWrite(YELLOW_LED, HIGH); delay(50); digitalWrite(YELLOW_LED, LOW); delay(50); } } // Toggle red LED when power button command is received if( code == 279939191 && bit_position > 0) { red_led_state ^= 1; if(red_led_state) digitalWrite(RED_LED, HIGH); else digitalWrite(RED_LED, LOW); } // Ready to process an other command digitalWrite(GREEN_LED, HIGH); } }