adafruit / circuitpython

CircuitPython - a Python implementation for teaching coding with microcontrollers
https://circuitpython.org
Other
4.12k stars 1.22k forks source link

Using TCC to generate multi-pin PWM waveforms #7505

Open lloydaviation opened 1 year ago

lloydaviation commented 1 year ago

I asked a question about synchronous PWM on two pins and was redirected here by mikeysklar. It was suggested that this might have general application in other areas.

My immediate application requires synchronized PWM on two pins. Each pin represents half a cycle. Pulses are equally spaced. If the duty cycle is set 50% then each pin would have a square-wave and they would be 180° out of phase. Decreasing the duty cycle preserves the frequency, but the on time of each pin is decreased. The goal would be to support changes in duty cycle without change in frequency, change in frequency without change in duty cycle, or a combination of the two.

My specific application is to drive a push-pull transformer and be able to control the energy delivered to the windings without changing overall frequency.

As a general tool, I can see the use for generating various synchronized timing waveforms.

dhalbert commented 1 year ago

I think this would be possible, but there are many variations on the theme here, and I'm not sure we could come up with a useful general API. The capabilities may also vary per chip family. PIO on the RP2040 may make programming it possible in CircuitPython. Otherwise getting into the register settings would be necessary at the C level, lower than Arduino.

In terms of hardware, if you just added an external inverter to the pin, would that introduce enough undesirable phase shift and mess up your measurements? You could also add two external buffers, one inverting and one not, with the same latency.

lloydaviation commented 1 year ago

I forgot to add, I am using an ATSAMD51 based board (Metro M4 and ItsyBitsy M4), not an RP2040. I can, of course, bit-bang for testing. My only real limitations are, a) keep the frequency high enough to avoid core saturation, and b) no pulse overlap. So, yes, an inverter would work in the case of a 50% duty cycle. It doesn't work in the case of reduced duty cycle because the duty cycle of the pins must decrease at the same rate to keep the power symmetrical.

You are right, if wanting to use the TCC to do all of this, one has to program the TCC at the register level, all the way down on the metal. I do think that something like this would be useful at doing things like making a stepper free-run without tying up the processor. Of course, that then ties up 4xGPIO/PWM but who knows.

And maybe dragging the registers up to user level allowing the programmer to get something like 80% of the TCC functionality, and then programming the registers in the correct order for stability would do a lot.

The last time I wrote drivers at this level it was shortly after the 8086 came out and I was writing in assembler and PL/M. I have forgotten much as I'm only just now getting back into hacking.