mirror of
https://github.com/esp-rs/esp-idf-hal.git
synced 2025-09-27 12:21:02 +00:00

* commit test 1 test commit 2 next device asd * try example, haven't built yet * Add feature flags for legacy RMT examples Remove references to the ds18b20 specific device. Add a feature flag `rmt-legacy` that, when enabled, will build the original rmt modules from v4 of the esp-idf. When disabled, the v5 rmt interface can be used for one wire applications. Implement the Iterator trait for a device search and use the Iterator in the example. * Add more feature guards to examples compile * Add alternative main functions for examples * Use std threading * Add std to thread sleep * use std duration * correct use for legacy rmt component * Remove local bindings and use the esp-idf-sys master * fix a typo * Remove esp-idf component inclusion * Update gitignore * Fix examples * mut-ex out the example compilation * add implementation for temperature readings * Conditional compile * esp4.4 compile * Changes to cargo and config * Remove OWDevice and simplify API * Remove phantomdata that is not required * adjust lifetimes for single search at a time * Keep RMT peripheral and add channel to onewire Moves the RMT driver into a private `driver` module, which will only be compiled in rmt-legacy mode. Also reduce the number of cfg feature flags in examples by wrapping the implementation in a module. * modularise examples * Fix for CI * update example name to make it pop --------- Co-authored-by: Dane Slattery <dane@polarmonitoring.com> Co-authored-by: DaneSlattery <dane_s@umantec.net>
128 lines
4.4 KiB
Rust
128 lines
4.4 KiB
Rust
//! A simple example to change colours of a WS2812/NeoPixel compatible LED.
|
|
//!
|
|
//! This example demonstrates the use of [`FixedLengthSignal`][crate::rmt::FixedLengthSignal] which
|
|
//! lives on the stack and requires a known length before creating it.
|
|
//!
|
|
//! There is a similar implementation in the esp-idf project:
|
|
//! https://github.com/espressif/esp-idf/tree/20847eeb96/examples/peripherals/rmt/led_strip
|
|
//!
|
|
//! Datasheet (PDF) for a WS2812, which explains how the pulses are to be sent:
|
|
//! https://cdn-shop.adafruit.com/datasheets/WS2812.pdf
|
|
|
|
#[cfg(any(feature = "rmt-legacy", esp_idf_version_major = "4"))]
|
|
fn main() -> anyhow::Result<()> {
|
|
example::main()
|
|
}
|
|
|
|
#[cfg(not(any(feature = "rmt-legacy", esp_idf_version_major = "4")))]
|
|
fn main() -> anyhow::Result<()> {
|
|
println!("This example requires feature `rmt-legacy` enabled or using ESP-IDF v4.4.X");
|
|
|
|
loop {
|
|
std::thread::sleep(std::time::Duration::from_millis(1000));
|
|
}
|
|
}
|
|
|
|
#[cfg(any(feature = "rmt-legacy", esp_idf_version_major = "4"))]
|
|
mod example {
|
|
use std::time::Duration;
|
|
|
|
use anyhow::{bail, Result};
|
|
use esp_idf_hal::{
|
|
delay::FreeRtos,
|
|
prelude::Peripherals,
|
|
rmt::{config::TransmitConfig, FixedLengthSignal, PinState, Pulse, TxRmtDriver},
|
|
};
|
|
|
|
pub fn main() -> Result<()> {
|
|
esp_idf_hal::sys::link_patches();
|
|
|
|
let peripherals = Peripherals::take()?;
|
|
// Onboard RGB LED pin
|
|
// ESP32-C3-DevKitC-02 gpio8, ESP32-C3-DevKit-RUST-1 gpio2
|
|
let led = peripherals.pins.gpio2;
|
|
let channel = peripherals.rmt.channel0;
|
|
let config = TransmitConfig::new().clock_divider(1);
|
|
let mut tx = TxRmtDriver::new(channel, led, &config)?;
|
|
|
|
// 3 seconds white at 10% brightness
|
|
neopixel(Rgb::new(25, 25, 25), &mut tx)?;
|
|
FreeRtos::delay_ms(3000);
|
|
|
|
// infinite rainbow loop at 20% brightness
|
|
(0..360).cycle().try_for_each(|hue| {
|
|
FreeRtos::delay_ms(10);
|
|
let rgb = Rgb::from_hsv(hue, 100, 20)?;
|
|
neopixel(rgb, &mut tx)
|
|
})
|
|
}
|
|
|
|
fn neopixel(rgb: Rgb, tx: &mut TxRmtDriver) -> Result<()> {
|
|
let color: u32 = rgb.into();
|
|
let ticks_hz = tx.counter_clock()?;
|
|
let (t0h, t0l, t1h, t1l) = (
|
|
Pulse::new_with_duration(ticks_hz, PinState::High, &Duration::from_nanos(350))?,
|
|
Pulse::new_with_duration(ticks_hz, PinState::Low, &Duration::from_nanos(800))?,
|
|
Pulse::new_with_duration(ticks_hz, PinState::High, &Duration::from_nanos(700))?,
|
|
Pulse::new_with_duration(ticks_hz, PinState::Low, &Duration::from_nanos(600))?,
|
|
);
|
|
let mut signal = FixedLengthSignal::<24>::new();
|
|
for i in (0..24).rev() {
|
|
let p = 2_u32.pow(i);
|
|
let bit: bool = p & color != 0;
|
|
let (high_pulse, low_pulse) = if bit { (t1h, t1l) } else { (t0h, t0l) };
|
|
signal.set(23 - i as usize, &(high_pulse, low_pulse))?;
|
|
}
|
|
tx.start_blocking(&signal)?;
|
|
Ok(())
|
|
}
|
|
|
|
struct Rgb {
|
|
r: u8,
|
|
g: u8,
|
|
b: u8,
|
|
}
|
|
|
|
impl Rgb {
|
|
pub fn new(r: u8, g: u8, b: u8) -> Self {
|
|
Self { r, g, b }
|
|
}
|
|
/// Converts hue, saturation, value to RGB
|
|
pub fn from_hsv(h: u32, s: u32, v: u32) -> Result<Self> {
|
|
if h > 360 || s > 100 || v > 100 {
|
|
bail!("The given HSV values are not in valid range");
|
|
}
|
|
let s = s as f64 / 100.0;
|
|
let v = v as f64 / 100.0;
|
|
let c = s * v;
|
|
let x = c * (1.0 - (((h as f64 / 60.0) % 2.0) - 1.0).abs());
|
|
let m = v - c;
|
|
let (r, g, b) = match h {
|
|
0..=59 => (c, x, 0.0),
|
|
60..=119 => (x, c, 0.0),
|
|
120..=179 => (0.0, c, x),
|
|
180..=239 => (0.0, x, c),
|
|
240..=299 => (x, 0.0, c),
|
|
_ => (c, 0.0, x),
|
|
};
|
|
Ok(Self {
|
|
r: ((r + m) * 255.0) as u8,
|
|
g: ((g + m) * 255.0) as u8,
|
|
b: ((b + m) * 255.0) as u8,
|
|
})
|
|
}
|
|
}
|
|
|
|
impl From<Rgb> for u32 {
|
|
/// Convert RGB to u32 color value
|
|
///
|
|
/// e.g. rgb: (1,2,4)
|
|
/// G R B
|
|
/// 7 0 7 0 7 0
|
|
/// 00000010 00000001 00000100
|
|
fn from(rgb: Rgb) -> Self {
|
|
((rgb.r as u32) << 16) | ((rgb.g as u32) << 8) | rgb.b as u32
|
|
}
|
|
}
|
|
}
|