Skip to content

embassy-stm32 - Unsplit timer types for more control #4863

@usbalbin

Description

@usbalbin

Hi!

We are looking to use embassy-stm32 hal for a couple of projects, all which will use the hardware timers for different things. One of the things is triac control for soft starting an AC-motor. For that, we are thinking "one pulse mode", restart timer on ETR input, set output on compare match, reset on period etc. Perhaps even load the next pulse width from the DMA which is given the ramp profile as an array.

However that does not really map to any of the timer types available in embassy-stm32/src/timer.

From what I can tell most of that is available but not on the same type, I would need some combination of for example

  • one_pulse.rs (trigger input and single shot mode)
  • simple_pwm.rs (output to pin and DMA support)

In my mind "one pulse", "pwm output" and "input capture" does not need to be mutually exclusive. I understand if the majority of users are happy with the different types and the discoverability is better that way. However it would be nice to have something slightly higher than the pac level as exposed in the low level timer type but still having the control to do what I want.

What do you think about moving down a lot of logic from the different types and putting it directly on the low level type so as to make that more useful(and delegate to the inner type in the higher level types so as to keep the same API) and/or perhaps add new timer type (insert too-many-standards-meme here) which can do all the things.

Coming from stm32g4xx-hal, and to some extent stm32h5xx-hal, where there is quite extensive use of builder types for setting up peripherals with lots of options. From what I have seen so far, embassy does not seem to do that quite as often. Is there any particular reason for this or would you think something like this could work?

For example

let mut triac_ctrl = MySwissArmyKnifeTimer::new(p.TIM1)
    //.frequency()
    .prescaler(...)
    .period(...)
    .ch1_out(output_pin, initial_duty)
    //.ch1_out_compl(...)
    .trigger(zero_detect_pin)
    .enable_oneshot_mode()
    .output_compare_mode(OutputCompareMode::PwmMode2)
    .init();

triac_ctrl.waveform_up(dma, MY_SOFT_START_RAMP_PROFILE).await;

Or do you have any other suggestions? :) I suppose some of the the things above could be made into methods on the final type to mutate it after it has been initialized and the things that have to be done before could be put into some Config struct if you prefer?

cc @denenilsson

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions