adafruit / seesaw

I2C friend to expand capabilities of other chips.
Other
76 stars 34 forks source link

Support for high-frequency PWM output (8-bit mode) for SAMD09 #59

Open evtimDev opened 1 year ago

evtimDev commented 1 year ago

Current Status: The current implementation of PWM is 16-bit, which for samd09 (48Mhz core clock) gives us the following range of frequencies: 732Hz, 366Hz, 183Hz, 91Hz, 45Hz, 11Hz, 2.8Hz (with timer prescalers 1, 2, 4, 8, 16, 64, 256)

Higher Frequency Use Cases: There are use-cases where one needs higher frequencies, for example driving a fan with variable voltage via PWM, where higher frequencies help deliver more of a continuous DC voltage level via RC net or similar schematic. For those use-cases a tradeoff where the possible PWM levels have 8-bit resolution vs the currently implemented 16-bit resolution would be acceptable.

Proposed Solution: Perhaps we could add an option to configure for 8-bit PWM mode in addition to the current 16-bit mode. This could be done via CONFIG flag at compile-time that defaults to 16-bit. A change like that would allow for the following frequencies: 187.5Khz, 93.7Khz, 46.8Khz, 23.4Khz, 11.7Khz, 2.9Khz, 732Hz, 183Hz.

One wrinkle of this is that setting frequencies above 65,536 will not be possible via the current SEESAW_TIMER_FREQ message, as the frequency is communicated through 2 data bytes (16bit). A possible fix that would be backwards-compatible would be to introduce an additional message SEESAW_TIMER_FREQ24/32 that will send the frequency request as either 24-bit or 32-bit. On the Adafruit_Seesaw side, we could expand freq parameter of ::setPWMFreq() method to uint32_t and update the implementation to send two messages - first SEESAW_TIMER_FREQ, then SEESAW_TIMER_FREQ24/32 - this will keep the library backwards-compatible with existing firmwares and also support newer firmwares.

Next Steps: I'd welcome feedback on this proposal! If there is interest, I could work on trying these changes.

evtimDev commented 1 year ago

If we are to introduce additional SEESAW_TIMER_FREQ24/32 event, we'd need to also update Adafruit_seesawPeripheral https://github.com/adafruit/Adafruit_seesawPeripheral/blob/4de86ca93998f1ff1beb59aedccd10c6886f1983/Adafruit_seesawPeripheral_receive.h#L179

suurkivi commented 4 months ago

@evtimDev Do you have sample code for this proposed solution? I noticed you forked this repo.

I would be interested in trying it out.

evtimDev commented 4 months ago

Hey @suurkivi, sure! I just pushed the code to https://github.com/evtimDev/seesaw/tree/high-frequency-pwm Just set #define CONFIG_TIMER_PWM_RESOLUTION 8 in your board_config.h to enable.

You may also need my other proposed change here in order for the code to fit the 16Kb limit https://github.com/adafruit/seesaw/compare/master...evtimDev:seesaw:codesize-optimize

suurkivi commented 4 months ago

@evtimDev Thanks! Tried out both of your changes above and it worked!

(after spending a LOT of time building and fiddling with JLink)

For my use case I only need speeds around 20kHz, so this is useful to me even without the api changes you proposed.