How 38kHz IR Receivers Actually Work

An IR receiver module (like the Vishay TSOP38238 or the generic VS1838B) is not just a raw photodiode exposed to the environment. It is a highly integrated optoelectronic circuit containing a PIN photodiode, an automatic gain control (AGC) amplifier, and a bandpass filter tuned specifically to a carrier frequency—almost always 38kHz. When your remote's IR LED pulses at 38kHz, the receiver's internal demodulator strips away the high-frequency carrier wave and outputs a clean, baseband digital signal representing the original data envelope.

Crucially, this output is strictly digital (a 0V to VCC square wave), not an analog voltage. A common beginner mistake is conflating these 38kHz demodulating receivers with Sharp IR distance sensors (like the GP2Y0A21YK0F), which output an analog voltage proportional to reflected light intensity. When you are pairing an IR sensor and remote combo for button presses, you are not measuring voltage levels; you are measuring microsecond pulse widths using hardware timers to decode serial protocols.

Hardware Specs, Supply Range, and Wiring

Not all 38kHz receivers are created equal. While the generic VS1838B modules found in $2 starter kits work for basic bench testing, their AGC circuits often fail under continuous transmission or high ambient light. For reliable jobsite or living room deployments, name-brand silicon like Vishay's TSOP series is mandatory. Below is a data-dense comparison of common modules you will encounter.

Table 1: 38kHz IR Receiver Module Specifications
Module / IC Supply Range (VCC) Carrier Freq Output Type Max Data Rate AGC Stability
Generic VS1838B 2.7V - 5.5V 38kHz Digital (Active Low) ~2400 bps Poor (Struggles with continuous bursts)
Vishay TSOP38238 2.5V - 5.5V 38kHz Digital (Active Low) 4000 bps Excellent (Designed for noisy environments)
Everlight IRM-H638T 2.7V - 5.5V 38kHz Digital (Active Low) 2400 bps Good (Solid mid-tier alternative)
OS-1838 (OptoSupply) 3.0V - 5.0V 38kHz Digital (Active Low) 2000 bps Moderate

Wiring and Pinout Table

Because the output is an active-low digital signal, the data pin idles HIGH (at VCC) and pulls LOW (to GND) when it detects a 38kHz burst. If you are using a 3.3V microcontroller like the ESP32 or Raspberry Pi Pico, power the receiver from the 3.3V pin. The TSOP38238 operates natively down to 2.5V, and powering it at 3.3V ensures the output HIGH state never exceeds the ESP32's GPIO voltage limit, preventing silicon damage.

Table 2: ESP32 to IR Receiver Wiring
Receiver Pin ESP32 Pin Notes & Conditioning
VCC (Left) 3V3 Add 100Ω series resistor + 4.7µF ceramic cap to GND for noise immunity.
GND (Middle) GND Keep ground return path short; avoid sharing with high-current motor grounds.
OUT (Right) GPIO 15 Internal pull-up is usually sufficient; add 4.7kΩ external pull-up if wire > 10cm.
Callout Tip: The Vishay RC Filter
If your ESP32 resets or you get phantom IR triggers when switching a relay, your power rail is noisy. Vishay's datasheet explicitly recommends placing a 100Ω resistor between your 3.3V source and the receiver's VCC pin, with a 4.7µF ceramic capacitor tied from the receiver's VCC pin to GND. This low-pass filter blocks high-frequency switching noise from coupling into the receiver's internal AGC amplifier.

Decoding the Signal: Raw Timings to Hex Commands

The 'physical unit' of an IR remote isn't a temperature or distance; it is a decoded hexadecimal command state. To get from a raw electrical signal to a usable button command, the microcontroller must measure the duration of the HIGH and LOW states in microseconds. Most cheap consumer electronics use the NEC IR Protocol.

The Raw-to-Unit Math (NEC Protocol)

The NEC protocol uses pulse-distance encoding. The carrier burst length is fixed, but the space (the silent gap between bursts) determines if a bit is a 0 or a 1. Here is the exact timing math your microcontroller's hardware timer (like the ESP32's RMT peripheral) captures:

  • Leader Code (Start): 9000µs pulse (LOW) + 4500µs space (HIGH). This tells the receiver a new command is starting.
  • Logic 0: 562.5µs pulse + 562.5µs space (Total bit time: ~1.125ms).
  • Logic 1: 562.5µs pulse + 1687.5µs space (Total bit time: ~2.25ms).

