rdk-peripheral-cookbook
Skill1 starsChanged 3 months agoApache-2.0View on GitHub
Hands-on peripheral driving on RDK boards — GPIO/I2C/SPI/UART/PWM, servos, DC/stepper/BLDC motors, LED/WS2812, audio (ALSA), and CAN (X5 SocketCAN vs S100/S600 MCU-domain CANHAL) — plus cross-platform pin/bus mapping and zero-driver diagnosis. Use whenever the user wants to actually light an LED, spin a motor, read a sensor, play/record audio, wire a servo, bring up CAN, or when a peripheral plugged into the board is "not detected / no driver". 触发词:点灯、GPIO 不工作、libgpiod、i2cdetect、PCA9685、舵机、步进电机、无刷、WS2812 灯带、ALSA 播放录音、aplay、CAN、SocketCAN、cansend、candump、S100 CAN、S600 自锁口、40PIN 接线、拨码开关、设备不识别没驱动. Routing — pure GPIO pin-number facts / per-board pinout tables → rdk-hardware (cite it when wiring); device error-code lookup / "板子报错" → rdk-board-knowledge; connector/cable/accessory part numbers → rdk-accessories.
- Deletes or force-pushes
- Installs packages
2 other projects use a version of this, 2 of them edited.
Adopted by
Most recently taken up by
- D-Robotics/rdk-device-skillsedited, first seen Oct 15, 2026
- D-Robotics/rdk-skillsedited, first seen Oct 9, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 2
- D-Robotics/rdk-skills★ 5100% same
- D-Robotics/rdk-device-skills★ 4100% same
Wrote their own version · 0
None found.
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository59 other files it gives its agents.
- bsp-bootloader-buildSkill
- bsp-deb-buildSkill
- bsp-env-setupSkill
- bsp-image-buildSkill
- bsp-kernel-buildSkill
- bsp-rootfs-customSkill
- bsp-source-syncSkill
- bsp-s-seriesSkill
- hmct-workflowSkill
- horizon-routerSkill
- ucpSkill
- x5-accuracy-diagnosticsSkill
- x5-board-monitorSkill
- x5-bpu-python-apiSkill
- x5-calibration-data-prepareSkill
- x5-consistency-diagnosticsSkill
- x5-environment-installSkill
- x5-environment-probeSkill
- x5-environment-setupSkill
- x5-model-diagnosticsSkill
- x5-model-preflightSkill
- x5-performance-diagnosticsSkill
- x5-ptq-compileSkill
- x5-ptq-config-authoringSkill
- x5-ptq-deploySkill
- x5-qat-adaptationSkill
- x5-qat-compileSkill
- x5-qat-deploySkill
- x5-qat-trainingSkill
- x5-routerSkill
- x5-runtime-cpp-inferSkill
- x5-runtime-deploySkill
- x5-runtime-perf-evalSkill
- rdk-accessoriesSkill
- rdk-board-delegateSkill
- rdk-board-knowledgeSkill
- rdk-camera-setupSkill
- rdk-command-manualSkill
- rdk-diagnosticSkill
- rdk-docs-referenceSkill
- rdk-ecosystemSkill
- rdk-embodied-lerobotSkill
- rdk-gpio-40pinSkill
- rdk-hardwareSkill
- rdk-headless-modeSkill
- rdk-llm-deploymentSkill
- rdk-log-forensicsSkill
- rdk-memory-auditSkill
- rdk-model-benchmarkSkill
- rdk-model-deploySkill
- rdk-model-zooSkill
- rdk-multimediaSkill
- rdk-network-remoteSkill
- rdk-source-mapSkill
- rdk-system-configSkill
- rdk-system-maintainSkill
- rdk-tros-setupSkill
- rdk-vision-pipelineSkill
- d-robotics-pack-installerSkill
The file
We split this skill into the rules it gives an agent
11 rules. About 0 are common, 3 are distinctive, and 8 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
8
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- could be automatic: a setting could enforce it
- Very specific: line 47
Use
Hobot.GPIO: only when you need RPi-tutorial compatibility (its API copies RPi.GPIO). - Very specific: line 48
Real-time / <1ms jitter?: Call libgpiod from C, or on X5 use x5-hobot-io (C bindings, ~10× lower latency than Python Hobot.GPIO).
- Very specific: line 93
S100/S600: start MCU1, build the /app/Can sample (make), edit the JSON config to the right IPC instance/channel for your CAN line, then …
- Very specific: line 110
Answer template: ask for board model + interface (USB / 40PIN I2C / UART / MIPI) + device model → have the user run dmesg/lsusb/ls /dev and …
- Very specific: line 125
No TROS needed — go straight to ALSA.
- Distinctive: line 145
When answering from this skill, follow these rules — never fabricate facts, commands, or file paths:
- Distinctive: line 148
No fabrication when tools are missing: If a script or reference doesn't exist, say "not found" — don't invent from memory.
- Very specific: line 149
Preserve null/false/empty on failure: If a probe returns null or false, report that — don't substitute a plausible value.
- Very specific: line 150
No substitution off-platform: If off_platform: true, say "probe didn't run on an RDK board" — don't guess what it would have returned.
- Distinctive: line 152
Acknowledge sandbox limits: If you can't run a command, say so — don't pretend you did.
- Very specific: line 153
Read-only boundary: Never modify the system — no dd, mkfs, rm -rf, apt install, reboot, or GPIO output without explicit user confirmation.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
RDK Peripheral Cookbook
Drive a real peripheral on an RDK board: GPIO, I2C, SPI, UART, PWM, servos, motors, LEDs, audio, and CAN. The single rule that prevents the most damage: never power a servo, motor, or LED strip from 40PIN Pin 2/4 (5V) — even one SG90 stall current can brown out the board and reboot it. Always use an external 5V/6V supply and share GND.
Sources: official D-Robotics docs (rdk_doc / rdk_s_doc 40pin user guide, rdk_x5/can.md, mcu_development/09_mcu_can.md), the x5-hobot-io toolchain, and standard cross-platform Linux peripheral practice. Every non-trivial board-specific claim is verified against the cited source; cross-platform Linux facts (libgpiod, ALSA, PCA9685) are standard and noted as such.
The one rule that matters most
A peripheral that needs current — servo, DC/stepper/BLDC motor, WS2812 strip — must NOT draw its power from the 40PIN 5V rail (Pin 2/4). Stall or full-load current pulls the rail down and reboots the board. Always: external 5V/6V supply for the load, signal line back to the board, common GND. This applies on RDK, Raspberry Pi, Jetson, and Rockchip alike — it is not RDK-specific.
Decision cheat-sheet (pick the right approach)
| Need | First-choice approach |
| Cross-board GPIO / unsure of pin number | libgpiod (gpiodetect / gpioinfo / gpiofind "GPIO17") — don't guess BCM numbers |
| Single servo (1–2 ch) | On-board hardware PWM (50Hz / 20ms period, 1.0–2.0ms pulse), external supply |
| Multiple servos (≥3 ch) | PCA9685 + I2C (default addr 0x40), servo power on PCA9685's V+ terminal |
| DC motor | H-bridge (TB6612 / DRV8833 / BTS7960) + PWM speed + GPIO direction |
| Stepper motor | Dedicated driver (A4988 / DRV8825 / TMC2209 silent) + STEP/DIR |
| Brushless (BLDC) | RC ESC (50Hz PWM, reuse PCA9685) or ODrive/VESC (UART/CAN closed-loop); on S100 use the MCU real-time domain |
| WS2812 RGB strip | SPI MOSI emulating the 800kHz timing (run SPI at 2.4MHz, NeoPixel-SPI). RPi's rpi_ws281x does NOT work on RDK |
| Audio (no TROS) | Standard ALSA (aplay -l / arecord / alsamixer); a USB sound card is the universal fallback |
| CAN | Only X5 is Linux SocketCAN (TCAN4550): ip link set can0 type can bitrate 500000 dbitrate 2000000 fd on + can-utils. S100/S600 CAN lives in the MCU domain — use CANHAL/IPC + /app/Can sample, NOT ip link. X3/Ultra have no on-board CAN. Full bringup: rdk-can-and-board-io.md |
Safety rules (check before powering any peripheral)
- Never take 5V for servos/motors/WS2812 from 40PIN Pin 2/4. External 5V/6V supply, common GND with the board.
- Scan before you read/write. I2C: run
i2cdetect -y <bus>and confirm the address appears first. PWM: start at low frequency / low duty. - Persistent kernel/boot changes are the highest risk (
/boot, device tree, MCU firmware). On RDK, don't touch them unless necessary. - RDK-specific trap: a 40PIN pin may default to GPIO. On X-series, switch the function first via
sudo srpi-config→3 Interface Options→I3 Peripheral bus config(or the/app/40pin_samples/scripts) before/dev/i2c-Xor apwmchipappears. S100 muxes I2C5/UART2 on the 40PIN with a dip switch (pick one). S600 has NO standard 40PIN — self-locking connectors, 1.8V digital IO; the 40PIN wiring in this cookbook does not apply to S600 (see rdk-can-and-board-io.md §4 and rdk-hardware).
Workflows
Workflow 1 — Cross-board GPIO (light an LED, read a button)
Use when: 点灯, GPIO 不工作, blink, button read, writing a script meant to run on more than one board.
- Enumerate, don't guess.
gpiodetect→ lists every gpiochip.gpioinfo gpiochip0→ shows each line's name. - Operate by name for portability:
gpioset $(gpiofind "GPIO17")=1. This is the only API common to RDK / RPi / Jetson / Rockchip. - Use
Hobot.GPIOonly when you need RPi-tutorial compatibility (its API copiesRPi.GPIO). It is system-Python only —import Hobot.GPIOinside conda/venv fails; use/usr/bin/python3. - Real-time / <1ms jitter? Call
libgpiodfrom C, or on X5 usex5-hobot-io(C bindings, ~10× lower latency than PythonHobot.GPIO). - Verify — run
bash scripts/gpio_probe.shfor structured JSON (gpio_lines,can_interfaces,can0_state). Confirmgpio_lines> 0 (or note thegpio_noteif libgpiod is missing) before proceeding with GPIO operations.
Details and the cross-platform pin/bus mapping: hardware-notes.md.
验证: bash scripts/gpio_probe.sh returns gpio_lines > 0; gpioinfo gpiochip0 shows each line's name and consumer; gpioget $(gpiofind "GPIO17") reads the expected level (0 or 1).
Workflow 2 — Servos and motors
Use when: 舵机, 步进电机, 直流电机, 无刷, motor won't turn, robot joint.
- Single servo (1–2 ch): on-board hardware PWM. Signal = 50Hz (20ms period) + 1.0ms (0°) to 2.0ms (180°) pulse. Switch the pin to PWM mode first (
srpi-configon X-series), then drive via/sys/class/pwm/pwmchipN/. - ≥3 servos: PCA9685 + I2C (addr
0x40, 16ch, 12-bit). Servo power goes to PCA9685's V+ screw terminal, never the 40PIN rail. - DC motor: H-bridge + PWM (speed) + GPIO (direction). TB6612FNG for a small 2-wheel car, BTS7960 for high current.
- Stepper: dedicated driver + STEP/DIR (2 GPIO, no PWM needed). TMC2209 if silence matters.
- BLDC: RC ESC (50Hz PWM like a servo) for open-loop; ODrive/VESC (UART/USB/CAN) for closed-loop. Bus servos (Feetech STS / Dynamixel) over USB-TTL are the standard for desktop arms / quadrupeds — one wire, many addressable servos.
Full wiring tables, code, and the PCA9685 troubleshooting steps: hardware-notes.md §Servos and §Motors.
验证: servo — cat /sys/class/pwm/pwmchipN/pwmX/enable shows 1 and the shaft holds position; PCA9685 — i2cdetect -y <bus> shows 0x40 and servos respond; motor — shaft turns and dmesg | tail shows no overcurrent warnings.
Workflow 3 — Audio without TROS (ALSA)
Use when: play/record audio and hobot_audio (TROS + official mic-array board) is not available.
- Probe:
aplay -l/arecord -llist output/input cards. Nothing listed → kernel didn't see hardware → checklsusbanddmesg | grep -i snd. - Play:
aplay test.wav, oraplay -D plughw:1,0 test.wavfor a specific card. MP3 needsmpg123/soxfirst. - Record:
arecord -D plughw:1,0 -f S16_LE -r 16000 -c 1 -d 5 test.wav. - Silent but a card exists?
alsamixer→ unmute (M), raise volume. Busy/"unable to open slave" → another process holds it (sudo fuser /dev/snd/*). - Universal fallback: plug in a USB sound card —
snd-usb-audioauto-loads andaplay -lshows it immediately. This is the only recommended path on Jetson (no on-board audio) and on RDK without an I2S HAT.
Command catalog and error table: hardware-notes.md §Audio.
验证: aplay -l lists the card; aplay test.wav plays sound; arecord -D plughw:1,0 -d 1 test.wav records and aplay test.wav plays it back; alsamixer shows the card unmuted.
Workflow 4 — CAN bringup
Use when: CAN, SocketCAN, cansend, candump, S100/S600 CAN.
- Identify the board first — this decides everything (
scripts/can_mode.py <board>answers it deterministically):- X5 → Linux SocketCAN (TCAN4550 on SPI5).
ip link+can-utils. Has acan0network device. - S100 / S600 → CAN controller is in the MCU domain. Use CANHAL library + IPC + the
/app/Cansample. There is nocan0—ip link set canXdoes not apply. - X3 / Ultra → no on-board CAN.
- X5 → Linux SocketCAN (TCAN4550 on SPI5).
- X5 quick self-test (loopback):
ip link set can0 type can bitrate 125000→loopback on→up→candump can0 -L &→cansend can0 123#1122334455667788. - X5 CAN FD:
ip link set can0 type can bitrate 500000 dbitrate 2000000 fd on; send an FD frame with##(e.g.cansend can0 123##3...). - S100/S600: start MCU1, build the
/app/Cansample (make), edit the JSON config to the right IPC instance/channel for your CAN line, then./canhal_get bypass &/./canhal_send bypass <ch>. Terminate the bus with the right 120Ω element (X5 = switch, S100 = jumper, S600 = dip ON).
Full per-board CAN bringup, IPC channel maps, S100 dip mux, and S600 self-locking IO: rdk-can-and-board-io.md.
验证: X5 — ip link show can0 shows UP; candump can0 -L receives frames after cansend can0 123#1122334455667788; S100/S600 — ./canhal_get bypass prints received CAN frames without error; bus terminator is set (X5 switch / S100 jumper / S600 dip ON).
Workflow 5 — Zero-driver diagnosis (device not detected)
Use when: "I plugged in X but the board doesn't recognize it / no driver". Don't guess — run the 9 steps. Universal across RDK / RPi / Jetson / Rockchip.
dmesg | tail -50 → lsusb → ls /dev/ (tty*/video*/i2c-*/spidev*/snd/)
→ i2cdetect -l && i2cdetect -y <bus> → v4l2-ctl --list-devices
→ aplay -l / arecord -l → lsmod | grep <kw> → modinfo/modprobe <mod>
→ cat /proc/device-tree/…Answer template: ask for board model + interface (USB / 40PIN I2C / UART / MIPI) + device model → have the user run dmesg/lsusb/ls /dev and paste back → match the symptom table → give the smallest verifiable command → only then discuss ROS2-node wrapping / autostart.
Symptom→diagnosis table and the three orthogonal fix paths: hardware-notes.md §Zero-driver diagnosis.
验证: dmesg | tail -50 shows device enumeration (or explains why it's missing); ls /dev/ shows the expected device node (tty*/video*/i2c-/spidev/snd*); lsmod | grep <kw> shows the driver loaded.
Worked examples
Example 1 — "我在 S100 上敲 ip link set can0 type can bitrate 500000 不工作"
That's the X5 path. S100's CAN is in the MCU domain — there is no can0 network device. Answer: "S100/S600 don't expose SocketCAN. The CAN controller lives in the MCU domain; Acore reaches it through CAN2IPC → IPC → the CANHAL library. Use the /app/Can sample: start MCU1, make the sample, set the IPC instance/channel in its JSON config (e.g. S100 CAN6 = instance 0 / channel 6), then ./canhal_get bypass & and ./canhal_send bypass 6. ip link, cansend, candump only work on X5." Point to rdk-can-and-board-io.md §2.
Example 2 — "想在 RDK X5 上接 4 个舵机,怎么接线?"
Don't drive 4 servos from on-board PWM or the 40PIN rail. Answer: "Use a PCA9685 (I2C, default 0x40, 16 channels). Wire SDA/SCL/VCC/GND to the board; put the servo power on the PCA9685 V+ screw terminal from an external 5V/5A supply, common GND. Confirm with i2cdetect -y <bus> that 0x40 shows up before coding. If servos jitter, it's almost always supply, not signal." Point to Workflow 2.
Example 3 — "插了 USB 麦克风,想录音,没装 TROS"
No TROS needed — go straight to ALSA. Answer: "arecord -l to find the card (e.g. card 1). Record with arecord -D plughw:1,0 -f S16_LE -r 16000 -c 1 -d 5 test.wav, play back with aplay test.wav. If nothing shows in arecord -l, check lsusb and dmesg | grep -i snd — a USB mic should auto-load snd-usb-audio." Point to Workflow 3.
Example 4 — "我接了个 WS2812 灯带,GPIO 拉高拉低控制不了"
GPIO bitbang can't hold the WS2812 800kHz timing reliably. Answer: "Drive WS2812 from the SPI MOSI pin, emulating the timing: run SPI at ~2.4MHz and encode each WS2812 bit as 4 SPI bits, via Adafruit-CircuitPython-NeoPixel-SPI. RPi's rpi_ws281x does NOT work on RDK. And 30 LEDs at full white ≈ 1.8A — power the strip from an external 5V supply with common GND, never the 40PIN rail." Point to hardware-notes.md §LEDs.
Common pitfalls
| ❌ Don't | ✅ Do |
| Power servos/motors/WS2812 from 40PIN Pin 2/4 | External 5V/6V supply, common GND |
Run ip link set can0 ... on S100/S600 | Use the MCU-domain CANHAL /app/Can sample (only X5 is SocketCAN) |
| Guess BCM numbers in a cross-board script | Use libgpiod by line name (gpiofind "GPIO17") |
| Read I2C before confirming the address | i2cdetect -y <bus> first, then read/write |
Expect /dev/i2c-X / pwmchip to exist by default | Switch the 40PIN function first (X5 srpi-config; S100 dip switch) |
import Hobot.GPIO inside conda/venv | Use system /usr/bin/python3 (bindings are system-only) |
| Drive WS2812 via GPIO bitbang | SPI MOSI emulation at 2.4MHz (NeoPixel-SPI) |
| Assume S600 has a 40PIN | S600 uses 1.8V self-locking connectors (§4) |
Anti-hallucination guardrails
When answering from this skill, follow these rules — never fabricate facts, commands, or file paths:
- Report only observed data. Quote what scripts/commands actually return, not what you remember. If the probe says
board_id: X5, answer for X5 — even if the user insists it's an S100. - No fabrication when tools are missing. If a script or reference doesn't exist, say "not found" — don't invent from memory. Route to the appropriate skill or doc instead.
- Preserve null/false/empty on failure. If a probe returns
nullorfalse, report that — don't substitute a plausible value. Empty output is data, not an error to "fix". - No substitution off-platform. If
off_platform: true, say "probe didn't run on an RDK board" — don't guess what it would have returned. Ask for on-board logs. - No hand-editing JSON. Scripts emit structured JSON; never hand-craft output. If the contract says
{ok,off_platform,reason,fields}, that's what goes to the user. - Acknowledge sandbox limits. If you can't run a command, say so — don't pretend you did. Offer the command for the user to run.
- Read-only boundary. Never modify the system — no
dd,mkfs,rm -rf,apt install,reboot, or GPIO output without explicit user confirmation.
Reference map
| Read this | When |
| gpio-commands.md | Quick command/risk table for I2C / SPI / GPIO / pinmux probing |
| hardware-notes.md | Deep dives: cross-platform 40PIN pin/bus mapping, libgpiod, servos & PCA9685, motor paradigms, LEDs/WS2812, ALSA audio, zero-driver diagnosis SOP |
| rdk-can-and-board-io.md | CAN bringup (X5 SocketCAN / S100·S600 MCU-domain CANHAL), S100 I2C5↔UART2 dip mux, S600 self-locking IO (GPIO/UART6-7/SPI1) |
scripts/can_mode.py <board> | Deterministic "is this board SocketCAN or MCU-domain CAN?" lookup (X5/S100/S100P/S600/X3/Ultra) |
scripts/gpio_probe.sh | Live GPIO/CAN probe — reads gpioinfo for GPIO line count + scans /sys/class/net/can* for CAN interfaces + checks can0 operstate (structured JSON {ok,off_platform,reason,fields}; non-board → {"ok":false,"off_platform":true,"reason":"not_on_rdk_board","fields":null}; board-but-no-libgpiod → reason="libgpiod not found") |
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

