Action
We'll use the Embassy HAL for this exercise.
Project from template
To set up the project, run:
cargo generate --git https://github.com/ImplFerris/pico2-template.git
When prompted, give your project a name, like "dracula-ldr" and select embassy
as the HAL.
Then, navigate into the project folder:
cd PROJECT_NAME
# For example, if you named your project "dracula-ldr":
# cd dracula-ldr
Interrupt Handler
Let's set up interrupt handling for the ADC.
#![allow(unused)] fn main() { use embassy_rp::adc::InterruptHandler; bind_interrupts!(struct Irqs { ADC_IRQ_FIFO => InterruptHandler; }); }
In simple terms, when the ADC completes a conversion and the result is ready, it triggers an interrupt. This tells the pico that the new data is available, so it can process the ADC value. The interrupt ensures that the pico doesn't need to constantly check the ADC, allowing it to respond only when new data is ready.
Read more about RP2350 interreupts in the datasheet (82th page).
Initialize the Embassy HAL
#![allow(unused)] fn main() { let p = embassy_rp::init(Default::default()); }
Initialize the ADC
#![allow(unused)] fn main() { let mut adc = Adc::new(p.ADC, Irqs, Config::default()); }
Configuring the ADC Pin and LED
We set up the ADC input pin (PIN_26) for reading an analog signal. Then we set up an output pin (PIN_15) to control an LED. The LED starts in the low state (Level::Low), meaning it will be off initially.
#![allow(unused)] fn main() { let mut p26 = Channel::new_pin(p.PIN_26, Pull::None); let mut led = Output::new(p.PIN_15, Level::Low); }
Main loop
The logic is straightforward: read the ADC value, and if it's greater than 3800, turn on the LED; otherwise, turn it off.
#![allow(unused)] fn main() { loop { let level = adc.read(&mut p26).await.unwrap(); if level > 3800 { led.set_high(); } else { led.set_low(); } Timer::after_secs(1).await; } }
The full code
#![no_std] #![no_main] use embassy_executor::Spawner; use embassy_rp::adc::{Adc, Channel, Config, InterruptHandler}; use embassy_rp::bind_interrupts; use embassy_rp::block::ImageDef; use embassy_rp::gpio::{Level, Output, Pull}; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; #[link_section = ".start_block"] #[used] pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); bind_interrupts!(struct Irqs { ADC_IRQ_FIFO => InterruptHandler; }); #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); let mut adc = Adc::new(p.ADC, Irqs, Config::default()); let mut p26 = Channel::new_pin(p.PIN_26, Pull::None); let mut led = Output::new(p.PIN_15, Level::Low); loop { let level = adc.read(&mut p26).await.unwrap(); if level > 3800 { led.set_high(); } else { led.set_low(); } Timer::after_secs(1).await; } }
Clone the existing project
You can clone (or refer) project I created and navigate to the dracula-ldr
folder.
git clone https://github.com/ImplFerris/pico2-embassy-projects
cd pico2-embassy-projects/dracula-ldr/