The Scaling Formula:
When the microcontroller's interrupt or RMT peripheral captures a space duration ($T_{space}$), the logic state is calculated as:
Bit_State = (T_space > 1125µs) ? 1 : 0

A standard NEC command is 32 bits long (8-bit address, 8-bit inverted address, 8-bit command, 8-bit inverted command). A raw array of microsecond timings like [9000, 4500, 560, 560, 560, 1690...] is shifted into a 32-bit integer, yielding a hex command like 0x18E710EF (the 'Power' button on many generic RGB strip remotes).

ESP32 Implementation Code

The ESP32 is uniquely suited for this because it features an RMT (Remote Control) peripheral. Unlike the Arduino Uno, which must use CPU-blocking timer interrupts to measure microsecond pulses (often dropping WiFi packets in the process), the ESP32's RMT hardware captures the IR pulse timings autonomously in the background. Below is a robust implementation using the modern Arduino-IRremote v4.x library, which natively supports the ESP32 RMT.

#include <IRremote.hpp>

// Define the GPIO pin connected to the IR receiver OUT pin
const int IR_RECEIVE_PIN = 15;

void setup() {
  Serial.begin(115200);
  
  // Initialize the IR receiver using the ESP32 RMT peripheral
  // ENABLE_LED_FEEDBACK blinks the ESP32's onboard LED on signal receipt
  IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
  
  Serial.println("IR Receiver initialized on GPIO 15. Waiting for NEC remote...");
}

void loop() {
  // Check if the RMT peripheral has captured a full protocol frame
  if (IrReceiver.decode()) {
    
    // Print the raw microsecond timings and the decoded hex command
    IrReceiver.printIRResultShort(&Serial);
    
    // Example: Trigger an action based on the decoded NEC hex command
    if (IrReceiver.decodedIRData.protocol == NEC) {
      uint32_t command = IrReceiver.decodedIRData.command;
      
      if (command == 0x45) { // Example: 'CH-' button on generic 24-key remote
        Serial.println(">> Action: Toggle Main Relay");
      }
    }
    
    // CRITICAL: Resume the receiver to clear the buffer and listen for the next burst
    IrReceiver.resume(); 
  }
}

Calibration, Scaling, and Interference Sources

Unlike analog sensors that require manual voltage calibration or mapping, digital IR protocol timing is handled by the library's internal tolerance windows. The NEC protocol specifies a ±10% timing tolerance. If your remote's ceramic resonator is slightly off-frequency and sends a 9200µs leader pulse instead of 9000µs, the IRremote library's state machine will still recognize it as a valid start burst. No manual scaling or calibration code is required on your end.

Common Interference Sources and Fixes

While the digital protocol is robust, the analog front-end (the photodiode and AGC) is highly susceptible to environmental noise. If your ESP32 is failing to register remote clicks, or is registering phantom buttons, check these three interference sources:

  1. Direct Sunlight and Halogen Lamps: Sunlight contains massive amounts of broadband infrared radiation. If the total IR energy saturates the photodiode, the internal AGC cranks the gain down to zero, effectively blinding the sensor to your remote's weak 38kHz signal. Fix: Mount the sensor in a recessed bezel or add an external optical bandpass filter.
  2. Compact Fluorescent (CFL) and Inverter-Driven LEDs: CFL bulbs and cheap LED drivers use high-frequency switching ballasts that emit sharp IR spikes. Some of these spikes harmonically overlap near the 30kHz–40kHz range, tricking the receiver's bandpass filter into thinking a remote signal is present. Fix: Use a Vishay TSOP receiver with 'AGC3' or 'AGC4' silicon, which is specifically designed to suppress continuous 38kHz noise from fluorescent ballasts.
  3. Power Rail Coupling (Ground Bounce): If your ESP32 is driving a 5V relay module or a motor driver on the same breadboard, the switching current causes micro-voltage drops on the ground plane. The IR receiver interprets this ground bounce as a digital LOW pulse on the data line. Fix: Implement the 100Ω / 4.7µF RC filter on the VCC pin mentioned in the wiring table, and route the IR receiver's ground directly to the ESP32's star ground point.

By treating the IR sensor and remote interface as a precise digital timing problem rather than a simple analog voltage read, and by conditioning the power rail against switching noise, you can achieve 100% reliable remote control for your embedded projects.