A rust program that sends HC-SR04 (Ultrasonic distance sensor) data to an MQTT broker.
Use cases include intrusion detection, water level monitoring and others.
git clone [email protected]:Benehiko/pico-ultrasonic-rs.git && cd pico-ultrasonic-rs/You need to install rust and install elf2uf2-rs and probe-rs
cargo install elf2uf2-rs --locked
# be sure to check the linked website for furthre instructions
cargo install probe-rs --cliSince the pico has a different architecture than your development
machine, you will need to install the rust toolchain for
thumbv6m-none-eabi.
rustup target add thumbv6m-none-eabiFor more detailed instructions, please take a look at The Embedded Rust Book.
To compile the program you need to export some environment variables that will be baked into the compiled application.
export RP_WIFI_NETWORK="MySSID"
export RP_WIFI_PASSWORD="1234"
export RP_MQTT_SERVER_IP=192.168.1.100
export RP_MQTT_SERVER_PORT=9000
export RP_MQTT_USERNAME="foo"
export RP_MQTT_PASSWORD="bar"MQTT_USERNAME,MQTT_PASSWORDandMQTT_SERVER_PORTare optional.
After you have installed all the required dependencies on your OS, run
# mount the pico (press and hold bootsel while powering on)
cargo run --release --bin pico-ultrasonic-rsYou need an MQTT broker. For quick testing on your local network, spin up a mosquitto instance.
printf '%s\n' 'listener 1883' 'allow_anonymous true' 'max_keepalive 43200' > mosquitto.conf
mosquitto -c mosquitto.conf
Then listen on the pico topic on your machine or another local network device.
mosquitto_sub -p 1883 -t "pico"
Other topics to listen to: pico, pico-status.
Topics the pico are subscribed to: pico-time.
Send the pico 0 or no payload on pico-time for it to immediately start. Otherwise specify in seconds
how long it should sleep for. Negative numbers aren't allowed.
To conserve the pico power source it might be preferrable to set a time (in seconds) for which the pico should be idle. In this state it will drop it's network connectivity, cleanup some memory and wait. After waiting it will reset and re-request a time in seconds to wait.
# send no payload
mosquitto_pub -p 1883 -t "pico-time" -n
# send a wait of 10 seconds
mosquitto_pub -p 1883 -t "pico-time" -m 10You can use a breadboard, but I used female to female jumper cables.
Sensor | Pico
VCC -> VSYS (5V) GND -> GND Trigger -> GP2 Echo -> GP3
The program uses the embassy-rs/embassy
packages for the WIFI drivers and GPIO interface.
Sometimes it's necessary to clone embassy to your machine when developing, for
example when using the embassy-usb-logger package.
git clone [email protected]:embassy-rs/embassy.gitEnsure that you clone this repository in the same root directory as embassy, otherwise it won't build.
-- root
-- embassy
-- rp-ultrasonic-rs
The Pico needs to be mounted as a storage device on your development machine.
Press and hold the BOOTSEL button on the pico while plugging
the USB cable into your host machine.
It will immediately come up as a mounted storage drive.
Next, you will need to run cargo run which will flash the Pico
with the latest build.
cargo run --release --bin pico-ultrasonic-rsTo output logs from your Pico you will need to have a local version of embassy and
use the feature = 'usb-logger'.
cargo run --features usb-logger --release --bin pico-ultrasonic-rsSince this is an embedded device, the std rust
library cannot be used. Always try use core instead or find another
alternative.
Explaining what happened
cargo builds the application based on the .cargo/config.toml target,
which in this case is thumbv6m-none-eabi and then executes
elf2uf2-rs with the -s flag to attach to the serial
port for log output.
Here is an exerpt of the .cargo/config.toml file.
[target.thumbv6m-none-eabi]
runner = "elf2uf2-rs -d -s"
[build]
target = "thumbv6m-none-eabi"Handling panics
In debug mode (omit --release from cargo run), the Pico will not reboot
and can be used with the debugger to get the last panic message.
If you have a debugger connected to your Pico, you can use the openocd
See the Pico documentation under Appendix A for using another Pico as a USB → SWD and UART bridge (Picoprobe).
When deploying your Pico into the wild, you might not have the relevant equipment to diagnose your Pico, such as your laptop.
The software uses the Pico's LEDs to give you some idea of what it's doing.
- Pico boots initializing the wifi drivers to access the onboard LED.
- Pico signals 2x1second blinks to show it is alive.
- Next it signals 5x1 second blinks to show it will connect to the specified AP.
- It will wait 2 seconds.
- On attempt of connection to AP it will blink.
- It will then attempt DHCP which gives rappid blinks (very rappid)
- Solid green means it has an IP and will start reading the HC-SR04 sensor
- On each attempt to read the HC-SR04 sensor it will blink
What about random errors and panics?
The Pico will restart itself when it panics or does not succeed on an important task.
For example, it does not connect to the AP after a few attempts or DHCP is unsucessful.
But only with the cargo run --release flag!
https://www.handsontec.com/dataspecs/HC-SR04-Ultrasonic.pdf
https://www.tomshardware.com/how-to/raspberry-pi-pico-ultrasonic-sensor
https://microcontrollerslab.com/hc-sr04-ultrasonic-sensor-raspberry-pi-pico-micropython-tutorial/
The HC-SR04 implementation is pretty much a rewrite of https://github.com/marcoradocchia/hc-sr04 with the difference being the underlying library that does the GPIO communications.


