esp-idf-hal/examples/rmt_neopixel.rs
2022-10-07 20:53:26 +03:00

54 lines
2.0 KiB
Rust

//! A simple example to change colours of a WS2812/NeoPixel compatible LED.
//!
//! It is set to pin 18 which some dev boards have connected to a 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
use core::time::Duration;
use esp_idf_hal::delay::Ets;
use esp_idf_hal::peripherals::Peripherals;
use esp_idf_hal::rmt::config::TransmitConfig;
use esp_idf_hal::rmt::*;
fn main() -> anyhow::Result<()> {
esp_idf_sys::link_patches();
let peripherals = Peripherals::take().unwrap();
let led = peripherals.pins.gpio18;
let channel = peripherals.rmt.channel0;
let config = TransmitConfig::new().clock_divider(1);
let mut tx = RmtDriver::new(channel, led, &config)?;
let rgbs = [0xff0000, 0xffff00, 0x00ffff, 0x00ff00, 0xa000ff];
loop {
for rgb in rgbs {
let ticks_hz = tx.counter_clock()?;
let t0h = Pulse::new_with_duration(ticks_hz, PinState::High, &ns(350))?;
let t0l = Pulse::new_with_duration(ticks_hz, PinState::Low, &ns(800))?;
let t1h = Pulse::new_with_duration(ticks_hz, PinState::High, &ns(700))?;
let t1l = Pulse::new_with_duration(ticks_hz, PinState::Low, &ns(600))?;
let mut signal = FixedLengthSignal::<24>::new();
for i in 0..24 {
let bit = 2_u32.pow(i) & rgb != 0;
let (high_pulse, low_pulse) = if bit { (t1h, t1l) } else { (t0h, t0l) };
signal.set(i as usize, &(high_pulse, low_pulse))?;
}
tx.start_blocking(&signal)?;
Ets::delay_ms(1000);
}
}
}
fn ns(nanos: u64) -> Duration {
Duration::from_nanos(nanos)
}