Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

LED Dimming on Raspberry Pi Pico with Embassy

Let’s create a dimming LED effect using PWM on the Raspberry Pi Pico with Embassy.

Generate project using cargo-generate

By now you should be familiar with the steps. We use the cargo-generate command with our custom template, and when prompted, select Embassy as the HAL.

cargo generate --git https://github.com/ImplFerris/pico2-template.git --tag v0.3.1

Update Imports

Add the import below to bring the PWM types into scope:

#![allow(unused)]
fn main() {
use embassy_rp::pwm::{Pwm, SetDutyCycle};
}

Initialize PWM

Let’s set up the PWM for the LED. Use the first line for the onboard LED, or uncomment the second one if you want to use an external LED on GPIO 16.

#![allow(unused)]
fn main() {
// For Onboard LED
let mut pwm = Pwm::new_output_b(p.PWM_SLICE4, p.PIN_25, Default::default());

// For external LED connected on GPIO 16
// let mut pwm = Pwm::new_output_a(p.PWM_SLICE0, p.PIN_16, Default::default());
}

Main logic

In the main loop, we create the fade effect by increasing the duty cycle from 0 to 100 percent and then bringing it back down. The small delay between each step makes the dimming smooth. You can adjust the delay and observe how the fade speed changes.

#![allow(unused)]
fn main() {
loop {
    for i in 0..=100 {
        Timer::after_millis(8).await;
        let _ = pwm.set_duty_cycle_percent(i);
    }
    
    for i in (0..=100).rev() {
        Timer::after_millis(8).await;
        let _ = pwm.set_duty_cycle_percent(i);
    }

    Timer::after_millis(500).await;
}
}

The full code

#![no_std]
#![no_main]

use embassy_executor::Spawner;
use embassy_rp as hal;
use embassy_rp::block::ImageDef;
use embassy_rp::pwm::{Pwm, SetDutyCycle};
use embassy_time::Timer;

//Panic Handler
use panic_probe as _;
// Defmt Logging
use defmt_rtt as _;

/// Tell the Boot ROM about our application
#[unsafe(link_section = ".start_block")]
#[used]
pub static IMAGE_DEF: ImageDef = hal::block::ImageDef::secure_exe();

#[embassy_executor::main]
async fn main(_spawner: Spawner) {
    let p = embassy_rp::init(Default::default());

    // For Onboard LED
    let mut pwm = Pwm::new_output_b(p.PWM_SLICE4, p.PIN_25, Default::default());

    // For external LED connected on GPIO 16
    // let mut pwm = Pwm::new_output_a(p.PWM_SLICE0, p.PIN_16, Default::default());

    loop {
        for i in 0..=100 {
            Timer::after_millis(8).await;
            let _ = pwm.set_duty_cycle_percent(i);
        }
        for i in (0..=100).rev() {
            Timer::after_millis(8).await;
            let _ = pwm.set_duty_cycle_percent(i);
        }
        Timer::after_millis(500).await;
    }
}

// Program metadata for `picotool info`.
// This isn't needed, but it's recomended to have these minimal entries.
#[unsafe(link_section = ".bi_entries")]
#[used]
pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [
    embassy_rp::binary_info::rp_program_name!(c"led-dimming"),
    embassy_rp::binary_info::rp_program_description!(c"your program description"),
    embassy_rp::binary_info::rp_cargo_version!(),
    embassy_rp::binary_info::rp_program_build_attribute!(),
];

// End of file

Clone the existing project

You can clone the project I created and navigate to the external-led folder:

git clone https://github.com/ImplFerris/pico2-embassy-projects
cd pico2-embassy-projects/led-dimming