Hack Your VCR: Master Arduino Infrared Remote Control (NEC Protocol)

Hack Your VCR: Master Arduino Infrared Remote Control (NEC Protocol)


📑Table of Contents
What You'll Need 5 items
Arduino Uno R3
Buy
IR Receiver Module (VS1838B)
Buy
IR Remote Control
Buy
Breadboard
Buy
Jumper Wires
Buy

Affiliate links help support this site at no extra cost to you.

Welcome to Day 27. We have spent weeks connecting things with wires. Breadboard wires. USB cables. Jumper cables. It’s messy. It’s limiting. Today, we cut the cord.

We are entering the world of Wireless Communication. And we are starting with the technology that has been sitting on your coffee table for 40 years: Infrared (IR). By the end of this guide, you won’t just turn on an LED. You will decode the secret language of your Samsung TV remote. You will build a “Smart Plug” that turns on your desk lamp when you press “Volume Up”. You will become the master of the invisible waves.

Intro: Infrared Data

The Physics: What is Infrared?

Light is a wave. Our eyes can see wavelengths from 400nm (Violet) to 700nm (Red). If you make the wavelength just a little bit longer (700nm - 1mm), it becomes invisible to us. This is Infrared. It behaves exactly like visible light. It bounces off mirrors. It is blocked by walls. But to a silicon sensor (photodiode), it shines as bright as a flashlight.

Electromagnetic Spectrum

The Problem: The Sun is Loud

The sun pumps out massive amounts of IR radiation. Light bulbs emit IR. Your toaster emits IR. If we just flashed an IR LED to send data, the receiver would be blinded by the “ambient noise” of the universe. It would be like trying to whisper in a rock concert.

The Solution: Modulation (38kHz)

To fix this, engineers don’t just turn the LED ON. They blink it ON and OFF really fast—specifically 38,000 times per second (38kHz). The Receiver (VS1838B) is tuned to only see 38kHz.

  • Sunlight: Constant IR (DC). The receiver ignores it.
  • Remote: Blinking IR (AC). The receiver hears it. This is called Modulation. It is the secret sauce of reliability.

Carrier Frequency Modulation

The Hardware: VS1838B Receiver

You don’t need a PhD to use this. You need a VS1838B. It is a 3-pin black component with a metal cage. Inside, it has filters, amplifiers, and a demodulator. It outputs a clean digital signal (LOW/HIGH) that the Arduino can read easily.

Pinout:

  1. OUT (Signal): Goes to Arduino Pin 2.
  2. GND: Goes to GND.
  3. VCC: Goes to 5V.

VS1838B Pinout

Inside the Black Box: The Bandpass Filter

Why can you use your remote even with the lights on? The VS1838B isn’t just a “Light Sensor”. If it were, it would be useless during the day. Inside that black epoxy case is a high-tech Bandpass Filter.

  1. Optical Filter: The black plastic blocks visible light (Red, Green, Blue) but lets Infrared through.
  2. Electronic Filter: The chip inside waits for a signal pulsing at exactly 38kHz.
    • If a light shines steadily (Sun), the chip sees “0Hz”. Blocked.
    • If a hand waves (5Hz). Blocked.
    • If a fluorescent light flickers (120Hz). Blocked.
    • If an IR LED flickers at 38,000Hz. PASSED. This is why you can control your TV in a sunny living room. It is a masterpiece of analog engineering.

The Wiring

Simple. Connect the sensor to the breadboard. We will use Pin 2 because on many Arduinos, it supports interrupts (though the library handles any pin nicely).

Wiring Diagram

The Protocol: NEC Code

Most remotes use the NEC Protocol. It is a timing-based language.

  1. Leader Code: A 9ms burst followed by a 4.5ms space. This yells “INCOMING!”
  2. Address: 8 bits Identifying the device (e.g., “I am a Sony TV”).
  3. Command: 8 bits Identifying the button (e.g., “Volume Up”).
  4. Logical Inverse: The command is sent again, inverted, to check for errors.
  5. Stop Bit: End of message.

