embassy-rs / embassy

Modern embedded framework, using Rust and async.
https://embassy.dev
Apache License 2.0
5.64k stars 782 forks source link

Create a waker for the SimplePwm to be able to synchronize ADC with PWM #2056

Open smeenka opened 1 year ago

smeenka commented 1 year ago

Here is my use case: The SimplePWM does create a pwm for a motor. At the start of the pwm cycle the motor is enabled. A millisecond after this event I want to measure the current of the motor with ADC.

The moment of measuring is crucial: if the ADC is not synchronized with the PWM, basically I get a random value for the current, as I do not know if the sampling was done during the low time or the high time of the PWM.

So what I need is the possibility to register a waker on the SimplePWM start-of-cycle event, which can wake a user task for starting the adc conversion. I cannot find something like InterruptHandler in timer for embassy-stm32, so I think my request is not yet implemented!

A possible implementation could be that in user code one can await the start-of-cycle event.

xoviat commented 1 year ago

Does the current of the motor change over the duration of the pwm period? If it does, you would need a hardware ticker to sample the current. That's currently not implemented, but I would like for it to be.

So what I need is the possibility to register a waker on the SimplePWM start-of-cycle event, which can wake a user task for starting the adc conversion.

This is one of the rare times that the core will be too slow to get an accurate measurement. You will need to bypass the core if you want any kind of accuracy.

I can help you implement this if you want to discuss further in matrix. I am probably one of the few people around here that cares about power electronics.

smeenka commented 1 year ago

The pwm frequency in my case is 100 hrz, so I think that embassy is fast enough. Realtime accuracy is not what I need here, if the measurement time has a jitter of 2 ms it does not harm the use case. For high frequency pwm (>25 Khz) I think that RTIC is better suited for the case than Embassy. Or even a combination of those two. Yes the current does change, during the off state the current will flow back to the supply over the fly back diodes. No current will go through the measuring resistor then.

For motor control (for example bldc motors) you need a very fast part (for example for measuring the zero crossings). It could be a requirement on the roadmap to integrate the RTIC functionality inside embassy, so that one has a very fast interrupt driven real time part, and a async driven semi real time part.

I will start implementing my use case, (possibility to await the start-of-cycle only for SimplePwm and only for the stm32g0). I will create a pull request when its finished. Can take a few weeks.

xoviat commented 1 year ago

I personally would like to avoid real-time code to the extent possible. RTIC can be avoided with DMA and a hardware ticker, and can produce better results as well. Of course I will not reject an intermediate solution, but that is the direction that I want to go in.

showier-drastic commented 2 months ago

It would be better for you to use hardware triggers for ADC, so that once the timer reaches a certain threshold, ADC conversion automatically starts without any software intervention. If you are driving a 3-phase motor with STM32, you can use the 4-th channel of TIM as ADC trigger. Additionally, you can use injected mode, so that up to 4 channels of data can be directly stored in ADC registers, no DMA is needed. For a reference see ST RM0440 (STM32G4 reference manual) 21.4.18 Conversion on external trigger and trigger polarity (EXTSEL, EXTEN, JEXTSEL, JEXTEN).

This method is not directly supported by embassy HAL though, and you have to directly manipulate registers to do this. It would be nicer if embassy can provide such abstraction.