Created
July 24, 2026 08:17
-
-
Save Muhammad-Yunus/0a54e58c25b47192ad8ebc2d7d2fa545 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| https://www.youtube.com/shorts/goCs0tH-d78 | |
| github - kaiaai/LDS | |
| Your LIDAR uses the Delta-2A / 3irobotics protocol (same as LDS08RR in the kaiaai/LDS repo), NOT the Neato XV11 protocol. | |
| Key issues with the old code: | |
| - Start byte is 0xAA, not 0xFA. The 0xFA bytes you were seeing are just random data/distance values | |
| - Packet size is variable (typically 72 bytes: header says packet_length=70 + 2 for the start/length fields), not a fixed 42 bytes | |
| - You were reading misaligned slices of the actual data stream | |
| Protocol structure (confirmed from your data matching AA 00 46 01 61 AD 00 3E): | |
| ┌────────┬───────────────────┬──────────────────┬─────────────────────────────┐ | |
| │ Offset │ Field │ Your data │ Meaning │ | |
| ├────────┼───────────────────┼──────────────────┼─────────────────────────────┤ | |
| │ 0 │ Start byte │ AA │ Packet start │ | |
| ├────────┼───────────────────┼──────────────────┼─────────────────────────────┤ | |
| │ 1-2 │ Packet length │ 00 46 (70) │ Total - 2 │ | |
| ├────────┼───────────────────┼──────────────────┼─────────────────────────────┤ | |
| │ 3 │ Protocol version │ 01 │ Always 0x01 │ | |
| ├────────┼───────────────────┼──────────────────┼─────────────────────────────┤ | |
| │ 4 │ Packet type │ 61 │ Always 0x61 │ | |
| ├────────┼───────────────────┼──────────────────┼─────────────────────────────┤ | |
| │ 5 │ Data type │ AD │ RPM + measurements │ | |
| ├────────┼───────────────────┼──────────────────┼─────────────────────────────┤ | |
| │ 6-7 │ Data length │ 00 3E (62) │ n_samples = (62-5)/3 = 19 │ | |
| ├────────┼───────────────────┼──────────────────┼─────────────────────────────┤ | |
| │ 8 │ Scan freq ×20 │ 85/86 │ ~4.25 Hz │ | |
| ├────────┼───────────────────┼──────────────────┼─────────────────────────────┤ | |
| │ 9-10 │ Offset angle ×100 │ varies │ Signed, BE │ | |
| ├────────┼───────────────────┼──────────────────┼─────────────────────────────┤ | |
| │ 11-12 │ Start angle ×100 │ varies │ e.g. 08 CA = 22.50° │ | |
| ├────────┼───────────────────┼──────────────────┼─────────────────────────────┤ | |
| │ 13+ │ Samples (×19) │ 3 bytes each │ [quality, dist_hi, dist_lo] │ | |
| ├────────┼───────────────────┼──────────────────┼─────────────────────────────┤ | |
| │ last 2 │ Checksum │ sum of all bytes │ Big-endian │ | |
| └────────┴───────────────────┴──────────────────┴─────────────────────────────┘ | |
| Each measurement sample: distance_mm = (dist_hi<<8 | dist_lo) * 0.25 | |
| The updated script syncs on 0xAA, validates the header constants and checksum, decodes all 19 samples per packet with proper angles, | |
| and plots a polar scan like your previous version. Try running it and let me know if the data looks correct! |
Author
Author
Python XIAOMI_LDS02RR Visualizer (watch https://www.youtube.com/shorts/goCs0tH-d78)
import serial
import struct
import math
import matplotlib.pyplot as plt
PORT = "COM9"
BAUD = 115200
# Delta-2A / 3irobotics LDS protocol (used by Xiaomi MVXVC01-JG LDS)
START_BYTE = 0xAA
PROTOCOL_VERSION = 0x01
PACKET_TYPE = 0x61
DATA_TYPE_RPM_AND_MEAS = 0xAD
DATA_TYPE_RPM_ONLY = 0xAE
HEADER_SIZE = 13
PACKETS_PER_SCAN = 16
def validate_checksum(pkt):
data_sum = sum(pkt[:-2]) & 0xFFFF
chk_hi, chk_lo = pkt[-2], pkt[-1]
expected = (chk_hi << 8) | chk_lo
expected_with_self = (expected + chk_hi + chk_lo) & 0xFFFF
return (data_sum + chk_hi + chk_lo) & 0xFFFF == expected_with_self
def decode_packet(pkt):
"""Decode a Delta-2A LIDAR packet. Returns list of (angle_deg, distance_mm, quality)."""
data_type = pkt[5]
data_length = (pkt[6] << 8) | pkt[7]
scan_freq_x20 = pkt[8]
start_angle_x100 = (pkt[11] << 8) | pkt[12]
scan_freq_hz = scan_freq_x20 * 0.05
start_angle = start_angle_x100 * 0.01
if data_type != DATA_TYPE_RPM_AND_MEAS:
return [], scan_freq_hz, start_angle
n_samples = (data_length - 5) // 3
angle_step = 360.0 / (PACKETS_PER_SCAN * n_samples)
points = []
for i in range(n_samples):
offset = HEADER_SIZE + i * 3
if offset + 3 > len(pkt) - 2:
break
quality = pkt[offset]
dist_x4 = (pkt[offset + 1] << 8) | pkt[offset + 2]
distance_mm = dist_x4 * 0.25
angle = start_angle + i * angle_step
points.append((angle, distance_mm, quality))
return points, scan_freq_hz, start_angle
ser = serial.Serial(PORT, BAUD)
buffer = bytearray()
# Plotting setup
plt.ion()
fig = plt.figure()
ax = fig.add_subplot(111, projection='polar')
all_angles = []
all_dists = []
last_start_angle = -1
print("Listening for LIDAR packets on", PORT, "...")
while True:
incoming = ser.read(ser.in_waiting or 1)
buffer += incoming
while True:
start = buffer.find(bytes([START_BYTE]))
if start == -1:
buffer.clear()
break
if start > 0:
buffer = buffer[start:]
if len(buffer) < 3:
break
packet_length = (buffer[1] << 8) | buffer[2]
total_size = packet_length + 2
if packet_length < 10 or packet_length > 200:
buffer = buffer[1:]
continue
if len(buffer) < total_size:
break
pkt = buffer[:total_size]
if (len(pkt) >= 6 and
pkt[3] == PROTOCOL_VERSION and
pkt[4] == PACKET_TYPE and
pkt[5] in (DATA_TYPE_RPM_AND_MEAS, DATA_TYPE_RPM_ONLY)):
if validate_checksum(pkt):
points, freq, start_angle = decode_packet(pkt)
# Detect new scan (angle wraps back to 0)
if start_angle < last_start_angle and len(all_angles) > 50:
ax.clear()
ax.set_rmax(6000)
ax.set_title(f"LIDAR Scan ({freq:.1f} Hz)")
ax.scatter(all_angles, all_dists, s=2, c='blue')
plt.draw()
plt.pause(0.001)
all_angles.clear()
all_dists.clear()
last_start_angle = start_angle
for angle, dist, quality in points:
if dist > 0 and quality > 0:
all_angles.append(math.radians(angle))
all_dists.append(dist)
print(f" angle={angle:7.2f}° dist={dist:8.2f} mm q={quality}")
buffer = buffer[total_size:]
else:
buffer = buffer[1:]
else:
buffer = buffer[1:]
```
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
buka sample code examples/all_lidars_lds02rr_esp32.ino
comment #define XIAOMI_LDS02RR
uncomment #define _3IROBOTIX_DELTA_2A_115200
pin nya sama