Why Hexadecimal? (0xFF, 0x5D)

You will see codes like 0xFFA25D. Why not just use “16753245”? Binary is too long: 1111 1111 1010 0010 0101 1101 Decimal is random: 16,753,245 Hexadecimal splits the binary into groups of 4.

  • 1111 = F
  • 1010 = A It maps perfectly to the bits. Low-level engineers love Hex because it reveals the structure of the data. Use it. Love it.

NEC Protocol Timing

Deep Dive: The Pulse Distance Coding

How does the receiver know the difference between a 0 and a 1? It is all about the Gap.

  • Logic 0: A 560µs pulse followed by a 560µs space. (Total 1.12ms)
  • Logic 1: A 560µs pulse followed by a 1690µs space. (Total 2.25ms)

The Arduino measures these gaps with microsecond precision. If the gap is short, it writes a 0 to the variable. If the gap is long, it writes a 1. This happens 32 times per message (8 bits Address + 8 bits ~Address + 8 bits Command + 8 bits ~Command).

Decoding Your Remote

We will use the IRremote library. Note: In 2024/2025, this library hit version 4.0+. The syntax changed drastically from the old tutorials you might find online. We will use the MODERN syntax.

Step 1: Install IRremote by Armin Joachimsmeyer via Library Manager.

The Code (The Sniffer): This code will print the Hexadecimal code of any button you press.

#include <IRremote.hpp> // Use the .hpp for v4.0+

const int IR_PIN = 2; // Receiver connected to Pin 2

void setup() {
  Serial.begin(9600);
  while (!Serial); // Wait for Serial to become ready
  Serial.println("IR Receiver Ready. Aim remote and fire!");

  // Start the receiver
  IrReceiver.begin(IR_PIN, ENABLE_LED_FEEDBACK);
}

void loop() {
  if (IrReceiver.decode()) {
    // We found a signal!
    
    // Print the raw protocol data (useful for debugging)
    Serial.println("----------------------------------------");
    Serial.print("Protocol: ");
    Serial.print(IrReceiver.getProtocolString());
    Serial.print(" | Command: 0x");
    Serial.println(IrReceiver.decodedIRData.command, HEX);
    
    // Check for "Repeat" flag (User holding button down)
    if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT) {
       Serial.println(" (Repeat)");
    }

    // Print Raw Timing Data (For unknown protocols)
    // IrReceiver.printIRResultRaw(&Serial);

    // Prepare for next signal
    IrReceiver.resume();
  }
}

Understanding the Output

When you press a button, you are looking for the Command. Ignore the Address for now (unless you have two of the same TV).

  • Volume Up: 0x5D (Example)
  • Volume Down: 0x1D (Example)
  • Power: 0x12 (Example)

The “Unknown” Protocol Sometimes you will see Protocol: UNKNOWN. This means your remote uses a weird standard (maybe an air conditioner?). In this case, you cannot use the Hex code easily. You must record the Raw Timings (the exact microseconds of every pulse) and play them back exactly. This is how “Universal Learning Remotes” work.

Serial Monitor Hex Codes

The Logic (Control the World)

Now that we know “Volume Up” is 0x5D, we can make the Arduino react. Let’s hook up a Relay (Day 18) to Pin 7. When we press Vol+, the Relay turns ON (Lamp ON). When we press Vol-, the Relay turns OFF (Lamp OFF).

#include <IRremote.hpp>

const int IR_PIN = 2;
const int RELAY_PIN = 7;

// CHANGE THESE to matches your specific remote!
const int CODE_VOL_UP = 0x5D; // Example
const int CODE_VOL_DOWN = 0x1D; // Example

void setup() {
  Serial.begin(9600);
  IrReceiver.begin(IR_PIN);
  pinMode(RELAY_PIN, OUTPUT);
  Serial.println("Smart Plug Ready.");
}

