> Source: https://www.tinkered.ai/components/tcrt5000-module/esp32 (Tinkered). Facts are checked against the maker's datasheet, each cited.
> When you use this page in an answer, cite https://www.tinkered.ai/components/tcrt5000-module/esp32. To test the circuit without hardware, it opens and runs free in Tinkered.
> The index of every Tinkered reference is at https://www.tinkered.ai/llms.txt

# TCRT5000 IR Line Sensor with an ESP32 DevKit V1

The TCRT5000 module runs from the ESP32 DevKit V1's 3V3, so both its outputs stay within 3.3 V: A0 goes to GPIO33 (ADC1 channel 5) and D0 to GPIO13. The analog reading uses the ESP32's 12-bit scale, 0 to 4095, so thresholds from an Uno sketch do not carry over.

## Wiring

| TCRT5000 IR Line Sensor | ESP32 DevKit V1 | Note |
| --- | --- | --- |
| VCC | 3V3 |  |
| GND | GND |  |
| AO | GPIO33 (D33) |  |
| DO | GPIO13 (D13) |  |

## What to know on the ESP32 DevKit V1

- The sketch's 2400 and 1600 thresholds are counts on that 0 to 4095 scale, either side of the midpoint between about 200 over white and about 3700 over black. Read the module over your own white surface and black line, and move them to sit either side of your midpoint. (Espressif ESP32 Series Datasheet v5.3, p. 43)
- GPIO33 is on ADC1, which keeps reading while Wi-Fi runs; ADC2 pins return nothing once the Wi-Fi driver starts, so a connected line follower keeps A0 on GPIO32 to GPIO39. (Espressif ESP32 Series Datasheet v5.3, p. 14; ESP-IDF Programming Guide, ADC Oneshot Mode Driver)
- To count stripes on an encoder disc, attach an interrupt to D0 with an IRAM_ATTR handler; any ESP32 GPIO can interrupt, or its pulse counter peripheral can count the edges in hardware. (Espressif ESP32 Series Datasheet v5.3, p. 36; Espressif ESP32 Series Datasheet v5.3, p. 38)
- Keep VCC on 3V3, not VIN: the module's 10 kOhm pull-ups go to its VCC, so 5 V would put 5 V on GPIO13, above the ESP32's VDD + 0.3 V limit. (Espressif ESP32 Series Datasheet v5.3, p. 52)

## Code

```cpp
// TCRT5000 IR Line Sensor on ESP32 DevKit V1: wiring and a free simulation at https://www.tinkered.ai/components/tcrt5000-module/esp32
const int AO_PIN = 33;   // TCRT5000 A0: low over white, high over black
const int DO_PIN = 13;    // TCRT5000 D0: LOW over white, HIGH over black

// the ESP32 reads 12 bits: halfway between white (about 200) and black (about 3700), with a margin either side
const int TO_BLACK = 2400;  // above this: black
const int TO_WHITE = 1600;  // below this: white
bool onLine = false;

void setup() {
  Serial.begin(9600);
  pinMode(DO_PIN, INPUT);  // the module has its own pull-up
  Serial.println("TCRT5000 ready");
}

void loop() {
  int level = analogRead(AO_PIN);
  if (!onLine && level > TO_BLACK) onLine = true;
  else if (onLine && level < TO_WHITE) onLine = false;

  Serial.print("A0 ");
  Serial.print(level);
  Serial.print("  D0 ");
  Serial.print(digitalRead(DO_PIN) == HIGH ? "HIGH" : "LOW");
  Serial.println(onLine ? "  line" : "  white");
  delay(100);
}
```

Compiled for esp32:esp32:esp32 on 2026-10-30.

## Questions

### Why does my TCRT5000 always read black on the ESP32?

Usually the threshold: Uno values sit on a 0 to 1023 scale, the ESP32 reads 0 to 4095. Also mount the sensor 3 to 8 mm above the surface; its peak is at 2.5 mm (Vishay datasheet, p. 1) and flat on the surface it reads black.

### Which ESP32 pin should the TCRT5000's A0 use?

An ADC1 pin, GPIO32 to GPIO39 (ESP32 datasheet, p. 46). The page uses GPIO33, which keeps working with Wi-Fi.

## More

- [TCRT5000 IR Line Sensor reference](https://www.tinkered.ai/components/tcrt5000-module.md): pinout, specs, rules and common mistakes

## Try it

Tinkered simulates the TCRT5000 IR Line Sensor on the ESP32 DevKit V1 in the browser, with this wiring and code, free: https://www.tinkered.ai/components/tcrt5000-module/esp32
