A live, local visualizer for the DFRobot SEN0628 and YDLIDAR GS5
Tiny depth sensors in. Surprisingly lovely spatial data out.
8 × 8 matrix ToF · 160-beam solid-state lidar · USB serial · zero frontend dependencies
Depth Field auto-detects either supported sensor, decodes its native serial protocol, and streams live measurements into a responsive browser dashboard. Explore the SEN0628 as a smooth depth field or perspective surface; view the GS5 as an 85° radar fan or 160-beam range profile. Inspect individual returns, follow the nearest target, or watch the signal move over time.
Everything stays on your machine. There is no cloud service, account, or frontend build step.
|
|
| Perspective surface view | Responsive mobile layout |
|
|
| GS5 polar scan fan | GS5 angle-versus-range profile |
Screenshots use the built-in animated demo source so the scene is reproducible without hardware.
You need the sensor connected over USB and Node.js 20 or newer.
npm install
npm startOpen http://localhost:8787. The server finds the most likely USB serial device automatically and reconnects if the sensor is unplugged.
Automatic mode also supports live sensor swaps: unplug one supported sensor, attach the other, and the existing dashboard switches geometry, protocol, controls, and labels without a server restart.
Want to explore without the sensor?
npm run demo
npm run demo:gs5The first command simulates the SEN0628; the second simulates a GS5. Both exercise the same server and dashboard used by real hardware.
| View | What it does |
|---|---|
| Field | Interpolates the 8×8 measurements into a smooth thermal depth map while preserving the exact readings in each zone. |
| Surface | Projects the matrix as an illuminated depth topography for a more spatial view of nearby objects. |
| Radar | Draws all 160 GS5 returns as a top-down polar fan across its 85° field of view. |
| Profile | Shows the GS5 scan as angle versus range, colored by distance and signal intensity. |
| Target lock | Tracks the closest valid return and reports its sensor coordinates. |
| Raw aperture | Shows the exact 8×8 zone readings or angle-ordered GS5 return strip at a glance. |
| Signal trace | Plots the nearest distance over the latest six seconds. |
The controls let you:
- tune temporal smoothing without changing the source data;
- narrow the display range for more color contrast;
- mirror the field for camera-like interaction;
- freeze and inspect a frame;
- hover any zone to see its exact millimeter reading.
The layout scales from a wide monitoring display down to a phone-sized viewport.
flowchart LR
A["SEN0628<br>text · 115200 baud"] --> B["USB auto-detection<br>+ reconnect"]
G["GS5<br>binary · 921600 baud"] --> B
D["Demo source"] -.-> B
B --> C["Protocol parser<br>matrix or line scan"]
C --> E["Node HTTP server<br>stats + SSE"]
E --> F["Browser dashboard<br>Canvas 2D"]
The stock SEN0628 firmware emits eight text rows for every frame:
y0:4000,4000,872,846,901,4000,4000,4000,
…
y7:4000,4000,4000,4000,4000,4000,4000,4000,
The parser treats y0 as the frame boundary, so it can recover cleanly after partial reads, noise, or reconnects. Distances are millimeters. Firmware v1.3 uses 4000 for invalid or out-of-range zones; Depth Field renders those as empty space and excludes them from statistics.
The GS5 uses an A5 A5 A5 A5 binary packet header. Depth Field runs its stop/address/version/calibration/start sequence, validates the 8-bit packet checksum, then decodes 160 little-endian samples per frame. Each sample contains an 11-bit millimeter distance and 5-bit signal intensity. Device calibration coefficients recover the physical beam angles. The GS5's opposing 80-pixel camera halves are de-duplicated at their overlapping centerline and sorted by physical angle before streaming, matching the vendor SDK's scan treatment. The published 85° FOV is used as a fallback until calibration arrives.
Automatic discovery is usually enough. To select a device explicitly:
npm start -- --port /dev/cu.usbmodem1301
npm start -- --sensor gs5 --port /dev/cu.usbserial-0001All server options:
--demo use animated sample data
--sensor <type> auto, sen0628, or gs5 (default: auto)
--port <device> serial device (auto-detected by default)
--http-port <port> web server port (default: 8787)
--host <address> bind address (default: 127.0.0.1)
The equivalent environment variables are SENSOR_TYPE, SENSOR_PORT, PORT, and HOST.
To make the dashboard reachable on your local network:
HOST=0.0.0.0 npm startThen visit http://<this-machine's-ip>:8787 from the other device. The service has no authentication, so only expose it on a network you trust. By default it binds to loopback and is accessible only from this machine.
| Endpoint | Purpose |
|---|---|
GET / |
Dashboard |
GET /events |
Live frames and connection state as server-sent events |
GET /api/status |
Current source, serial path, frame count, and measured rate |
GET /healthz |
200 while the source is connected; 503 otherwise |
A frame event contains a flat distance array plus sensor geometry, range, nearest/farthest/mean, valid-return, and frame-rate statistics. GS5 events also contain 160 beam angles, intensities, and the ambient-light reading.
The dashboard stays on “Locating sensor.”
- Make sure the USB cable carries data, not power only.
- Close Arduino Serial Monitor,
screen, or any other program holding the port. - On macOS, look for
/dev/cu.usbmodem*(SEN0628) or/dev/cu.usbserial*(GS5) and pass it using--portif necessary. - On Linux, the port is commonly
/dev/ttyACM0; your user may need serial-device permissions (often membership in thedialoutgroup).
The sensor connects but returns stale or invalid zones.
DFRobot recommends SEN0628 firmware v1.3, which fixes invalid readings that could remain unchanged. See the official USB setup and firmware guide.
The GS5 adapter appears, but the dashboard stays on “Waking GS5.”
- Make sure the GS5 itself is connected to the adapter board; the CP2102 adapter can appear as a serial port on its own.
- Confirm the sensor's 4-wire cable is fully seated in the adapter board.
- The CP2102 serial bridge can enumerate even when the lidar lacks enough power. If the board has a second Type-C socket labeled
USB_PWR, connect it to a 5V supply. - Connect the computer to the socket labeled
USB_DATA, not the power-only socket. - The GS5 does not stream at power-on; Depth Field sends its start command automatically at the factory-default 921600 baud.
The usual web port is already occupied.
npm start -- --http-port 9000npm testTests cover fragmented text and binary input, malformed and incomplete frames, GS5 checksums, calibration and dual-camera ordering, resynchronization, invalid-distance handling, statistics, and USB-device selection. There are no generated frontend artifacts: edit the files in public/ and refresh the page.
.
├── server.js HTTP/SSE server and runtime orchestration
├── lib/
│ ├── matrix-parser.js SEN0628 frame parsing and statistics
│ ├── gs5-protocol.js GS5 commands, packets, samples, and angles
│ └── sources.js USB auto-detection and animated demo sources
├── public/
│ ├── index.html Dashboard structure
│ ├── styles.css Responsive visual system
│ └── app.js Streaming client and canvas rendering
└── test/ Node test suite
- DFRobot SEN0628 product page
- Getting started, USB output, and firmware
- API and communication reference
- YDLIDAR GS5 product downloads
- YDLIDAR GS5 development manual
- YDLIDAR open-source SDK
Made for tiny depth cameras and the delightful things they notice.




