ledc: add support for fading leds (#519)

This commit is contained in:
Justin Buchanan 2025-03-13 11:26:23 -07:00 committed by GitHub
parent a38789173d
commit 318bb4e4fe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 103 additions and 2 deletions

View File

@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- `Send` for `AsyncCanDriver`
- `fade_with_time`, `fade_with_step` for `LedcDriver`
### Fixed
- Fix the SDMMC driver for ESP-IDF V5.5+

39
examples/ledc_fade.rs Normal file
View File

@ -0,0 +1,39 @@
use esp_idf_hal::delay::FreeRtos;
use esp_idf_hal::ledc::{config::TimerConfig, LedcDriver, LedcTimerDriver};
use esp_idf_hal::peripherals::Peripherals;
use esp_idf_hal::prelude::*;
use std::time::Duration;
fn main() -> anyhow::Result<()> {
esp_idf_hal::sys::link_patches();
let peripherals = Peripherals::take()?;
let timer_driver = LedcTimerDriver::new(
peripherals.ledc.timer0,
&TimerConfig::default().frequency(25.kHz().into()),
)?;
let mut ledc_driver = LedcDriver::new(
peripherals.ledc.channel0,
timer_driver,
peripherals.pins.gpio7,
)?;
for _ in 0..2 {
// Fade up over 2 seconds
ledc_driver.fade_with_time(
ledc_driver.get_max_duty(),
Duration::from_secs(2).as_millis() as i32,
true,
)?;
// Fade down over 2 seconds
ledc_driver.fade_with_time(0, Duration::from_secs(2).as_millis() as i32, true)?;
}
ledc_driver.set_duty(ledc_driver.get_max_duty() / 10)?;
FreeRtos::delay_ms(10000);
Ok(())
}

View File

@ -3,8 +3,6 @@
//! Interface to the [LED Control (LEDC)
//! peripheral](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-reference/peripherals/ledc.html)
//!
//! This is an initial implementation supporting the generation of PWM signals
//! but no chrome and spoilers like fading.
//!
//! # Examples
//!
@ -323,6 +321,69 @@ impl<'d> LedcDriver<'d> {
pub fn timer(&self) -> ledc_timer_t {
self.timer as _
}
/// Fade the LED to a target duty cycle over a specified time
pub fn fade_with_time(
&mut self,
target_duty: u32,
fade_time_ms: i32,
wait: bool,
) -> Result<(), EspError> {
let max_duty = self.get_max_duty();
if target_duty > max_duty {
return Err(EspError::from_infallible::<ESP_ERR_INVALID_ARG>());
}
let fade_mode = if wait {
ledc_fade_mode_t_LEDC_FADE_WAIT_DONE
} else {
ledc_fade_mode_t_LEDC_FADE_NO_WAIT
};
unsafe {
esp!(ledc_set_fade_with_time(
self.speed_mode,
self.channel(),
target_duty,
fade_time_ms
))?;
esp!(ledc_fade_start(self.speed_mode, self.channel(), fade_mode))?;
}
Ok(())
}
/// Fade the LED to a target duty cycle using steps
pub fn fade_with_step(
&mut self,
target_duty: u32,
step_size: u32,
step_time_ms: u32,
wait: bool,
) -> Result<(), EspError> {
let max_duty = self.get_max_duty();
if target_duty > max_duty {
return Err(EspError::from_infallible::<ESP_ERR_INVALID_ARG>());
}
let fade_mode = if wait {
ledc_fade_mode_t_LEDC_FADE_WAIT_DONE
} else {
ledc_fade_mode_t_LEDC_FADE_NO_WAIT
};
unsafe {
esp!(ledc_set_fade_with_step(
self.speed_mode,
self.channel(),
target_duty,
step_size,
step_time_ms,
))?;
esp!(ledc_fade_start(self.speed_mode, self.channel(), fade_mode))?;
}
Ok(())
}
}
impl Drop for LedcDriver<'_> {