mirror of
https://github.com/ImplFerris/esp32-book.git
synced 2025-09-24 14:31:13 +00:00
servo chapter migrated to esp-hal 1.0.0-beta
This commit is contained in:
parent
b5de2cd550
commit
429c05b4d6
@ -10,7 +10,7 @@ To create the project, use the `esp-generate` command. Run the following:
|
||||
esp-generate --chip esp32 buzzer-song
|
||||
```
|
||||
|
||||
This will open a screen asking you to select options. In the latest esp-hal, ledc requires us to enable the unstable features.
|
||||
This will open a screen asking you to select options. In the latest esp-hal, ledc requires us to explicitly enable the unstable features.
|
||||
|
||||
- So you select the option "Enable unstable HAL features."
|
||||
|
||||
|
@ -12,7 +12,7 @@ To create the project, use the `esp-generate` command. Run the following:
|
||||
esp-generate --chip esp32 led-fader
|
||||
```
|
||||
|
||||
This will open a screen asking you to select options. In the latest esp-hal, ledc requires us to enable the unstable features.
|
||||
This will open a screen asking you to select options. In the latest esp-hal, ledc requires us to explicitly enable the unstable features.
|
||||
|
||||
- So you select the option "Enable unstable HAL features."
|
||||
|
||||
|
@ -7,6 +7,12 @@ To create the project, use the `esp-generate` command. Run the following:
|
||||
```sh
|
||||
esp-generate --chip esp32 servo-motor
|
||||
```
|
||||
This will open a screen asking you to select options. In the latest esp-hal, ledc requires us to explicitly enable the unstable features.
|
||||
|
||||
- So you select the option "Enable unstable HAL features."
|
||||
|
||||
Then save it by pressing "s" in the keyboard.
|
||||
|
||||
|
||||
## Update dependencies
|
||||
Add the following crate to the Cargo.toml file
|
||||
@ -25,26 +31,25 @@ Let's initialize the timer with frequency of 50Hz and 12 bit resolution and conf
|
||||
|
||||
```rust
|
||||
let mut servo = peripherals.GPIO33;
|
||||
|
||||
let ledc = Ledc::new(peripherals.LEDC);
|
||||
|
||||
let mut hstimer0 = ledc.timer::<HighSpeed>(timer::Number::Timer0);
|
||||
hstimer0
|
||||
.configure(timer::config::Config {
|
||||
duty: timer::config::Duty::Duty12Bit,
|
||||
duty: timer::config::Duty::Duty5Bit,
|
||||
clock_source: timer::HSClockSource::APBClk,
|
||||
frequency: 50.Hz(),
|
||||
frequency: Rate::from_khz(24),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let mut channel0 = ledc.channel(channel::Number::Channel0, &mut servo);
|
||||
channel0
|
||||
.configure(channel::config::Config {
|
||||
timer: &hstimer0,
|
||||
duty_pct: 12, // not important, we will change it in loop
|
||||
pin_config: channel::config::PinConfig::PushPull,
|
||||
})
|
||||
.unwrap();
|
||||
.configure(channel::config::Config {
|
||||
timer: &hstimer0,
|
||||
duty_pct: 10,
|
||||
pin_config: channel::config::PinConfig::PushPull,
|
||||
})
|
||||
.unwrap();
|
||||
```
|
||||
|
||||
## Helper function
|
||||
@ -74,21 +79,21 @@ We have already explained the code in the last chapter.
|
||||
In the main loop, we first rotate from 0 degrees to 180 degrees. We add a 10ms gap to reach its position, which is enough since we are moving in smaller steps. Then, we use the rev() function to reverse the range, so it goes from 180 back to 0.
|
||||
|
||||
```rust
|
||||
loop {
|
||||
for deg in 0..=180 {
|
||||
let duty = duty_from_angle(deg, min_duty, duty_gap);
|
||||
channel0.set_duty_cycle(duty).unwrap();
|
||||
delay.delay_millis(10);
|
||||
}
|
||||
delay.delay_millis(500);
|
||||
|
||||
for deg in (0..=180).rev() {
|
||||
let duty = duty_from_angle(deg, min_duty, duty_gap);
|
||||
channel0.set_duty_cycle(duty).unwrap();
|
||||
delay.delay_millis(10);
|
||||
}
|
||||
delay.delay_millis(500);
|
||||
loop {
|
||||
for deg in 0..=180 {
|
||||
let duty = duty_from_angle(deg, min_duty, duty_gap);
|
||||
channel0.set_duty_cycle(duty).unwrap();
|
||||
delay.delay_millis(10);
|
||||
}
|
||||
delay.delay_millis(500);
|
||||
|
||||
for deg in (0..=180).rev() {
|
||||
let duty = duty_from_angle(deg, min_duty, duty_gap);
|
||||
channel0.set_duty_cycle(duty).unwrap();
|
||||
delay.delay_millis(10);
|
||||
}
|
||||
delay.delay_millis(500);
|
||||
}
|
||||
```
|
||||
|
||||
## The full code
|
||||
@ -97,45 +102,48 @@ In the main loop, we first rotate from 0 degrees to 180 degrees. We add a 10ms g
|
||||
#![no_main]
|
||||
|
||||
use embedded_hal::pwm::SetDutyCycle;
|
||||
use esp_backtrace as _;
|
||||
use esp_hal::{
|
||||
delay::Delay,
|
||||
ledc::{
|
||||
channel::{self, ChannelIFace},
|
||||
timer::{self, TimerIFace},
|
||||
HighSpeed, Ledc,
|
||||
},
|
||||
prelude::*,
|
||||
};
|
||||
use esp_hal::clock::CpuClock;
|
||||
use esp_hal::delay::Delay;
|
||||
use esp_hal::ledc::channel::ChannelIFace;
|
||||
use esp_hal::ledc::timer::TimerIFace;
|
||||
use esp_hal::ledc::{channel, timer, HighSpeed, Ledc};
|
||||
use esp_hal::main;
|
||||
use esp_hal::time::Rate;
|
||||
use esp_println as _;
|
||||
|
||||
#[entry]
|
||||
#[panic_handler]
|
||||
fn panic(_: &core::panic::PanicInfo) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[main]
|
||||
fn main() -> ! {
|
||||
let peripherals = esp_hal::init({
|
||||
let mut config = esp_hal::Config::default();
|
||||
config.cpu_clock = CpuClock::max();
|
||||
config
|
||||
});
|
||||
// generator version: 0.3.1
|
||||
|
||||
let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
|
||||
let peripherals = esp_hal::init(config);
|
||||
|
||||
let mut servo = peripherals.GPIO33;
|
||||
|
||||
let ledc = Ledc::new(peripherals.LEDC);
|
||||
|
||||
let mut hstimer0 = ledc.timer::<HighSpeed>(timer::Number::Timer0);
|
||||
hstimer0
|
||||
.configure(timer::config::Config {
|
||||
duty: timer::config::Duty::Duty12Bit,
|
||||
duty: timer::config::Duty::Duty5Bit,
|
||||
clock_source: timer::HSClockSource::APBClk,
|
||||
frequency: 50.Hz(),
|
||||
frequency: Rate::from_khz(24),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let mut channel0 = ledc.channel(channel::Number::Channel0, &mut servo);
|
||||
channel0
|
||||
.configure(channel::config::Config {
|
||||
timer: &hstimer0,
|
||||
duty_pct: 12,
|
||||
duty_pct: 10,
|
||||
pin_config: channel::config::PinConfig::PushPull,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let delay = Delay::new();
|
||||
|
||||
let max_duty_cycle = channel0.max_duty_cycle() as u32;
|
||||
@ -170,7 +178,6 @@ fn duty_from_angle(deg: u32, min_duty: u32, duty_gap: u32) -> u16 {
|
||||
let duty = min_duty + ((deg * duty_gap) / 180);
|
||||
duty as u16
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
@ -11,13 +11,17 @@ To create the project, use the `esp-generate` command. Run the following:
|
||||
esp-generate --chip esp32 servo-mcpwm
|
||||
```
|
||||
|
||||
This will open a screen asking you to select options. For now, we dont need to select any options. Just save it by pressing "s" in the keyboard.
|
||||
This will open a screen asking you to select options. In the latest esp-hal, mcpwm requires us to explicitly enable the unstable features.
|
||||
|
||||
- So you select the option "Enable unstable HAL features."
|
||||
|
||||
Then save it by pressing "s" in the keyboard.
|
||||
|
||||
### Clock Config
|
||||
Let's create an instance of the peripheral clock. We have chosen 1 MHz as the base clock frequency for the PWM. The function will internally calculate the prescaler and divide the input clock, which is 160 MHz.
|
||||
|
||||
```rust
|
||||
let clock_cfg = PeripheralClockConfig::with_frequency(1.MHz()).unwrap();
|
||||
let clock_cfg = PeripheralClockConfig::with_frequency(Rate::from_mhz(32)).unwrap();
|
||||
```
|
||||
|
||||
For the servo, we need to achieve a final PWM frequency of 50 Hz. So, we need to keep the base clock frequency as low as possible. We can go down to 625 kHz with the maximum prescaler value of 255, but we keep it at 1 MHz to make the calculations easier.
|
||||
@ -32,8 +36,8 @@ let mut mcpwm = McPwm::new(peripherals.MCPWM0, clock_cfg);
|
||||
mcpwm.operator0.set_timer(&mcpwm.timer0);
|
||||
// connect operator0 to pin
|
||||
let mut pwm_pin = mcpwm
|
||||
.operator0
|
||||
.with_pin_a(peripherals.GPIO33, PwmPinConfig::UP_ACTIVE_HIGH);
|
||||
.operator0
|
||||
.with_pin_a(peripherals.GPIO33, PwmPinConfig::UP_ACTIVE_HIGH);
|
||||
```
|
||||
|
||||
### Configure the Timer
|
||||
@ -42,9 +46,8 @@ To achieve a 50 Hz PWM signal for the servo with a 1 MHz clock, the timer needs
|
||||
|
||||
```rust
|
||||
let timer_clock_cfg = clock_cfg
|
||||
.timer_clock_with_frequency(19_999, PwmWorkingMode::Increase, 50.Hz())
|
||||
.timer_clock_with_frequency(19_999, PwmWorkingMode::Increase, Rate::from_hz(50))
|
||||
.unwrap();
|
||||
|
||||
mcpwm.timer0.start(timer_clock_cfg);
|
||||
```
|
||||
|
||||
@ -60,18 +63,18 @@ After each adjustment, we give enough delay to allow the servo to reach the spec
|
||||
|
||||
```rust
|
||||
loop {
|
||||
// 0 degree (2.5% of 20_000 => 500)
|
||||
pwm_pin.set_timestamp(500);
|
||||
delay.delay(1500.millis());
|
||||
// 0 degree (2.5% of 20_000 => 500)
|
||||
pwm_pin.set_timestamp(500);
|
||||
delay.delay_millis(1500);
|
||||
|
||||
// 90 degree (7.5% of 20_000 => 1500)
|
||||
pwm_pin.set_timestamp(1500);
|
||||
delay.delay(1500.millis());
|
||||
// 90 degree (7.5% of 20_000 => 1500)
|
||||
pwm_pin.set_timestamp(1500);
|
||||
delay.delay_millis(1500);
|
||||
|
||||
// 180 degree (12.5% of 20_000 => 2500)
|
||||
pwm_pin.set_timestamp(2500);
|
||||
delay.delay(1500.millis());
|
||||
}
|
||||
// 180 degree (12.5% of 20_000 => 2500)
|
||||
pwm_pin.set_timestamp(2500);
|
||||
delay.delay_millis(1500);
|
||||
}
|
||||
```
|
||||
|
||||
## The full code
|
||||
@ -79,25 +82,30 @@ loop {
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp_backtrace as _;
|
||||
use esp_hal::clock::CpuClock;
|
||||
use esp_hal::delay::Delay;
|
||||
use esp_hal::main;
|
||||
use esp_hal::mcpwm::operator::PwmPinConfig;
|
||||
use esp_hal::mcpwm::timer::PwmWorkingMode;
|
||||
use esp_hal::mcpwm::{McPwm, PeripheralClockConfig};
|
||||
use esp_hal::prelude::*;
|
||||
use esp_hal::time::Rate;
|
||||
use esp_println as _;
|
||||
|
||||
#[entry]
|
||||
#[panic_handler]
|
||||
fn panic(_: &core::panic::PanicInfo) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[main]
|
||||
fn main() -> ! {
|
||||
let peripherals = esp_hal::init({
|
||||
let mut config = esp_hal::Config::default();
|
||||
config.cpu_clock = CpuClock::max();
|
||||
config
|
||||
});
|
||||
// generator version: 0.3.1
|
||||
|
||||
esp_println::logger::init_logger_from_env();
|
||||
let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
|
||||
let peripherals = esp_hal::init(config);
|
||||
|
||||
let delay = Delay::new();
|
||||
let clock_cfg = PeripheralClockConfig::with_frequency(1.MHz()).unwrap();
|
||||
|
||||
let clock_cfg = PeripheralClockConfig::with_frequency(Rate::from_mhz(32)).unwrap();
|
||||
let mut mcpwm = McPwm::new(peripherals.MCPWM0, clock_cfg);
|
||||
|
||||
// connect operator0 to timer0
|
||||
@ -110,22 +118,22 @@ fn main() -> ! {
|
||||
// start timer with timestamp values in the range of 0..=19999 and a frequency
|
||||
// of 50 Hz
|
||||
let timer_clock_cfg = clock_cfg
|
||||
.timer_clock_with_frequency(19_999, PwmWorkingMode::Increase, 50.Hz())
|
||||
.timer_clock_with_frequency(19_999, PwmWorkingMode::Increase, Rate::from_hz(50))
|
||||
.unwrap();
|
||||
mcpwm.timer0.start(timer_clock_cfg);
|
||||
|
||||
loop {
|
||||
// 0 degree (2.5% of 20_000 => 500)
|
||||
pwm_pin.set_timestamp(500);
|
||||
delay.delay(1500.millis());
|
||||
delay.delay_millis(1500);
|
||||
|
||||
// 90 degree (7.5% of 20_000 => 1500)
|
||||
pwm_pin.set_timestamp(1500);
|
||||
delay.delay(1500.millis());
|
||||
delay.delay_millis(1500);
|
||||
|
||||
// 180 degree (12.5% of 20_000 => 2500)
|
||||
pwm_pin.set_timestamp(2500);
|
||||
delay.delay(1500.millis());
|
||||
delay.delay_millis(1500);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -13,7 +13,7 @@ To create the project, use the `esp-generate` command. Run the following:
|
||||
esp-generate --chip esp32 ultrasonic
|
||||
```
|
||||
|
||||
This will open a screen asking you to select options. In the latest esp-hal, ledc requires us to enable the unstable features.
|
||||
This will open a screen asking you to select options. In the latest esp-hal, ledc requires us to explicitly enable the unstable features.
|
||||
|
||||
- So you select the option "Enable unstable HAL features."
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user