Here are the items I'm aware of that should be considered:
- As far as I know, these are the key concepts in configuring pulse width modulation: pulse width, period, duty cycle, and perhaps phase. The API pwm_pin_set_values seems too generic, sort of like pwm_pin_do_stuff. It might be better to remove this API in favor of one calling out pulse width.
- Any two of these three need to be configured, to fully describe the PWM waveform: i) pulse width, ii) duty cycle, and iii) period. This presents a problem because if there are individual APIs to set all three, all three may be called and conflict, requiring resolution. I suggest that a better tactic might be pwm_set_pulse_width(int period, int pulse_width) and pwm_set_duty_cycle(int period, int duty_percent). This avoids that problem.
- Setting the "phase" of the PWM to say 20ms from the start of the period is AFAIK the same as waiting 20ms and starting the PWM with phase = 0ms. For common use cases, the phase is not important. You just want the pulses to start as soon as possible. The only purpose of the phase would be to synchronize to some other timed event, or synchronize multiple PWMs. I haven't tried to do this - perhaps it could be done by checking the current time, finding that I have 17ms left until I want it to start, and starting the PWM with a phase of 17ms? Or else there could be an API that gives an absolute time at which the PWM pulse should begin. If achieving this type of synchronization isn't considered, I think the phase API is pointless and could be dropped. If there is such an API, the documentation should be clear about how I guarantee that my pulse begins at the more or less exact time I want it to, e.g. with example code.
My experience with all this is limited but I feel like I know the basic purposes of PWM, so here's a little background that informs the above. There are three basic ways PWMs are used:
- One is to have a very specific pulse width, such as a 180 degree servo where a 1ms pulse means turn to 0 degrees, a 2ms pulse means turn to 180 degrees, and intermediate values map proportionally. The period may not matter much, e.g. 10-50ms would work fine. For this kind of intention, pwm_pin_set_pulse_width(int period, int pulse_width) would be appropriate, and values expressed in milliseconds or microseconds is probably most useful AFAIK.
- The second is to effect a certain duty cycle, so the waveform is "on" a certain percentage of the time, e.g. to dim an LED to 33% brightness it would have a 33% duty cycle. For this application, again the period is not very important, and the smaller the better, probably, to avoid visible flicker. FWIW Arduino calls the API that does this "analogWrite", which is a somewhat helpful, if false, way to think about it.
- Another case would be where the period does matter, such as blinking a smoke alarm LED once per minute, or kicking off a DRAM refresh every 60ms. Here the pulse width / duty cycle might not be important above some minimum, but the period is.
So essentially that breaks down to cases where pulse width, duty cycle, or period is the important thing - which seems rather complete!
Are there other concerns about the PWM API, while we're at it?