avr-hal
avr-hal copied to clipboard
Accurate PWM
The existing PWM implementation is fixed to 1kHz and uses the Fast PWM mode which isn't phase- nor frequency-correct. This is rather useless for applications like controlling a Servo where an exact frequency and duty-cycle are needed.
So, in addition to the Fast PWM implementation a seconds "correct" PWM implementation should be added which allows specifying the frequency + duty cycle exactly. Ideally, this should be based on the rate and duration primitives from embedded-time.
Open Questions:
- How to select the prescaling? We could devise an algorithm to use the smallest clock-divider which still fits the frequency. This would, however make it entirely unobvious what precision the duty-cycle will have. Would good documentation help here? Or should the prescaler be selected manually instead?
- Should the
Dutytype be a percentage or a duration? - Not all pins will be available with this "correct" PWM mode, because some of the timer peripherals aren't flexible enough for this (e.g.
OCR0Ais either used for PWM onOC0A, or as the timer period). How do we properly model this?
- Looks like prescaler is better option. It's better to be explicite
- Duration? Percentage seems not very precise. Aret there any usecases where percentage is common?
- Are we able to define this in avr-device?
Looks like prescaler is better option. It's better to be explicite
Not sure what you mean? We'll use the prescaler either way, the question is how it is initialized. Either we have an algorithm which takes a frequency and selects a fitting prescaler, or we leave it up to the user to decide manually.
Actually, while thinking about it: Why not both? We could provide two separate constructors for 'automatic' and 'manual' configuration ...
Duration? Percentage seems not very precise.
In terms of precision, the two solutions don't differ too much. It's always a bit up to luck whether the integer values cleanly divide the timer steps. But we could, again, build a solution where all possibilities are accounted for and provide multiple methods for setting the duty-cycle based on exact timer counts, based on duration, or based on percentage.
Aret there any usecases where percentage is common?
Yes, definitely. PWM is a cheap way to create power output that scales linearly and for those usecases you mostly care about a percentage of the maximum power (= 100% duty cycle).
Are we able to define this in avr-device?
No, this belongs into the HAL only.
I do like Pwm from embedded_hal. According to which, you are setting up period with time variable/frequency which is one type, and duty with 0..65535 when duty type is u16. Then you can use custom map function as C++ Arduino lib does.
I can see no issue with using Fast PWM to control servo motors which have it's own controller. IMHO phase/frequency correct modes are needed if you are going to control coils directly.
Biggest problem with servo is that you have to ensure no full cycles when you moving OCR value. Maybe it deserves separate method set_duty_correct that will make required checks and fixes.