Projects

Adeept PiCar-B

Rewriting the Adeept PiCar-B kit in .NET/C# with a browser UI — ROS2, Lidar, and IMU next.

Adeept PiCar-B assembled, blue wheels and cat-face sensor head

An Adeept PiCar-B I wanted under my own software, not the kit's Python defaults. Phase one is a .NET / C# 10 app with a web UI for lights, steering and motor, pan/tilt, ultrasonic ranging, and camera streaming — plus line following once that sensor is wired again. I'll link the GitHub repo here when it's actually running.

Phase two is ROS2: collision awareness and SLAM with the Lidar, and orientation from the IMU. Browser first; autonomy after that.

Current status

The browser teleop UI is up on the car: drive, steering, speed, camera pan/tilt joystick, WS2812 colour and effects, and a live status panel (ultrasonic, line sensor, steer/pan/tilt angles, CPU temperature).

The main view toggles between a 3D model of the robot and the live camera. The 3D view renders the PiCar-B in the browser — drag to orbit, scroll to zoom — with a point-cloud toggle ready for Lidar data later.

PiCar-B Teleop web UI showing the 3D robot model view alongside drive, lights, steering and pan/tilt controls

Camera streaming from the Arducam IMX708 works end to end in the same page. It's usable, but there's noticeable latency between the car moving and the picture catching up — fine for looking around, not yet good enough for driving by camera alone.

PiCar-B Teleop camera view streaming live video from the robot's IMX708 camera

Next steps

  • Cut camera stream latency — the biggest gap right now. Look at resolution/frame rate, encoder settings, buffering on both ends, and the transport (MJPEG vs. a lower-latency option like WebRTC).
  • Line follower — rewire to the HAT V3.1 and replace the software stub.
  • Phase two — ROS2 with the LD06 Lidar (feeding the point-cloud view) and BNO055 orientation.

Hardware

Parts photos

Arducam Camera Module 3 with IMX708 sensor and CSI ribbon

GY-BNO055 IMU breakout with pin header

OKDO LD06 Lidar on mounting plate

Challenges

OS choice mattered more than expected. Ubuntu-style hosts fought the Pi camera stack and package story, so the robot host settled on Raspberry Pi OS. ROS and heavier perception can come later — often in Docker — without owning the GPIO path on the native board.

The camera stayed black until I stopped treating it like a plain V4L2 device. On Pi OS the CSI path is libcamera / rpicam; OpenCV opening /dev/video0 just fails. Streaming through rpicam fixed it. Newer Pi OS had also dropped the original kit camera driver, so I swapped in an Arducam Camera Module 3 (Sony IMX708) — same class as the official Pi module, slightly larger than stock, which meant cutting a bigger recess in the chassis.

Pi 5 was less forgiving than older boards. Opening GPIO and the WS2812 LED path in the wrong order could hard-lock the machine, and multiple GPIO openers fought over the chip (whose index also varied by image). One shared GPIO owner, LEDs off by default with WS2812, and a safe config for recovery.

The Robot HAT V3.1 upgrade was the other awkward bit. Connectors don't match the older loom one-for-one — most of the harness went back on after some patience, but the line follower is still disconnected, so line-follow stays a software stub for now. Old docs and config still pointed at HAT V2 ultrasonic pins; V3 uses different numbering and the ULTRASONIC header, which looked like a dead sensor until the pin map caught up. On Pi 5 the trigger pulse that worked on a Pi 3 was also too short, and a no-echo reading as Infinity blew up the status JSON — longer pulse, null for no echo.

Smaller software snags: the ASP.NET static-asset path served index.html but / itself 404'd until that route was mapped explicitly. And coupling teleop to ROS early slowed bring-up — host-first, ROS off by default, Docker as a DDS peer later so GPIO stays on the native host.

← All projects