Troubleshooting
Find your issue by symptom. Quick diagnostic matrices are below, followed by deep-dive resolution paths.
Quick Diagnostic Matrices
Motor Issues
| Symptom | Quick Fix |
|---|---|
| No motors move | Check 12V DC cable from battery to motor board — 5 V USB will not drive them |
| Permission denied | sudo usermod -aG dialout $USER, then re-login |
| Whole bus silent | Duplicate IDs — scan each motor in isolation |
| Motor count mismatch | Scan the bus; the missing ID names the culprit |
| Single unresponsive | Re-assign its ID with set_motor_id.py, one motor on the chain |
| Arm jerks / wrong dir | Verify IDs match the motor map |
| Grinding noise | Inspect servo horn alignment; replace if stripped |
could not open /dev/xle_arms | The bus symlinks do not exist — run python diagnostics/detect_buses.py --write |
| Answers the bus, never moves | Logic power without motor power — check Present_Voltage |
| Arm drops when a script ends | Torque cut instead of bled off — step Torque_Limit down over seconds |
| Bus vanishes after driving | A cable was tugged loose — check dmesg, then strain-relieve it |
Camera Issues
| Symptom | Quick Fix |
|---|---|
| Camera not detected | ls /dev/video* to check path |
| Black frame | Check lens cap; test with cv2.VideoCapture |
| YOLO not tracking | Verify camera index in script |
Software Issues
| Symptom | Quick Fix |
|---|---|
| Import errors | pip install -e ".[all]" from the repo root, inside the venv |
| CUDA unavailable | Check for a +cpu torch build; reinstall from the Jetson index |
| Module not found | Use the venv interpreter directly: ~/.venvs/xlerobot-pro/bin/python |
| Joy-Con not pairing | sudo apt install joycond, enable Bluetooth |
Assembly Issues
| Symptom | Quick Fix |
|---|---|
| Arm wobbles/play | Tighten servo horn screws; check bracket fit |
| Wheels not straight | Adjust z-axis scale in slicer or use printed washers |
| Cart tips reaching | Move battery to lowest shelf to lower CoG |
Failure Signatures
Every one of these presents as something other than its cause. That is exactly why they cost people hours — and why they are worth reading once before you need them.
| What you see | What it actually is | Fix |
|---|---|---|
[TxRxResult] There is no status packet!Whole bus dead, yet each motor works in isolation |
Duplicate motor IDs. Feetech is half-duplex — two motors on the same ID transmit together and the collision corrupts every packet on the wire, not just theirs. Reads exactly like a power or cabling fault. | Scan each motor in isolation and correct the duplicates. See Motor Configuration. |
device descriptor read/64, error -110unable to enumerate USB device |
USB physical layer. The adapter is powered and looks connected but never enumerates, so its bus is invisible rather than faulty. | New cable first, then plug directly into the Jetson bypassing any hub, then try a different port. |
torch.cuda.is_available() → False |
Wrong PyTorch wheel or wrong environment. Either the CPU wheel won the resolve (check for a +cpu suffix) or torch was installed inside conda. |
Reinstall from the Jetson index by direct wheel URL, into a venv built on system Python 3.10. |
| Bus drops mid-calibration, always at the same joint | Cable tugged at that joint's travel extreme. Range recording retries only once, so a single dropped packet aborts the run. | Add a service loop at that joint. Do not raise the retry count to mask it — the same dropout will recur mid-grasp, under power. |
Permission denied: /dev/ttyACM0 |
User not in the dialout group — or the group was added without logging back in. |
sudo usermod -aG dialout $USER, then log out and back in. |
| Motors answer every scan but never move Load pinned at 1024 + Torque_Limit, current 0 |
Logic power without motor power. The servos have enough to talk and nothing to move with. A lit LED proves nothing here — the STS3215 has no external LED, so any light you see belongs to the adapter board and only means its barrel jack has voltage. | Read Present_Voltage: ~120–135 means 12 V and is healthy; ~50 means the bus is on a 5 V rail. Take 12 V from a battery's car/DC socket, never a USB-to-barrel cable. |
could not open port /dev/xle_arms |
The udev symlinks were never created, or a rules file from an older build has different serials in it. | Delete any stale /etc/udev/rules.d/99-xlerobot.rules, then run python diagnostics/detect_buses.py --write — see software step 7. |
| Grasp lands confidently in the wrong place Motion is smooth, the target is simply not there |
The camera-to-base transform is wrong, not the IK. Head tilt and pan feed that transform, so swapping the two axes — or reading the wrong motors as "head" — produces a transform that looks entirely plausible. | Confirm on your hardware that ID 1 moves up/down and ID 2 left/right. Then work through diagnostics/debug_transform_chain.py and diagnose_fk_vs_vision.py. |
| A script connects, but drives the wrong arm | Single-arm scripts address motor IDs 1–6, which on this build is the left arm. The right arm is at 7–12, so a port change alone will never reach it. | Use the whole-robot teleop for two-armed work — software step 11. |
| An arm falls the moment a script starts or ends | Torque was cut in one write rather than bled off. Some read-only tools release torque deliberately so you can pose the arm by hand — diagnostics/read_motors.py is one — and bus.disconnect() disables torque by default. |
Lower the arms before running anything that releases torque. In your own code, pass disconnect(disable_torque=False) and step Torque_Limit down over several seconds instead of zeroing it. |
UEFI Interactive Shell v2.2 — Shell> |
No bootable storage. Run map -r: if the only entries are MemoryMapped and Fv(...), both are internal (RAM and the QSPI firmware volume) and zero block devices are present. |
Seat a flashed microSD, or confirm firmware is 36.x for a JetPack 6 card. |
Error: could not make network connection |
Not a network fault. UEFI exhausted its boot order and fell through to PXE as a last resort. It is the tail end of "nothing bootable found." | Ignore it. Disappears once a bootable card is present. |
EXT4-fs (mmcblk0p1): error count since last fsck |
Filesystem damage on the card, usually from power loss during a write. Accumulates silently. | Schedule an fsck at next boot. Prefer clean shutdowns — SD cards tolerate abrupt power cuts poorly. |
Diagnostic Order
When a bus misbehaves, this sequence separates causes fastest. Each step rules out an entire class of problem, so work them in order rather than jumping to the most interesting theory.
- Does the adapter enumerate?
lsusb | grep 1a86andls /dev/ttyACM*. No device node means the problem is USB, not motors — stop looking at the robot. - Does any motor answer?
Runscan_port()across all baud rates. A single reply proves power, wiring, baud rate, and protocol all work. - Does one motor answer but not the chain?
That is duplicate IDs, essentially every time. Go to Motor Configuration. - Does the chain answer but drop under motion?
Cable routing at a rotating joint. Find the joint that reproduces it and add slack there.
Deep Dive: Camera Not Detected
Hardware / USBSymptoms
ls /dev/video*shows no entries or fewer cameras than expected.cv2.VideoCapture()returnsFalseforret.- YOLO tracking script errors with “no camera found”.
- Camera LED is off even though it’s plugged in.
Likely Causes
- USB cable not seated: Loose connection or damaged cable.
- USB hub not powered: Hub can’t supply enough current for multiple cameras.
- Wrong device index: Camera is at a different path than the script expects.
- Kernel driver issue: Camera module not loaded (rare on Ubuntu).
Diagnostic & Fix Steps
1. Check Physical Connection: Unplug and replug the camera. Try a different USB port. Try without the USB hub (direct to PC) to isolate the issue.
2. Check USB Power: If using a USB hub, make sure it’s powered. Low-power hubs may not supply enough current for multiple cameras.
3. Check Device Detection: You should see even-numbered entries (/dev/video0, /dev/video2) — one per camera.
# To see detailed device paths:
$ v4l2-ctl --list-devices
4. Test the Camera Directly: Use a one-line Python test to verify the OpenCV pipeline.
Verification Checklist
ls /dev/video*shows the expected number of devices.- The Python camera test returns OK.
- YOLO or teleoperation scripts run without camera errors.
Prevention Tips
- Use a powered USB hub for multiple cameras.
- Always use the same USB ports—paths change when swapped.
- Label USB cables to avoid confusion during setup.