-
Notifications
You must be signed in to change notification settings - Fork 210
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PWM implementation #125
PWM implementation #125
Conversation
697303e
to
7213273
Compare
Ok, this got a bit out of hand. There are some differences between the available timers, because of that different macros were necessary. The way it's now it should work with all timers, but it looks a bit ugly and maybe there is a better way to do it. I would like some feedback and I would like to know if there's a better approach to this. PS: For some reason TIM5 interface on stm32f410 is different of any other timer in any supported chip, maybe there's a problem in the svd. For now I had to add one more macro to take care of this case. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking forward to this feature!
@danclive This seems to be working ok already, but I didn't have the opportunity to check everything on the oscilloscope, I tried on the stm32f401. If you can do some tests that would be helpful. |
I've tested this on an stm32f415 using most of the channels from TIM1,2,3,4,8 and everything seems to be working great. |
Thanks @cjblocker , have you tested if the frequency/period is correct ? |
@thalesfragoso Could you rebase this? |
Sure, I just want to polish some stuff and then I will do the rebase. I will see if I can find the time in the next few days. |
So I looked at the frequency on the scope. It's accurate for low-frequencies (500Hz read at about 502Hz, 20khz read about 20.01khz). But for higher frequencies, say 1 MHz, where my returned max duty is only 16, I get about 950khz. Putting a slightly higher frequency so that my max duty cycle is 15, then I actually get 1.001 Mhz on the scope, which is closer to what I wanted. So maybe there is an off-by-one error, and it doesn't affect the lower frequencies/larger counts as much? I don't think this API is meant to guarantee any arbitrary frequency anyway though, as integer division and integer counters can only do so much. |
@cjbloqker did you |
Oh good call, I was not. That will probably explain my errors. I can rerun my tests later. |
That was the problem. Frequencies look perfect now. |
I guess this is ready for review. I'm not quite delighted by this implementation but its quirks seemed necessary to be able to support all these different timers in all these different parts. I'm all open to ideas to improve this. |
@thalesfragoso thanks for the pwm driver! It works on my Nucleo-F446RE board and output is as expected on the scope. I haven't tested many timers, frequencies, and duty cycles though. A couple of questions:
let tim3_channels = pwm::tim3(dp.TIM3, (pa6, pa7, pb0, pb1,), clocks, 50.hz()); // 4 channels, OK
let tim3_channels = pwm::tim3(dp.TIM3, (pa6, pa7,), clocks, 50.hz()); // 2 channels, OK
let tim3_channels = pwm::tim3(dp.TIM3, (pa6,), clocks, 50.hz()); // 1 channel, fails Error is: I'm a Rust learner so I can't discern why your
|
Hey @jkboyce , thanks for testing.
let tim3_channel = pwm::tim3(dp.TIM3, pa6, clocks, 50.hz());
let tim1_channels = pwm::tim1(dp.TIM1, ((pa8, pe9), pa9), 50.hz()); |
Ok @jkboyce , now you should be able to do something like this: let channels = (
(pa6, pb4),
pa7,
);
let tim3_channels = pwm::tim3(dp.TIM3, channels, clocks, 50.hz()); Assuming all the pins are in the right configuration. Could you test this on the hardware for me ? Thanks. |
Hi @thalesfragoso , thanks for the tips. Nice work! Confirming that your solution works for me for 1 channel. Also you are correct, with your previous version I was able to add more pins to the output by calling tim() with one of the channel pins, then putting the other pin into the correct AF. I think this is a perfectly good solution. Your update works as well, specifically I tried this snippet and verified it on the scope: let tim3_channels = pwm::tim3(
dp.TIM3,
((pa6, pb4), pa7, pb0, pb1), // changing pb4 to pb5 gives a compile error
clocks,
50.hz(),
); I see that the pins themselves are unused in the call to |
Hmm, I don't quite understand, do you mean this ? let tim3_channel = pwm::tim3(
dp.TIM3,
(pa6, pb4),
clocks,
50.hz(),
); I think this should just work and give you a pwm channel (not a tuple of channels). |
@thalesfragoso Looks good to me. Mind fixing the merge conflict? |
@therealprof Done. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent, thanks a lot!
I still have to test this on hardware and add some documentation and examples. I will try to test this on the weekend but it would be nice to get some feedback already w.r.t the implementation.
#124 should be merged first.
Closes #67.
PS: Inspired by the implementation in the F1 HAL.