The Physics of 940nm Light and 38kHz Modulation

When you integrate an arduino infrared remote into a microcontroller project, you are relying on a localized optical communication link. Infrared (IR) light sits just beyond the visible spectrum, with maker-grade remote systems almost universally peaking at a 940nm wavelength. This specific wavelength is chosen because it aligns perfectly with the peak sensitivity of silicon photodiodes while avoiding the highest intensity bands of ambient solar radiation.

However, simply turning an IR LED on and off is insufficient for reliable data transmission. Ambient light sources—including sunlight and incandescent bulbs—emit massive amounts of broadband infrared noise. To solve this, IR remotes use carrier modulation. The 940nm light is pulsed at a specific carrier frequency, almost always 38kHz (a 26.3-microsecond period). The receiver module contains an internal bandpass filter tuned exclusively to 38kHz, allowing it to strip away the DC and low-frequency ambient light noise and output a clean, demodulated digital baseband signal to the Arduino's GPIO pin.

Receiver Hardware: VS1838B vs. TSOP38238

The demodulation process is handled by a 3-pin IR receiver module. While thousands of maker kits ship with the generic VS1838B (often branded as HX1838), professional and high-reliability designs utilize the Vishay TSOP38238. Understanding the difference in their internal Automatic Gain Control (AGC) algorithms is critical for preventing edge-case failures in your sketches.

Feature Generic VS1838B (HX1838) Vishay TSOP38238
Typical Price (2026) $0.10 - $0.15 (bulk) $1.60 - $2.10 (Mouser/DigiKey)
AGC Tuning Profile AGC2: Suppresses continuous data bursts AGC3: Optimized for continuous data streams
Supply Voltage 2.7V to 5.5V 2.5V to 5.5V
Best Application Basic hobby kits, simple NEC 24-key remotes Industrial control, high-noise environments, RC5/Sony protocols
Noise Rejection Low (prone to phantom triggers from CFL/SMPS noise) High (integrated envelope detector and suppression logic)

The VS1838B utilizes an AGC algorithm designed to mute the receiver if it detects a continuous 38kHz signal, assuming it is ambient noise rather than data. While this works for the standard NEC protocol (which features distinct gaps between pulses), it can cause the receiver to "blind" itself when decoding protocols with longer continuous burst trains, like Philips RC5. The TSOP38238 handles these continuous streams flawlessly, making it the superior choice for universal remote decoding projects.

Anatomy of the NEC Protocol

The vast majority of cheap, credit-card-style 24-key IR remotes bundled with Arduino starter kits use the NEC IR protocol (originally developed for the uPD6121G IC). The NEC protocol uses pulse-distance encoding, where the length of the space (the "off" time) determines whether a bit is a logical 0 or 1, while the burst (the "on" time) remains constant.

Timing Specifications

To decode the signal manually via pin-change interrupts, or to understand what libraries like Arduino-IRremote are doing under the hood, you must memorize the NEC timing matrix:

  • Carrier Frequency: 38kHz
  • Header (Preamble): 9ms burst (9000µs) followed by a 4.5ms space (4500µs). This alerts the receiver that a data frame is incoming.
  • Logical 0: 562.5µs burst followed by a 562.5µs space (Total bit time: 1.125ms).
  • Logical 1: 562.5µs burst followed by a 1.6875ms space (Total bit time: 2.25ms).
  • Frame Structure: 8-bit Address + 8-bit Logical Inverse Address + 8-bit Command + 8-bit Logical Inverse Command (32 bits total).
Pro-Tip on Data Validation: The NEC protocol sends the address and command bytes followed by their exact logical inverses (bitwise NOT). Your Arduino sketch should always verify that (Command ^ 0xFF) == Inverse_Command. If this check fails, the IR frame was corrupted by ambient noise and should be discarded to prevent phantom button presses.

How the Arduino Decodes the Signal

Because IR timing requires microsecond-level precision, you cannot use standard digitalRead() polling loops to decode an arduino infrared remote. Polling is easily disrupted by background tasks, serial interrupts, or Wi-Fi stack operations on an ESP32. Instead, professional MCU implementations rely on Hardware Timer Capture or Pin-Change Interrupts (PCINT).

When the receiver's output pin transitions from HIGH to LOW (a falling edge), an Interrupt Service Routine (ISR) fires. The ISR reads the current value of a free-running hardware timer (e.g., Timer1 on an ATmega328P running at 16MHz, which ticks every 0.0625µs). By subtracting the previous timer capture value from the current one, the ISR calculates the exact duration of the pulse or space in microseconds. These durations are pushed into a circular buffer. Once the buffer detects a gap longer than 5ms (indicating the end of a frame), the main loop processes the raw timing array, maps it to binary 0s and 1s, and extracts the 32-bit hexadecimal command.

For a comprehensive look at how these sensor signals are structured at the hardware level, Adafruit's IR Sensor Guide provides excellent oscilloscope captures of the demodulated baseband waves.

Real-World Failure Modes and 2026 Noise Profiles

Even with perfect code, IR links fail in the field. As a maker or engineer, you must design around these physical edge cases:

1. Sunlight Saturation

Direct sunlight contains immense infrared energy. If sunlight hits the photodiode directly, it can exceed the sensor's dynamic range, effectively "blinding" the junction and preventing it from detecting the 1mA pulses from your remote. The Fix: Never rely on software to fix this. You must use a physical IR-pass optical filter or mount the receiver deep inside a 3D-printed shroud/tube to limit the field of view (FOV) to the expected direction of the remote.

2. Switch-Mode Power Supply (SMPS) Harmonics

In 2026, the phase-out of CFL bulbs has eliminated one source of IR noise, but modern, ultra-cheap SMPS LED drivers and USB-C fast chargers emit broadband electromagnetic interference (EMI). This EMI can couple into the receiver's internal preamplifier, causing phantom 38kHz triggers. The Fix: Never power an IR receiver directly from a noisy microcontroller USB rail without decoupling.

Implement a strict power filtering network on your PCB or breadboard:

  1. Place a 100Ω series resistor on the VCC line feeding the IR receiver.
  2. Add a 4.7µF ceramic capacitor in parallel with a 10µF electrolytic capacitor directly across the VCC and GND pins of the receiver module.
  3. This creates a low-pass RC filter that starves high-frequency EMI while providing a local energy reservoir for the receiver's internal AGC amplifier.

3. Voltage Sag and Brownouts

The internal oscillator of the VS1838B is highly sensitive to VCC fluctuations. If your Arduino is simultaneously driving a high-current load (like a 5V relay or a servo motor), the resulting voltage sag can shift the receiver's internal bandpass filter away from 38kHz. A remote transmitting at exactly 38.0kHz might be rejected if the receiver's center frequency temporarily drifts to 37.2kHz. Always isolate inductive loads using optocouplers or dedicated motor driver ICs with separate power planes to maintain a rock-solid 5V (or 3.3V) rail for your optical sensors.