stm32f1xx-hal icon indicating copy to clipboard operation
stm32f1xx-hal copied to clipboard

Pwm module,How to understand set_duty

Open adminSxs opened this issue 3 years ago • 12 comments

i want to use pwm drive steering engine,but I don't understand set_duty how to set value, in c design formulas

Freq = CK_PSC/((PSC+1)*(ARR+1)) Duty = CCR/(ARR+1)

freq = 50Hz

Duty should how to set value

adminSxs avatar Aug 11 '22 11:08 adminSxs

1 PWM cycle contains (ARR+1) ticks. You can take this number with .get_max_duty(). It is 100% of cycle. If you set 50Hz, it match 2ms. Duty is part of cycle when pin is high. For example .get_max_duty() gives you 8000. If you pass .set_duty(4000) you take square wave with 50% duty cycle. .set_duty(2000) => 25%

burrbull avatar Aug 11 '22 12:08 burrbull

1 PWM cycle contains (ARR+1) ticks. You can take this number with .get_max_duty(). It is 100% of cycle. If you set 50Hz, it match 2ms. Duty is part of cycle when pin is high. For example .get_max_duty() gives you 8000. If you pass .set_duty(4000) you take square wave with 50% duty cycle. .set_duty(2000) => 25%

thanks very much

adminSxs avatar Aug 11 '22 12:08 adminSxs

 let mut pwm = dp
        .TIM2
        .pwm_hz::<Tim2NoRemap, _, _>(pins, &mut afio.mapr, 50.Hz(), &clocks);
let (mut c1) = pwm.split();
let max = c1.get_max_duty();

why max =53333.

then

c1.set_period(50.Hz()); let max = c1.get_max_duty(); max still is 53333

adminSxs avatar Aug 11 '22 12:08 adminSxs

1 PWM cycle contains (ARR+1) ticks. You can take this number with .get_max_duty(). It is 100% of cycle. If you set 50Hz, it match 2ms. Duty is part of cycle when pin is high. For example .get_max_duty() gives you 8000. If you pass .set_duty(4000) you take square wave with 50% duty cycle. .set_duty(2000) => 25%

 let mut pwm = dp
        .TIM2
        .pwm_hz::<Tim2NoRemap, _, _>(pins, &mut afio.mapr, 1.kHz(), &clocks);
let (mut c1) = pwm.split();
let max = c1.get_max_duty();

the max is 8000

adminSxs avatar Aug 11 '22 12:08 adminSxs

pwm_hz automatically select values of PRE and ARR registers to make ARR as much big as possible. So you can't control them.

Instead you could use .pwm::<Tim2NoRemap, _, SAMPLING_FREQ_YOU_NEED>(pins, &mut afio.mapr, 2.ms(), &clocks).

https://docs.rs/stm32f1xx-hal/0.9.0/stm32f1xx_hal/timer/pwm/trait.PwmExt.html#tymethod.pwm

NOTE. Sampling is time of 1 tick (not 1 cycle). For example 1MHz (1_000_000) or 10kHz (10_000)

burrbull avatar Aug 11 '22 12:08 burrbull

pwm_hz automatically select values of PRE and ARR registers to make ARR as much big as possible. So you can't control them.

Instead you could use .pwm::<Tim2NoRemap, _, SAMPLING_FREQ_YOU_NEED>(pins, &mut afio.mapr, 2.ms(), &clocks).

https://docs.rs/stm32f1xx-hal/0.9.0/stm32f1xx_hal/timer/pwm/trait.PwmExt.html#tymethod.pwm

NOTE. Sampling is time of 1 tick (not 1 cycle). For example 1MHz (1_000_000) or 10kHz (10_000)

    let mut pwm =
        dp.TIM2
            .pwm::<Tim2NoRemap, _, _, 1_000>(pins, &mut afio.mapr,2.millis() , &clocks);

when after execute above code,programe shutdown. what't the wrong about above code.

i use vscode+cotex-debug(openocd) to debug code,no any error

adminSxs avatar Aug 11 '22 14:08 adminSxs

1_000 is ~ lower limit use 1_000_000 for start. In this case max_duty will be 2000

burrbull avatar Aug 11 '22 14:08 burrbull

1_000 is ~ lower limit use 1_000_000 for start. In this case max_duty will be 2000

thanks,programe right

adminSxs avatar Aug 11 '22 14:08 adminSxs

ticks

burrbull avatar Aug 11 '22 14:08 burrbull

ticks

I have still some question: i'm try to drive steering engine steering engine requirement:

  • FREQ: 50Hz
  • Duty: (0.5- route to -90°, 1 - route to -45°,1.5 - route to 0, 2 - route to 45°,2.5-route to 90°)

in C Project Freq = 72M/((PSC+1)*(ARR+1)) Duty=CCR/(ARR+1)

ARR+1=20ms=20k Freq = 50Hz PSC=720000000-1

so CRR =500,Duty=1.5ms CRR=2500,Duty=2.5ms

 let mut pwm =
        dp.TIM2
            .pwm::<Tim2NoRemap, _, _, 50_000>(pins, &mut afio.mapr,2.millis() , &clocks);
 let (mut c1) = pwm.split();

should i how to set this value will generate result to same c code

adminSxs avatar Aug 12 '22 02:08 adminSxs

ARR+1=20ms=20k Freq = 50Hz ~~PSC=720000000-1~~ Your C prject looks broken. You cannot get ARR+1=20k as you cannot get 10 MHz from 72 MHz on stm32f1 (you need other chip like stm32f411 or other oscillator). Correct values are 9 MHz, 9.6 MHz (and maybe 10285714 Hz). This is what you need for 10 MHz on TIM is set sys clock to 40 Mhz and APB1 to 20 MHz: изображение

        let clocks = rcc.cfgr
            .use_hse(8.Mhz())
            .sysclk(40.Mhz())
            .pclk1(20.Mhz()) // bus with clocking for TIM2
            .freeze(&mut flash.acr);
  1. .pwm::<Tim2NoRemap, _, _, 10_000_000> This will set PSC+1=20_000_000/10_000_000=2; ARR+1 = 20000 2a. .pwm::<Tim2NoRemap, _, _, 20_000_000> ARR+1 = 40000` - maximum round number you can get

PS. Alternative is:

        let clocks = rcc.cfgr
            .use_hse(8.Mhz())
            .sysclk(72.Mhz())
            .pclk1(36.Mhz()) // bus with clocking for TIM2
            .freeze(&mut flash.acr);
  1. .pwm::<Tim2NoRemap, _, _, 9_000_000>. Then ARR+1 will be 18000 2a. .pwm::<Tim2NoRemap, _, _, 18_000_000>. Then ARR+1 will be 36000

burrbull avatar Aug 12 '22 04:08 burrbull

ARR+1=20ms=20k Freq = 50Hz ~PSC=720000000-1~ Your C prject looks broken. You cannot get ARR+1=20k as you cannot get 10 MHz from 72 MHz on stm32f1 (you need other chip like stm32f411 or other oscillator). Correct values are 9 MHz, 9.6 MHz (and maybe 10285714 Hz). This is what you need for 10 MHz on TIM is set sys clock to 40 Mhz and APB1 to 20 MHz: изображение

        let clocks = rcc.cfgr
            .use_hse(8.Mhz())
            .sysclk(40.Mhz())
            .pclk1(20.Mhz()) // bus with clocking for TIM2
            .freeze(&mut flash.acr);
  1. .pwm::<Tim2NoRemap, _, _, 10_000_000> This will set PSC+1=20_000_000/10_000_000=2

thanks, i understand

adminSxs avatar Aug 12 '22 05:08 adminSxs