Appearance
Simple Activities - Decode IR Signal
Problem Statement
- Write a code to Alphabot so that when a button on IR remote is pressed the respective command should be Displayed in the Serial Monitor
Code
#define IR 4 // IR remote receiver pin
// Remote key codes (adjust based on your remote)
#define KEY2 0x18 // Key:2 (Forward)
#define KEY8 0x52 // Key:8 (Backward)
#define KEY4 0x08 // Key:4 (Left)
#define KEY6 0x5A // Key:6 (Right)
#define KEY5 0x1C // Key:5 (Stop)
#define Repeat 0xFF // Key hold repeat code
#include <Adafruit_NeoPixel.h>
#define PIN 7
Adafruit_NeoPixel RGB = Adafruit_NeoPixel(4, PIN, NEO_GRB + NEO_KHZ800);
unsigned long lasttime = 0;
unsigned char results;
byte flag = 0;
int Speed = 180; // Default Speed (0-255)
char IR_decode(unsigned char *code);
void translateIR();
void setup() {
Serial.begin(115200);
pinMode(IR, INPUT);
Serial.println("IR Remote Control Robot - Ready!");
}
void loop() {
if (IR_decode(&results)) {
flag = 1;
lasttime = millis();
translateIR();
} else {
if (flag == 1 && (millis() - lasttime > 150)) {
flag = 0;
Serial.println("Stopping (no signal)");
}
}
}
// Decodes IR signals
char IR_decode(unsigned char *code) {
char value = 0; // Track the values (1 or 0)
unsigned int count = 0; // Variable used to prevent infinite loop
unsigned char i, index = 0, cnt = 0, data[4] = {0, 0, 0, 0}; // 4 byte IR code is stored (32 bits = 4 Bytes Using NEC Protocol)
// When a Signal is Detected IR Reciever Pulls 'LOW' value
if (digitalRead(IR) == LOW) {
// A IR Signal Always Starts with long LOW Pulse (9ms)
count = 0;
while (digitalRead(IR) == LOW && count++ < 200) {
delayMicroseconds(60);
}
// Also IR Signal Always Have 4.5ms HIGH Pulse after 9ms Short Pulse
count = 0;
while (digitalRead(IR) == HIGH && count++ < 80) {
delayMicroseconds(60);
}
// Decoding All The 32 Bits one by one
for (i = 0; i < 32; i++) {
count = 0;
while (digitalRead(IR) == LOW && count++ < 15) { // Always The First Short LOW Pulse is Ignored
delayMicroseconds(60);
}
count = 0;
while (digitalRead(IR) == HIGH && count++ < 40) { // Check Wether Its Long HIGH Pulse or Short HIGH Pule
delayMicroseconds(60);
}
if (count > 20) { // If count > 20 , Its a Long HIGH Pulse . So Putting 1 In correct position of Memory Using BITWISE Operator (<<).
data[index] |= (1 << cnt);
}
if (cnt == 7) { // We Have 8 Bits In a byte. Only Moves To Next Byte when all 8 Bits are stores .
cnt = 0;
index++;
} else {
cnt++;
}
}
// Validate checksum
// If data[0] = 0x00, then data[1] = 0xFF → 0x00 + 0xFF = 0xFF
// If data[2] = 0x18, then data[3] = 0xE7 → 0x18 + 0xE7 = 0xFF
// If the sum is 0xFF (No Transmission error) Giving value = 1
if (data[0] + data[1] == 0xFF && data[2] + data[3] == 0xFF) {
*code = data[2];
value = 1;
}
// When you hold a button, the remote doesn’t resend the full command. Instead, it sends a shortcut: 0xFFFFFFFF (all bytes = 0xFF).
// So Checking all 4 bytes are Repeating (0xFF)
else if (data[0] == 0xFF && data[1] == 0xFF && data[2] == 0xFF && data[3] == 0xFF) {
*code = Repeat;
value = 1;
}
}
return value;
}
// Maps IR codes to actions
void translateIR() {
switch (results) {
case KEY2:
Serial.println("Moving FORWARD");
break;
case KEY8:
Serial.println("Moving BACKWARD");
break;
case KEY4:
Serial.println("Turning LEFT");
break;
case KEY6:
Serial.println("Turning RIGHT");
break;
case KEY5:
Serial.println("STOPPED");
break;
default:
Serial.println("Unknown IR code");
}
}
Output
Exercise 🤖
- Try to code Yourself and Print the Value When the button is pressed