esp32c3 运行 Rust(三)

760 阅读2分钟

esp32c3 运行 Rust(三)

上篇已经实现通过按钮控制 LED,现在让我们使用实现呼吸灯效果。

环境

  • OS: Ubuntu 20.04.4 LTS

  • Rust: rustc 1.62.0-nightly

  • IDE: VsCode

  • ESP32C3: ESP-C3-13-Kit 开发板

    esp32c3.png

    GPIOtitle
    GPIO4Green LED

创建项目

使用如下命令创建 ledc-simple 项目,并修改项目配置

cargo generate --git https://github.com/esp-rs/esp-idf-template cargo

创建细节参见 esp32c3 运行 Rust(〇)创建项目 HelloWorld

让 LED 闪烁起来吧

  1. 安装相关依赖

    Cargo.toml 中添加相关依赖

    # ...
    [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" #  添加这行
    # ...
    
  2. 设置引脚

    //...
    use esp_idf_hal::peripherals::Peripherals;
    //...
    
    fn main() -> anyhow::Result<()> {
        //...
        let peripherals = Peripherals::take().unwrap();
        //...
    }
    
  3. 生成 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)?;
        //...
    }
    
  4. 获取最大占空比

    let max_duty = channel.get_max_duty();
    
  5. 设置新的占空比

    for numerator in (0..max_duty).cycle() {
        println!("Duty {}/5", numerator);
        channel.set_duty(numerator)?;
        FreeRtos.delay_us(1000_u16);
    }
    
  6. 编译并上传

    连接开发板,使用如下命令编译并上传

    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);
  }
}

参考

  1. Embedded Rust on Espressif
  2. embedded-hal
  3. esp-idf-hal