esp32c3 运行 Rust(三)
上篇已经实现通过按钮控制 LED,现在让我们使用实现呼吸灯效果。
环境
-
OS: Ubuntu 20.04.4 LTS
-
Rust: rustc 1.62.0-nightly
-
IDE: VsCode
-
ESP32C3: ESP-C3-13-Kit 开发板
GPIO title GPIO4 Green LED
创建项目
使用如下命令创建 ledc-simple 项目,并修改项目配置
cargo generate --git https://github.com/esp-rs/esp-idf-template cargo
创建细节参见 esp32c3 运行 Rust(〇) 中 创建项目 HelloWorld。
让 LED 闪烁起来吧
-
安装相关依赖
在
Cargo.toml中添加相关依赖- embedded-hal 嵌入式系统的硬件抽象层
- esp-idf-hal ESP32[-XX] + ESP-IDF 的
embedded-hal实现 - anyhow
# ... [dependencies] # ... esp-idf-sys = { version = "0.31.1", features = ["binstart"] } embedded-hal = "0.2.7" # 添加这行 esp-idf-hal = "0.36.0" # 添加这行 anyhow = "1.0.57" # 添加这行 # ... -
设置引脚
//... use esp_idf_hal::peripherals::Peripherals; //... fn main() -> anyhow::Result<()> { //... let peripherals = Peripherals::take().unwrap(); //... } -
生成 PWM 信号通道
//... use esp_idf_hal::{ ledc::{ config::TimerConfig, Timer, Channel, } }; //... fn main() -> anyhow::Result<()> { //... // 定时器配置 let config = TimerConfig::default().frequency(25.kHz().into()); // 创建定时器 let timer = Timer::new(peripherals.ledc.timer0, &config)?; // 创建 LED 控制输出通道 let mut channel = Channel::new(peripherals.ledc.channel0, &timer, peripherals.pins.gpio4)?; //... } -
获取最大占空比
let max_duty = channel.get_max_duty(); -
设置新的占空比
for numerator in (0..max_duty).cycle() { println!("Duty {}/5", numerator); channel.set_duty(numerator)?; FreeRtos.delay_us(1000_u16); } -
编译并上传
连接开发板,使用如下命令编译并上传
cargo espflash --release --monitor /dev/ttyUSB0
完整代码
use esp_idf_sys as _; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported
use embedded_hal::blocking::delay::DelayUs;
use esp_idf_hal::{
delay::FreeRtos,
ledc::{config::TimerConfig, Channel, Timer},
peripherals::Peripherals,
prelude::*,
};
use anyhow;
fn main() -> anyhow::Result<()> {
// Temporary. Will disappear once ESP-IDF 4.4 is released, but for now it is necessary to call this function once,
// or else some patches to the runtime implemented by esp-idf-sys might not link properly.
esp_idf_sys::link_patches();
println!("configuring output channel");
let peripherals = Peripherals::take().unwrap();
let config = TimerConfig::default().frequency(25.kHz().into());
let timer = Timer::new(peripherals.ledc.timer0, &config)?;
let mut channel = Channel::new(peripherals.ledc.channel0, &timer, peripherals.pins.gpio4)?;
println!("Starting duty-cycle loop");
let max_duty = channel.get_max_duty();
for numerator in (0..max_duty).cycle() {
println!("Duty {}/5", numerator);
channel.set_duty(numerator)?;
FreeRtos.delay_us(1000_u16);
}
loop {
FreeRtos.delay_us(1000_u16);
}
}
呼吸灯效果
已经实现了 LED 灯由灭变亮的渐变效果,现在实现由亮变灭的效果。完整代码如下
use esp_idf_sys as _; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported
use embedded_hal::blocking::delay::DelayUs;
use esp_idf_hal::{
delay::FreeRtos,
ledc::{config::TimerConfig, Channel, Timer},
peripherals::Peripherals,
prelude::*,
};
use anyhow;
fn main() -> anyhow::Result<()> {
// Temporary. Will disappear once ESP-IDF 4.4 is released, but for now it is necessary to call this function once,
// or else some patches to the runtime implemented by esp-idf-sys might not link properly.
esp_idf_sys::link_patches();
let peripherals = Peripherals::take().unwrap();
let config = TimerConfig::default().frequency(25.kHz().into());
let timer = Timer::new(peripherals.ledc.timer0, &config)?;
let mut channel = Channel::new(peripherals.ledc.channel0, &timer, peripherals.pins.gpio4)?;
let max_duty = channel.get_max_duty();
loop {
for numerator in 0..max_duty {
channel.set_duty(numerator)?;
FreeRtos.delay_us(10000_u16);
}
FreeRtos.delay_us(10000_u16);
for numerator in (0..max_duty).rev() {
channel.set_duty(numerator)?;
FreeRtos.delay_us(10000_u16);
}
FreeRtos.delay_us(10000_u16);
}
}