Skip to main content
Explore ERDILRF

Press ↑↓ to move, Enter to open, Esc to close.

ESP32 + UART Laser Distance Sensor: Wiring & Code

An ESP32 reads an ERDI laser distance module over a plain 3.3 V TTL UART: wire module TX to GPIO16 and module RX to GPIO17 (UART2), then parse the module’s frames with either Arduino-ESP32 HardwareSerial or the open-source MicroPython driver. This page gives the wiring, both code paths and the mistakes we see most often.

Logic level: stay at 3.3 V

ESP32 GPIO pins are 3.3 V only and are not 5 V tolerant. The module’s UART lines must therefore be 3.3 V TTL as well; do not connect a 5 V signal to the ESP32. Supply voltage is not UART voltage: a module that runs from 5 V may still use 3.3 V logic, or the reverse. Read the electrical table on the model page before connecting, and add a level shifter if the module TX swings higher than 3.3 V. For example, the LRF22VB model page lists a 3-3.6 V supply, the LRF50VB page lists 3.3-5 V, and the LRF3000A1 page lists UART, 3.3 V TTL. Always confirm your own model at erdilrf.com/models.

Wiring (ESP32 UART2)

Module pin ESP32 pin Note
TX GPIO16 (RX2) Module transmit goes to ESP32 receive
RX GPIO17 (TX2) Needed only for polled modules and configuration
GND GND Common ground, joined near the module
VCC Own supply per the model manual Do not assume the ESP32 3.3 V pin can carry it

Pin order differs between modules and is not standard across vendors, so check the model’s own pinout before powering up. A power-up order that works: ground first, then TX/RX, then power.

Power: size for the peak, not the average

A laser module draws short current peaks when it fires. A weak regulator or a thin USB cable can make the ESP32 brown out, or make the module send a valid-looking frame with a zero or maximum distance during start-up. Size the regulator for the peak current listed on the model page, put 10-100 µF of bulk capacitance close to the module plus 100 nF at the connector, and use a separate regulator if the same rail feeds motors or servos.

Two protocol families, one baud lookup

ERDI modules use one of two UART protocols. Family B (LRF22VB, LRF50VB and the H series) free-runs at 460800 baud and sends 5C lo hi chk frames; the check byte is the inverse of the sum of the distance bytes. Units are not uniform: the bytes 5C 02 11 EC mean 43.54 m on an H-series module (centimetres) but 4.354 m on a VB-series module (millimetres). Family A (LR1000E2 to LR2000E4, LRF1200A1, LRF3000A1, SPD1200N0/N2/N4) is polled at 115200 baud with the request 55 AA 88 FF FF FF FF 84. Use the baud rate of your model, not a guess.

Arduino-ESP32 code (family B stream, LRF22VB)

This sketch is a minimal rewrite of the frame logic in erdi_lrf.py for LRF22VB (4-byte frame, millimetres, out-of-range marker 20000). It resynchronises on the 5C header when a checksum fails.

#include <Arduino.h>

static const uint32_t BAUD = 460800;   // family B default
static uint8_t f[4];
static uint8_t n = 0;

void setup() {
  Serial.begin(115200);
  Serial2.begin(BAUD, SERIAL_8N1, 16, 17);  // RX=GPIO16, TX=GPIO17
}

void loop() {
  while (Serial2.available()) {
    uint8_t b = Serial2.read();
    if (n == 0 && b != 0x5C) continue;      // wait for header
    f[n++] = b;
    if (n < 4) continue;
    uint8_t chk = (uint8_t)~(uint8_t)(f[1] + f[2]);
    if (chk == f[3]) {
      uint16_t raw = f[1] | (f[2] << 8);    // little-endian
      if (raw >= 20000) Serial.println("out of range");
      else Serial.printf("%.3f mn", raw * 0.001f);  // VB series: mm
      n = 0;
    } else {                                   // resync on next 0x5C
      uint8_t i = 1;
      while (i < 4 && f[i] != 0x5C) i++;
      for (uint8_t k = 0; k < 4 - i; k++) f[k] = f[k + i];
      n = 4 - i;
    }
  }
}

If you prefer a library, the Arduino library in erdi-lrf-drivers/arduino/ErdiLRF is built on Stream, so it accepts Serial2: begin the port with erdiDefaultBaud(model), construct ErdiLRF lrf(Serial2, ERDI_LRF22VB); and call lrf.measure(&m). It returns ERDI_OK, ERDI_ERR_OUT_OF_RANGE or ERDI_ERR_TIMEOUT.

MicroPython version

The single-file driver from erdi-lrf-esp32-micropython has no dependencies. Install it with mip.install("github:ErdiTech/erdi-lrf-esp32-micropython") or copy erdi_lrf.py with mpremote cp erdi_lrf.py :. It picks the baud rate from the model table.

import time
from erdi_lrf import open_uart

lrf = open_uart("LRF22VB", uart_id=2, tx=17, rx=16)
while True:
    d = lrf.read_latest()
    print("out of range / no frame yet" if d is None else "%.3f m" % d)
    time.sleep_ms(50)

Polled modules (family A) use measure(), which sends the single-shot request and waits up to 500 ms for the 8-byte reply:

lrf = open_uart("LRF3000A1", uart_id=2, tx=17, rx=16)   # 115200 baud
d = lrf.measure()   # metres, None if no valid echo, OSError on timeout

Source: examples/esp32_stream.py and examples/esp32_single_shot_a.py in the repository.

Common pitfalls

Symptom Likely cause Fix
No bytes at all TX/RX swapped, or no common ground Module TX goes to GPIO16; join GND first
Garbage bytes Wrong baud rate 460800 for family B, 115200 for family A
Distance 10x too large or small Wrong unit VB series is mm, H series is cm, family A is metres x 10
Zero or maximum value at boot Supply sag during start-up Add bulk capacitance, use a stronger regulator
ESP32 resets when ranging Shared rail, current peaks Separate regulator for the module
Checksum failures on a long wire Noise on the TTL line Keep the run short and twisted; lowering the baud rate alone does not fix noise
Frames lost while Wi-Fi is busy RX buffer overflows Read in a dedicated task or enlarge the UART RX buffer

FAQ

Can I connect the module straight to ESP32 pins?

Yes, if the module UART is 3.3 V TTL. If the module TX is 5 V, use a level shifter or divider. Never rely on an ESP32 pin being 5 V tolerant.

Which UART should I use on ESP32?

UART2 on GPIO16 (RX) and GPIO17 (TX) matches both the Arduino and the MicroPython examples. UART0 is the USB console on most boards, so keep it free for logs.

Where do I find the frame format for my exact model?

The two families are summarised above; the per-model frame, units and range limits are on the model page at erdilrf.com/models. See the model page for the frame format of anything not covered here.

Who do I contact for help choosing a module?

Send your host, range and interface needs to tommy@erdimail.com.

Explore knowledge

Models mentioned in this article