esp-idf-hal/examples/rmt_neopixel.rs
gak 2b6fe48fa0
WIP: RMT (tx) (#44)
* WIP: Initial tx rmt implementation

* Rename Bulder to Config to line up with other mods

* WIP Potential traits for a "pulses" mod in embedded-hal

* WIP: Initial tx rmt implementation

* Rename Bulder to Config to line up with other mods

* WIP Potential traits for a "pulses" mod in embedded-hal

* Copied example code from ledc fork. Semi-working example.

* Rename level to pulse. dev-dep versions.

* WIP RMT, Examples

* WIP RMT Fix neopixel example

* WIP RMT morse code work

* WIP RMT fixed morse example

* WIP RMT more config, docs.

* WIP RMT fix compilation

* WIP RMT Fix doc comment in example.

* WIP RMT: notes on examples

* WIP RMT Group up same level config items.

* WIP RMT Change half_inserted to an Option

* WIP RMT Don't need to return Result in clear()

* WIP RMT Config refactor. Into for enum.

* Result instead of Option in PulseTick

* Don't use floats for ticks calcs

* WIP Duration for ticks

* Cleanups.

* Moved Duration logic into PulseDuration.

* Remove unused tick_hz field.

* Cleanups.

* WIP playing around with generics

* Refactored out Vec storage out of Writer

* WIP Heap and Stack implementations for data

* WIP about to nuke tricky const code

* Cleanups

* Own PinState. start/start_blocking.

* Wrap duty percent with range safety.

* Use units::Hertz

* Use Hertz in ticks_hz

* Stop transmitting implementation

* Fix morse example

* rmt peripheral for channels (4 for now)

* Small tweaks

* Morse example to demo more functionality

* WIP Fixes and testing functionality

* Cleanups and notes

* Assign devices to number of channels. Cleanups.

* Sprinkled TODO's around for docs/fixes

* Longer messages don't repeat so remove it for now

* Rename data to signal because data is a too generic term

* More docs

* Don't mention receiving in description.

* More docs

* Rename `add` to `push` like Vec. More docs.

* Rename `Writer` to `Transmit` to line up with rmt docs.

* Accidentally had idle_level in carrier config.

* More docs and cleanups. std compatibility.

* Remove chip::HwChannel import because of a * import later.

* Separate duration to ticks calc. Music example.

* Added comment on example.

* clippy: ok_or_else, Default.

* fixes: mut self, allows/features, alloc, &Pulse.

* only need feature alloc for the use warning.

* rename Signal implementations

* Alloc, morse example fix.

* Didn't need that map. iter does the ref.

* Clippy repairs. println! instead of info!
2022-03-02 19:11:30 +02:00

54 lines
2.1 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 embedded_hal::delay::blocking::DelayUs;
use esp_idf_hal::delay::Ets;
use esp_idf_hal::peripherals::Peripherals;
use esp_idf_hal::rmt::config::TransmitConfig;
use esp_idf_hal::rmt::{FixedLengthSignal, PinState, Pulse, Transmit};
fn main() -> anyhow::Result<()> {
esp_idf_sys::link_patches();
let peripherals = Peripherals::take().unwrap();
let led = peripherals.pins.gpio18.into_output()?;
let channel = peripherals.rmt.channel0;
let config = TransmitConfig::new().clock_divider(1);
let mut tx = Transmit::new(led, channel, &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)
}