|
| 1 | +# PWM |
| 2 | + |
| 3 | +In this chapter, we will learn how to digitally control the brightness of the LED using [Pulse-width modulation][1]. |
| 4 | +We will continue using the same `hello_world` project from the previous workshops. |
| 5 | + |
| 6 | +`esp-hal` crate provides a PWM driver in [`mcpwm`][2] module. Let's start by importing the necessary modules and types: |
| 7 | + |
| 8 | +```rust |
| 9 | +use esp_hal::mcpwm::operator::PwmPinConfig; |
| 10 | +use esp_hal::mcpwm::timer::PwmWorkingMode; |
| 11 | +use esp_hal::mcpwm::{McPwm, PeripheralClockConfig}; |
| 12 | +use esp_hal::time::Rate; |
| 13 | +``` |
| 14 | + |
| 15 | +Next, let set up the PWM peripheral: |
| 16 | + |
| 17 | +```rust |
| 18 | +let clock_cfg = PeripheralClockConfig::with_frequency(Rate::from_mhz(40)).unwrap(); |
| 19 | +let mut mcpwm = McPwm::new(peripherals.MCPWM0, clock_cfg); |
| 20 | +let timer_clock_cfg = clock_cfg |
| 21 | + .timer_clock_with_frequency(255, PwmWorkingMode::Increase, Rate::from_khz(20)) |
| 22 | + .expect("could not determine parameters for the requested frequency"); |
| 23 | + |
| 24 | +mcpwm.operator0.set_timer(&mcpwm.timer0); |
| 25 | +mcpwm.timer0.start(timer_clock_cfg); |
| 26 | +``` |
| 27 | + |
| 28 | +> 💡 Note the use of `expect`. `expect` performs the same function as `unwrap`, but allows us to write a helpful |
| 29 | +> error message. In general, use of `unwrap` is discouraged outside of "example" code. Ideally, the errors should be |
| 30 | +> handled gracefully or at least, provide an explanation of what has happened. |
| 31 | +
|
| 32 | +We'll change the LED pin to GPIO16, so we can have active-high configuration: |
| 33 | + |
| 34 | +```rust |
| 35 | +let led = Output::new( |
| 36 | + peripherals.GPIO16, |
| 37 | + esp_hal::gpio::Level::Low, |
| 38 | + OutputConfig::default(), |
| 39 | +); |
| 40 | +``` |
| 41 | + |
| 42 | +Then, we will transfer GPIO to the PWM instance: |
| 43 | + |
| 44 | +```rust |
| 45 | +let mut led = mcpwm.operator0.with_pin_a(led, PwmPinConfig::UP_ACTIVE_HIGH); |
| 46 | +``` |
| 47 | + |
| 48 | +> 💡 Note how we're re-using the name `led`. This is called rebinding and allows us to write cleaner code. |
| 49 | +
|
| 50 | +Finally, let's modify our application to cycle through different brightness levels in a loop: |
| 51 | + |
| 52 | +```rust |
| 53 | +let mut sequence = [32, 128, 255].iter().cycle(); |
| 54 | +loop { |
| 55 | + led.set_timestamp(*sequence.next().unwrap()); |
| 56 | + delay.delay_millis(1000); |
| 57 | +} |
| 58 | +``` |
| 59 | + |
| 60 | +[1]: https://en.wikipedia.org/wiki/Pulse-width_modulation |
| 61 | +[2]: https://docs.espressif.com/projects/rust/esp-hal/1.0.0-rc.0/esp32c6/esp_hal/mcpwm/index.html |
0 commit comments