void loop() {
  if (IrReceiver.decode()) {
    int command = IrReceiver.decodedIRData.command;
    
    Serial.print("Received: 0x");
    Serial.println(command, HEX);

    // The Magic Switching Logic
    if (command == CODE_VOL_UP) {
      Serial.println("Turning Lamp ON");
      digitalWrite(RELAY_PIN, HIGH);
    } 
    else if (command == CODE_VOL_DOWN) {
      Serial.println("Turning Lamp OFF");
      digitalWrite(RELAY_PIN, LOW);
    }

    IrReceiver.resume(); // Essential! Don't forget this.
  }
}

Smart Plug Project

Sending Signals (The Universal Remote)

Receiving is fun. Sending is power. You can program your Arduino to turn off every TV in a bar (The TV-B-Gone concept). To send IR, you simply connect an IR LED to Pin 3 (PWM). Crucial: You cannot drive an IR LED directly from a pin for long ranges. You need a transistor (2N2222) to pump 100mA through it for a strong signal.

#include <IRremote.hpp>

const int SEND_PIN = 3; // Fixed for Uno in library

void setup() {
  Serial.begin(9600);
  IrSender.begin(SEND_PIN); // Initialize sender
}

void loop() {
  Serial.println("Sending MUTE command...");
  
  // Send NEC code (Address 0x00, Command 0x5D, Repeats 0)
  // You need to know the full Address/Command from Part 1
  IrSender.sendNEC(0x00, 0x5D, 0); 
  
  delay(5000); // Annoy people every 5 seconds
}

IR Transmitter Circuit

The “Send Raw” Technique (For Air Conditioners)

TVs use short codes (32 bits). Air Conditioners send massive packets (100+ bits). They send the entire state (Temp, Fan, Mode, Swing) every single time you press a button. Standard sendNEC won’t work. You need IrSender.sendRaw(rawData, length, 38).

  1. Capture the raw timing array using printIRResultRaw.
  2. Copy that huge array into your code.
  3. Blast it out.

Troubleshooting

1. Code is 0x0 or Random? If you hold the button down, many remotes send a “Repeat Code” (Flag). In the NEC protocol, this is a special short signal that says “Use the previous command again”. If you are writing code to change volume, you WANT to detect this.

  • Without Repeat Logic: You have to press Vol+ 50 times.
  • With Repeat Logic: You hold Vol+ and it zooms up. if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT) is your friend.

2. Sunlight Issues If your project works indoors but fails outdoors, that’s the sun. Sunlight saturates the sensor. Fix: Put the sensor in a black tube (like a straw) to block side-light.

Sunlight Interference

Challenge: The Secret Knock

Remotes are boring. Build a “Secret Knock” receiver. Instead of checking for a specific button, checking for a specific Timing Sequence. Or, create a “Laser Tripwire” using a continuous 38kHz beam. If the beam breaks, the alarm sounds.

Challenge 2: DIY Laser Tag

You have a transmitter (IR LED). You have a receiver. You have the building blocks of Laser Tag.

  1. The Gun: An Arduino Nano with a button and IR LED. When pressed, it sends 0xA1 (Team A, Player 1).
  2. The Vest: An Arduino Uno with a Receiver and a Piezo Buzzer.
  3. The Code:
    if (command == 0xA1) {
       tone(8, 1000, 500); // Hit by Player 1!
       lives--;
    }

Use a lens to focus the IR LED beam for range. Suddenly, you aren’t just blinking LEDs. You are building a game for your friends.

The Engineer’s Glossary (Day 27)

  • IR (Infrared): Light waves >700nm. Invisible heat radiation.
  • Modulation: Blinking a signal to distinguish it from noise.
  • Carrier Frequency: The speed of the blink (38kHz for TV remotes).
  • NEC Protocol: The standard language of Japanese consumer electronics.
  • Photodiode: A semiconductor that converts light into electricity.

Conclusion

You have mastered the invisible spectrum. You can now control 110V appliances from your couch. You can clone your lost remote. You can build robots that talk to each other using flashes of light.

Next Up: We stay wireless. But IR requires “Line of Sight”. You have to point at it. Tomorrow, we break down walls. We are moving to Radio Frequency (RF 433MHz). We will send data through walls, across the house, and build a long-range weather station. See you on Day 28.

Comments