Skip to content

Commit c188289

Browse files
authored
Add non-blocking asynch smart LED driver (#6)
Adds infrastructure and example for async version of SmartLedsAdapter.
1 parent 0ddc575 commit c188289

File tree

5 files changed

+301
-75
lines changed

5 files changed

+301
-75
lines changed

esp-hal-smartled/CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## Unreleased
99

10+
## 0.15.0
11+
12+
### Added
13+
14+
- New `SmartLedsAdapterAsync` which is an asynchronous, non-blocking version of the driver.
15+
16+
## 0.14.0
17+
18+
## 0.13.1
19+
1020
### Added
1121

1222
### Changed

esp-hal-smartled/Cargo.toml

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "esp-hal-smartled"
3-
version = "0.14.0"
3+
version = "0.15.0"
44
edition = "2021"
55
rust-version = "1.84.0"
66
description = "RMT peripheral adapter for smart LEDs"
@@ -15,7 +15,7 @@ targets = ["riscv32imac-unknown-none-elf"]
1515
defmt = { version = "0.3.10", optional = true }
1616
document-features = "0.2.10"
1717
esp-hal = { version = "1.0.0-beta.0", features = ["unstable"] }
18-
smart-leds-trait = "0.3.0"
18+
smart-leds-trait = "0.3.1"
1919

2020
[dev-dependencies]
2121
cfg-if = "1.0.0"
@@ -24,6 +24,9 @@ esp-backtrace = { version = "0.15.0", features = [
2424
"panic-handler",
2525
"println",
2626
] }
27+
esp-hal-embassy = "0.7"
28+
embassy-executor = "0.7.0"
29+
embassy-time = "0.4.0"
2730
esp-println = "0.13.0"
2831
smart-leds = "0.4.0"
2932

@@ -33,14 +36,14 @@ defmt = ["dep:defmt", "esp-hal/defmt"]
3336

3437
#! ### Chip Support Feature Flags
3538
## Target the ESP32.
36-
esp32 = ["esp-backtrace/esp32", "esp-hal/esp32", "esp-println/esp32"]
39+
esp32 = ["esp-backtrace/esp32", "esp-hal/esp32", "esp-println/esp32", "esp-hal-embassy/esp32"]
3740
## Target the ESP32-C3.
38-
esp32c3 = ["esp-backtrace/esp32c3", "esp-hal/esp32c3", "esp-println/esp32c3"]
41+
esp32c3 = ["esp-backtrace/esp32c3", "esp-hal/esp32c3", "esp-println/esp32c3", "esp-hal-embassy/esp32c3"]
3942
## Target the ESP32-C6.
40-
esp32c6 = ["esp-backtrace/esp32c6", "esp-hal/esp32c6", "esp-println/esp32c6"]
43+
esp32c6 = ["esp-backtrace/esp32c6", "esp-hal/esp32c6", "esp-println/esp32c6", "esp-hal-embassy/esp32c6"]
4144
## Target the ESP32-H2.
42-
esp32h2 = ["esp-backtrace/esp32h2", "esp-hal/esp32h2", "esp-println/esp32h2"]
45+
esp32h2 = ["esp-backtrace/esp32h2", "esp-hal/esp32h2", "esp-println/esp32h2", "esp-hal-embassy/esp32h2"]
4346
## Target the ESP32-S2.
44-
esp32s2 = ["esp-backtrace/esp32s2", "esp-hal/esp32s2", "esp-println/esp32s2"]
47+
esp32s2 = ["esp-backtrace/esp32s2", "esp-hal/esp32s2", "esp-println/esp32s2", "esp-hal-embassy/esp32s2"]
4548
## Target the ESP32-S3.
46-
esp32s3 = ["esp-backtrace/esp32s3", "esp-hal/esp32s3", "esp-println/esp32s3"]
49+
esp32s3 = ["esp-backtrace/esp32s3", "esp-hal/esp32s3", "esp-println/esp32s3", "esp-hal-embassy/esp32s3"]

esp-hal-smartled/examples/hello_rgb.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
use esp_backtrace as _;
2626
use esp_hal::{delay::Delay, main, rmt::Rmt, time::Rate};
27-
use esp_hal_smartled::{smartLedBuffer, SmartLedsAdapter};
27+
use esp_hal_smartled::{smart_led_buffer, SmartLedsAdapter};
2828
use smart_leds::{
2929
brightness, gamma,
3030
hsv::{hsv2rgb, Hsv},
@@ -64,7 +64,7 @@ fn main() -> ! {
6464

6565
// We use one of the RMT channels to instantiate a `SmartLedsAdapter` which can
6666
// be used directly with all `smart_led` implementations
67-
let rmt_buffer = smartLedBuffer!(1);
67+
let rmt_buffer = smart_led_buffer!(1);
6868
let mut led = SmartLedsAdapter::new(rmt.channel0, led_pin, rmt_buffer);
6969

7070
let delay = Delay::new();
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
//! Asynchronous RGB LED Demo
2+
//!
3+
//! This example drives an SK68XX RGB LED, which is connected to a pin on the
4+
//! official DevKits.
5+
//!
6+
//! The demo will leverage the [`smart_leds`](https://crates.io/crates/smart-leds)
7+
//! crate functionality to circle through the HSV hue color space (with
8+
//! saturation and value both at 255). Additionally, we apply a gamma correction
9+
//! and limit the brightness to 10 (out of 255).
10+
//!
11+
//! The following wiring is assumed for ESP32:
12+
//! - LED => GPIO33
13+
//! The following wiring is assumed for ESP32C3:
14+
//! - LED => GPIO8
15+
//! The following wiring is assumed for ESP32C6, ESP32H2:
16+
//! - LED => GPIO8
17+
//! The following wiring is assumed for ESP32S2:
18+
//! - LED => GPIO18
19+
//! The following wiring is assumed for ESP32S3:
20+
//! - LED => GPIO48
21+
22+
#![no_std]
23+
#![no_main]
24+
25+
use esp_backtrace as _;
26+
use esp_hal::{rmt::Rmt, time::Rate, timer::timg::TimerGroup, Config};
27+
use esp_hal_smartled::{buffer_size_async, SmartLedsAdapterAsync};
28+
use smart_leds::{
29+
brightness, gamma,
30+
hsv::{hsv2rgb, Hsv},
31+
SmartLedsWriteAsync,
32+
};
33+
use embassy_executor::Spawner;
34+
use embassy_time::{Duration, Timer};
35+
36+
#[esp_hal_embassy::main]
37+
async fn main(_spawner: Spawner) -> ! {
38+
let peripherals = esp_hal::init(Config::default());
39+
let timg0 = TimerGroup::new(peripherals.TIMG0);
40+
esp_hal_embassy::init(timg0.timer0);
41+
42+
// Each devkit uses a unique GPIO for the RGB LED, so in order to support
43+
// all chips we must unfortunately use `#[cfg]`s:
44+
cfg_if::cfg_if! {
45+
if #[cfg(feature = "esp32")] {
46+
let led_pin = peripherals.GPIO33;
47+
} else if #[cfg(feature = "esp32c3")] {
48+
let led_pin = peripherals.GPIO8;
49+
} else if #[cfg(any(feature = "esp32c6", feature = "esp32h2"))] {
50+
let led_pin = peripherals.GPIO8;
51+
} else if #[cfg(feature = "esp32s2")] {
52+
let led_pin = peripherals.GPIO18;
53+
} else if #[cfg(feature = "esp32s3")] {
54+
let led_pin = peripherals.GPIO48;
55+
}
56+
}
57+
58+
// Configure RMT peripheral globally
59+
cfg_if::cfg_if! {
60+
if #[cfg(feature = "esp32h2")] {
61+
let freq = Rate::from_mhz(32);
62+
} else {
63+
let freq = Rate::from_mhz(80);
64+
}
65+
}
66+
67+
let rmt = Rmt::new(peripherals.RMT, freq).unwrap().into_async();
68+
69+
// We use one of the RMT channels to instantiate a `SmartLedsAdapter` which can
70+
// be used directly with all `smart_led` implementations
71+
let rmt_buffer: [u32; buffer_size_async(1)] = [0; buffer_size_async(1)];
72+
let mut led = SmartLedsAdapterAsync::new(rmt.channel0, led_pin, rmt_buffer);
73+
74+
let mut color = Hsv {
75+
hue: 0,
76+
sat: 255,
77+
val: 255,
78+
};
79+
let mut data;
80+
81+
loop {
82+
for hue in 0..=255 {
83+
color.hue = hue;
84+
// Convert from the HSV color space (where we can easily transition from one
85+
// color to the other) to the RGB color space that we can then send to the LED
86+
data = [hsv2rgb(color)];
87+
// When sending to the LED, we do a gamma correction first (see smart_leds
88+
// documentation for details) and then limit the brightness to 10 out of 255 so
89+
// that the output it's not too bright.
90+
led.write(brightness(gamma(data.iter().cloned()), 20)).await.unwrap();
91+
Timer::after(Duration::from_millis(10)).await;
92+
}
93+
}
94+
}

0 commit comments

Comments
 (0)