Welcome to a small collection of drivers for Embedded Rust - especially Embassy!
If you're like the author, you might have spent time:
- selecting the right part(s)
- considering features, price and availability
- reading their documentation
- ensuring drivers fit
- learning the quirks that are not necessarily documented, anywhere
In particular, while the embedded Rust ecosystem has matured fast (2025 situation), and some MCU vendors (at least Espressif) provide great and ongoing Rust support, dealing with sensor X - in Rust - may be less pleasant. The aim of this repo is to smoothen that corner as well: to provide great Rust support for selected third party sensors.
Which sensors will be supported?
Some.
This repo covers sensors (things that measure stuff) and actuators (things that move stuff), interesting to its author.
Why Embassy? (what is it?)
Rust provides async/await
support in the language, but you'll need an executor to actually use it. Embassy is such an executor (and much more) for embedded, no-std
targets.
Writing async
code allows concurrency to be dealt with as if only one thing moved at a time (which is not true). This is great for us humans - it makes source code shorter, more understandable and ... why wouldn't you want to program async
!?
Embassy means to this repo that instead of polling your hardware (and consuming CPU cycles), your code will be awaiting an interrupt, and saving (battery) power until it's time to act!
Examples that use Embassy are indicated by the postfix
.emb.rs
.
folder | what is it? | stability | comments | |
---|---|---|---|---|
Distance sensors | ||||
![]() ![]() The actual sensors are the small components to the left. |
tof , tof/vl_api |
Time-of-flight distance sensors; 4x4 (60Hz) or 8x8 (15Hz) | beta | VL53L8 and VL53L5CX sensors supported, over I2C bus. |
Wireless | ||||
![]() BLE |
comms/ble |
Working as custom Bluetooth (BLE) service | alpha | No external components needed; shows how to bake custom BLE interface into your project. |
Development kits | ||||
![]() |
devkit/rgb |
RGB LED | WIP | |
devkit/button |
Button | -- |
Each subfolder contains a structure similar to this:
built-in/
├── Cargo.toml # Cargo build file
├── [DEVS/] # Comments for development of the particular subfolder
├── README.md # start here
├── [WIRING.md] # wiring of peripherals to MCU
├── build.rs # additional build details
├── examples
│ └── button.rs # examples you can run (if HW is properly set up)
├── [pins.toml] # configuration of MCU pins
├── set-target.sh # (link to a) tool to switch between MCU's
└── [src] # library code
By keeping the folder structure similar, getting to speed with a new kind of sensor/actuator should be as swift as possible.
The repo focuses on ESP32 series MCU's; this is mainly so that the stated support remains maintained and tested.
The Rust / Embassy ecosystem, as such, provides the possibility to support more families; it's a matter of human effort. Let the author know if you'd like to become co-author, responsible for some other MCU's.
MCU | dev board | support level | notes |
---|---|---|---|
ESP32‑C6 | ESP32-C6-DevKitM-01 | used regularly | No problems! |
ESP32‑C3 | ESP32‑C3-DevKitC-02 | used sometimes | See below |
-
The chip does provide a built in USB/JTAG circuitry, but the suggested devkit doesn't have a connector for it. You can solder one, or (perhaps a better approach?), attach a cable to breakout pins on a breadboard.
-
I2C functionality - and possibly other time sensitive functionality - is known to suffer from a JTAG specification issue that affects
probe-rs
's ability to interface with the chip. If you need long I2C communications, ESP32-C6 is the better chip to target.[!NOTE] The problem only involves debugging/logging over JTAG. You can quite well do long I2C transactions in production.
Projects such as esp-hal
use Cargo features mechanism for selecting the target MCU (e.g. esp32c3
vs. esp32c6
). While this seems to be the norm, this repo deviates from it.
The main reason is philosophical. Features should be used for - well - features of the code base, and they should be cumulative (by the Rust recommendations). Using features for MCU selection, however, are exclusive.
So what do we do?
There are .config/cargo.toml
files under certain folders in the repo. These decide the MCU chip for the particular folder and its subfolders.
This means that you can, for example:
- use
dc-motors
code, targeting ESP32-C3, while.. - using
tof
code, targeting ESP32-C6
This at least matches the way the author works; there's always a particular breadboard wired for working with such software.
To change the folder's MCU target,
$ cd dc-motors
$ $ ./set-target.sh
1) esp32c3
2) esp32c6
Pick your target: 1
Going to edit:
- .cargo/config.toml
- ./drv8871/Cargo.toml
The edit is safe. You can see the changes made by 'git diff' (and revert by 'git restore --staged .cargo/config.toml ./drv8871/Cargo.toml').
Proceed? (Y/n) Y
Files '.cargo/config.toml' and './drv8871/Cargo.toml' now using:
MCU: esp32c3
TARGET: riscv32imc-unknown-none-elf
Please 'cargo build' or 'cargo run', as usual.
You can see the change by git diff
, i.e. the selected (default) MCU type gets stored in the version control.
This approach is a bit intrusive, but having used it for a while the author does prefer it over the features
approach, at least for the case of the ZOO (full of examples). For publishing a library, using the feature mechanism is likely preferrable (or only working solution).
- One of the dev kits mentioned above
- The necessary sensors (see particular subfolder)
- Breadboard
- Wires
Each sensor's subsection has a WIRING.md
that shows suggested wiring. You can change the pin layout by editing the pins.toml
file found in the same subfolder.
The repo can be used in multiple ways. Here, we walk you through the two that the author is actively using:
- macOS + Multipass VM
- Windows + WSL2
What's important is that:
- you are running Ubuntu Linux on the command prompt
- you have a working setup for either
probe-rs
(orespflash
) to reach your MCU
Please read this section to the end, and then decide how you'd like your setup to be.
Below, we use terms:
"desktop environment" = the OS you read your emails in
Pros:
- digital security: by using a VM, your build environment cannot reach your desktop environment - except for the source files which are mapped between the two
- electric safety: galvanic isolatation of MCU & wiring means no chance of frying your desktop computer (or laptop)
- tools added don't accumulate on your desktop environment; easy to start anew
- you can limit the amount of resources (disk, CPU) given to the build environment
Cons:
- managing Multipass
- Multipass needs a few hoops to get performance right
- need two computers
- need to use repos
mp
andprobe-rs-remote
to get the setup done right
Multipass is available also on Linux and Windows, making this a very OS-agnostic way to develop one's code.
For running Multipass on Windows, please note that only Windows Pro has Hyper-V. The author hasn't run Multipass on Windows (since WSL2 is there) but if he would, he'd pick a Pro license. You can run Multipass with Windows Home, but that involves VirtualBox.
#yuck
Pros:
- easy to get going if you have a Windows machine
- works also on Windows 10 Home
- only one computer is needed
Cons:
- no galvanic isolation from the MCU & wiring
- no digital safety: WSL2 can reach your main environment (it's not a sandbox)
- need to set up USB/IP, to reach the USB device in Linux (very smooth experience!)
The author uses this setup for travel (incl. visits to a Hacklab).
Note that in this setup, the source folders (your Git repos) should remain on the WSL2 partition. The Windows IDE's can reach them there, without problems, and the performance is way better this way.
Also note that - while WSL2 does use a Virtual Machine - there's no isolation between your development and desktop environments. They now run different OS'es, but you can still e.g. touch /mnt/c/Users/{yourid}/Desktop/abc.txt
, i.e. create and use stuff from the desktop. This means, so can the libraries you are working with!!
Also, probe-rs
in this case is installed within the WSL2, and accesses the devkit via USB/IP. USB/IP between a Windows host and WSL2 is very smooth and there's no reason for the ssh
stuff.
This scenario is ideal if you want to work on a single computer, e.g. for taking demos out on the field a Windows laptop is sufficient!
Galvanic isolation
Consider using a USB Isolator to protect your USB port. If you do, the author would like to hear your experiences.
In particular, of interest:
- do they still provide power for the MCU?
- does using one slow down the development (e.g. flashing), compared to directly fitting the MCU?
**Installing Multipass setup**
- Visit the
mp
andprobe-rs-remote
repos, and try to get the setup running.
**Installing WSL2 setup**
-
Set up USB/IP to see your MCU from the WSL2 prompt. Instructions in
USBIP-WSL2
. -
Install a Rust environment on WSL2, with:
$ rustup target add riscv32imc-unknown-none-elf $ rustup target add riscv32imac-unknown-none-elf
-
Install
probe-rs
either by:- curl; follow the
Linux
options cargo binstall probe-rs-tools
cargo install probe-rs-tools --locked
See the main page for comparison of the approaches.
- curl; follow the
Testing:
You should be able to (with MCU connected)..
$ probe-rs list
The following debug probes were found:
[0]: ESP JTAG -- 303a:1001:54:32:04:07:15:10 (EspJtag)
..get the list of MCU's you have connected to the auxiliary computer.
Let the author know if there are gotchas - e.g. by creating an issue.
As you can see, there are some different ways to set up the toolchain.
What's important to take home from this is that
- The ZOO runs on Ubuntu Linux only. With virtualization, however, this should not limit your choices.
probe-rs
is the tool of choice for interacting with your development kit. The build scripts don't care whether such command leads to USB/IP or assh
-bridged installation.
Good luck! ☀️☀️☀️
Visit the subfolders, pick any one you'd like to try. The instructions are within their particular README.md
.
PLEASE give feedback on the GitHub!