Status (2026-08-29): LIVE + OPERATOR-PROVEN. Wiring is soldered and the laser is mounted parallel to the wrist camera. The production wall-avoid graph owns GPIO17 through laser-control; the Wrist UI hold-to-fire button and release-to-off behavior passed live operator testing. Native-MJPEG wrist preview is stable at 640×480, 5 fps. Hardware tests passed one 200 ms pulse, six 250 ms flashes, and a recorded ten-flash sequence; every sequence ended with laser state confirmed OFF.
Public write-up: repo README.md. Next work is arm poses and camera/beam targeting calibration.
Config: configs/laser.json. Driver: lib/laser_gpio.py. Supervised test: scripts/test_laser.py.
Physical header pins, except where BCM is explicit:
| Connection | Pi / component |
|---|---|
KY-008 VCC and S tied together |
Pi pin 4, 5 V |
KY-008 - |
2N3904 collector |
| 2N3904 emitter | Pi pin 14, GND |
| Pi pin 11, BCM GPIO17 | 2 kΩ resistor → 2N3904 base |
| Base pull-down | 4.7 kΩ base-to-emitter |
The 2N3904 is a low-side switch; GPIO17 does not source laser current. On the installed flat-face package, pins were verified as emitter-base-collector from left to right. Recheck the specific transistor datasheet after replacing any component.
The 4.7 kΩ pull-down keeps the transistor off while GPIO17 floats during boot or after the process releases the line. Keep 5 V physically isolated from GPIO17.
LeBot is Ubuntu 24.04. gpiod 2.5.0 is installed in /home/jeff/Marco-Dora/dora-lerobot/.venv. The Pi 5 RP1 controller resolves by label pinctrl-rp1 to /dev/gpiochip4; do not hard-code the chip number.
Dry run—acquire GPIO17 low without firing:
cd /home/jeff/Marco-Dora/dora-lerobot
.venv/bin/python robots/so101/scripts/test_laser.pySupervised blink test:
.venv/bin/python robots/so101/scripts/test_laser.py \
--pulse-ms 250 --repeat 6 --interval-ms 250 \
--confirm LASER-AIMED-SAFELYThe supervised test driver permits only bounded blocking pulses. Config limits each test pulse to 1000 ms, and the test script limits a sequence to 10 seconds.
In the production graph, the UI repeats laser_on while the button is held. laser-control turns off unless a fresh command arrives within 750 ms. Button release, tab/page loss, STOP/cancel, any motion request, node shutdown, and GPIO release all request off; the hardware pull-down covers process death and boot. The server rejects laser-on unless the arbiter is idle, wheel telemetry is stopped, and the wrist preview is fresh.
Live acceptance completed on 2026-08-29:
- Wrist image remained stable after switching capture from uncompressed YUYV to native MJPEG at 5 fps.
- Wrist-tab press-and-hold illuminated the mounted laser; release extinguished it.
- Ten remote 300 ms flashes completed for video, followed by explicit off and
/stateverification (laser.on=false).
The soldered module is in a newly designed wrist-camera mount with the laser axis parallel to the camera. Confirm insulation, strain relief, harness service loops, and full safe joint travel before normal arm motion. Aim only downward into a matte beam stop; avoid eyes, people, pets, glass, mirrors, and polished metal.
Follower IDs:
| ID | Joint | Laser role |
|---|---|---|
| 1 | shoulder_pan |
Horizontal aim |
| 2 | shoulder_lift |
Raised clearance pose |
| 3 | elbow_flex |
Raised clearance pose |
| 4 | wrist_flex |
Vertical aim |
| 5 | wrist_roll |
Camera/laser roll; usually not primary aim |
| 6 | gripper |
Not an aiming joint |
Next record STOW and LASER_READY follower positions using teleoperation. LASER_READY must keep the arm out of the forward OAK-D view and constrain the beam below eye level. Keep the laser off during every arm or base movement.
After poses are repeatable:
- Calibrate the laser dot relative to wrist-camera pixels at several working distances.
- Detect the target in the wrist image and choose an aim pixel or physical offset.
- Start with stop-and-align corrections using shoulder pan and wrist flex.
- Add a bounded pulse only after wheels are stopped, the safe pose is confirmed, and the target remains valid.
- Make phone STOP, cancel, timeout, process exit, and any arm transition force laser off.
The production graph exposes supervised UI-only laser_on / laser_off; it still has no arm actions or DimOS laser skill. Develop arm poses and targeting as a supervised path before exposing autonomous firing.