Expand description
§device-envoy-rp
Build Pico applications with LED panels, easy WiFi, and composable device abstractions.
device-envoy-rp is a library for building embedded applications in Rust, built on the Embassy framework. It organizes hardware around device abstractions.
A device abstraction is a software encapsulation of hardware that manages timing, tasks, control flow, interrupts, channels, and state within the abstraction.
Rather than replacing HALs or drivers, device-envoy-rp builds on them. It defines device abstractions that expose a small set of simple operations to the rest of the program.
Currently targeting Raspberry Pi Pico 1 and Pico 2 (ARM cores) in device-envoy-rp, and ESP32-C6 and ESP32-S3 in device-envoy-esp. RISC-V core support on RP exists but is not actively tested.
§Start From a Template
Want a minimal starting project?
§Status
⚠️ Alpha / Experimental
The API is actively evolving. Not recommended for production use, but excellent for experimentation, learning, and exploratory projects.
§Features
- LED Strips & Panels - NeoPixel-style (WS2812) LED arrays with 2D text rendering, animation, embedded-graphics support. Provides efficient options for power limiting and color correction.
- WiFi (Pico W) - Connect to the Internet with automatic credentials management. On boot, opens a web form if WiFi credentials aren’t saved, then connects seamlessly to a stored network. Requires Pico W; WiFi is not supported on non-W boards.
- Audio Player - Play audio clips over I²S hardware with runtime sequencing, volume control, and compression.
- Button Input - Button handling with debouncing
- Servo Control - Servo positioning and animation
- Flash Storage - Type-safe, on-board persistent storage
- LCD Display - Text display (HD44780)
- IR Remote - Remote control decoder (NEC protocol)
- RFID Reader - Card detection and reading (MFRC522)
- Clock Sync - Network time synchronization utilities
- LED4 Display - 4-digit, 7-segment LED display control with optional animation and blinking
- Single LED - Single LED control with animation support
§Forum
- Using Embassy to build applications
A place to talk about writing embedded applications with Embassy: sharing code, asking practical questions, and learning what works in practice.
Not limited to Pico or ESP boards, or todevice-envoy.
§Videos and Articles
- device-envoy: Making Embedded Fun with Rust, Embassy, and Composable Device Abstractions – versions: article or video
- How Rust & Embassy Shine on Embedded Devices by Carl M. Kadie and Brad Gibson.
- More Rust articles
§Thanks
Special thanks to Brad Gibson, organizer of the Seattle Rust User Group. He introduced me to Rust programming on microcontrollers, suggested the term device abstraction, and encouraged thinking in terms of shared traits across controller families. Those conversations helped set the goals for device-envoy.
§Examples & Demos
The project includes examples (single-device tests) in examples/ and demo applications in demos/ showing integration patterns:
§Example: animated LED strip
This example cycles a 96-LED strip through red, green, and blue frames.

It shows how device-envoy generates a struct (device abstraction) for an LED strip and then animates a sequence of frames.
use device_envoy_rp::{Result, led_strip::{LedStrip as _, Frame1d, colors}};
use device_envoy_rp::led_strip;
led_strip! {
LedStripAnimated {
pin: PIN_4,
len: 96,
}
}
async fn example(spawner: embassy_executor::Spawner) -> Result<Infallible> {
let p = embassy_rp::init(Default::default());
let led_strip_animated = LedStripAnimated::new(p.PIN_4, p.PIO0, p.DMA_CH0, spawner)?;
// Create a sequence of frames and durations and then animate them (looping, until replaced).
let frame_duration = embassy_time::Duration::from_millis(300);
led_strip_animated.animate([
(Frame1d::filled(colors::RED), frame_duration),
(Frame1d::filled(colors::GREEN), frame_duration),
(Frame1d::filled(colors::BLUE), frame_duration),
]);
core::future::pending().await // run forever
}For complete, runnable examples (including wiring and setup), see the
examples/anddemos/directories.
-
Basic LED Examples: Simple on/off control with blinky pattern
-
LED Strip Examples: Simple animations, color control, text rendering
-
LED Panel Examples: 12×4, 12×8, and multi-panel configurations with graphics

- Button Examples: Debouncing and state handling
- Servo Examples: Position sweeps and animation playback
- WiFi Examples: WiFi setup, time sync, DNS
- Flash Examples: Configuration persistence and data reset
See the examples/ and demos/ directories for complete runnable code.
§Building & Running
- If you just want to use this library, start from the template project:
device-envoy-rp-blinky. - If you want to edit this project, see the Development Guide.
§Policy on AI-assisted development and contributions
The use of AI tools is permitted for development and contributions to this repository. AI may be used as a productivity aid for drafting, exploration, and refactoring.
All code and documentation contributed to this repository must be reviewed, edited, and validated by a human contributor. AI tools are not a substitute for design judgment, testing, or responsibility for correctness.
AGENTS.md contains the general instructions and constraints given to AI tools used during development of this repository.
§License
Licensed under either:
- MIT license (see the repository root
LICENSE-MITfile) - Apache License, Version 2.0 (see the repository root
LICENSE-APACHEfile)
at your option.
§Glossary
Resources available on the Pico 1 and Pico 2:
- PIO (Programmable I/O): Pico 1 has 2. Pico 2 has 3.
- DMA (Direct Memory Access): Both Pico 1 and 2 have 12 channels.
- PWM (Pulse Width Modulation) Slices: Both Pico 1 and 2 have 8 slices (& 16 channels). These “slices” are unrelated Rust slices.
- I2C (Inter-Integrated Circuit): Serial control bus used by abstractions like
lcd_text. Pico 1 and Pico 2 each provide 2 controllers (I2C0,I2C1).
Modules§
- audio_
player target_os=none, orhost - A device abstraction for playing audio clips over I²S hardware, with runtime sequencing, volume control, and compression.
- button
target_os=none - A device abstraction for buttons with debouncing and press duration detection.
- clock_
sync wifiandtarget_os=none - A device abstraction that combines NTP time synchronization with a local clock.
- docs
- Documentation-only pages for this crate.
- flash_
block target_os=none - A device abstraction for type-safe persistent storage in flash memory.
- ir
target_os=none - A device abstraction for infrared receivers using the NEC protocol.
- lcd_
text target_os=none - A device abstraction for HD44780-compatible character LCDs (e.g., 16x2, 20x2, 20x4).
- led
target_os=none - A device abstraction for a single digital LED with animation support.
- led4
target_os=none - A device abstraction for a 4-digit, 7-segment LED display for text with optional animation and blinking.
- led2d
- A device abstraction for rectangular NeoPixel-style (WS2812) LED panel displays.
For 1-dimensional LED strips, see the
led_stripmodule. - led_
strip - A device abstraction for 1-dimensional NeoPixel-style (WS2812) LED strips. For 2-dimensional
panels, see the
led2dmodule. - rfid
target_os=none - A device abstraction for RFID readers using the MFRC522 chip.
- servo
target_os=none - A device abstraction for hobby servos.
- wifi_
auto wifiandtarget_os=none - A device abstraction that connects a Pico with WiFi to the Internet and, when needed, creates a temporary WiFi network to enter credentials.
Enums§
- Error
- Define a unified error type for this crate.
Type Aliases§
- Result
- A specialized
Resultwhere the error is this crate’sErrortype.