I am currently a PhD student at UC Berkeley, following a 6-year journey working at Apple after my undergrad years at Cornell University. I grew up in Dhaka, Bangladesh where my interest in electronics was cultivated, resulting in the creation of this blog.
The underlying RP2040 in the Pi Pico provides an easy-to-use and still powerful and flexible set of PWM peripherals that can enable a wide range of applications. A common requirement in power electronics is the generation of complementary PWM signals. For example, the complementary PWM signals are used in a synchronous buck converter, shown below, to drive the switches S1 and S2.
To prevent shoot-through, a deadtime is employed. Shoot-through is the event when both S1 and S2 are turned on, causing a large current through them due to shorting across the supply voltage. Even if the generated PWM signals are non-overlapping (ie S1 and S2 are never turned on together), delays in the circuitry - through the gate drivers and the power switches themselves - can still result in shoot-through conditions. In a severe case, the shoot-through can cause damage to the switches, blowing them out. In a more moderate case, small overlap times can result in reduced efficiency due to wasted power, but not necessarily damage to the switches. To combat this issue, a deadtime is inserted between the S1 and S2 driving signals. This is an amount of time when both switch control signals are zero allowing for system transients to settle out. How large it should be depends on the circuit parameters and behavior.
In many cases, gate drivers can have built-in features to insert dead-times, such as the LM5106. However, the ability to generate this in the microcontroller itself gives greater flexibility in the selection of gate driver. Further, it allows tuning the time easily in software rather than needing to change hardware components to change deadtimes.
Fortunately, the Pi Pico makes it fairly straightforward to do this!
The corresponding source code is copied below for convenience:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
The RP2040 has 8x PWM slices, each with 2 channels. The complementary PWM waveforms are produced on these 2 channels (A and B) on a given slice. The slice to GPIO mapping is shown below.
Use Micropython to init PWM for the associated GPIO pins (A and B).
Alter RP2040 registers to configure for complementary PWM. This consists of two settings being changed.
Invert channel B relative to channel A.
Use center-aligned (phase-correct) PWM instead of edge-aligned. This ensures that the deadtime is applied to both rising and falling edges of channel A. If edge-aligned PWM was used, the channels would be set high together and the deadtime would only be applied on the falling edge of channel A.
The deadtime is applied to channel B such that channel A's duty cycle corresponds to the desired/set duty cycle.
The duty cycles corresponding to both channels A and B are updated with one register write.
The frequency of the output PWM using center-aligned/phase-correct mode is half that when using the default edge-aligned mode.
An example of phase-correct/center-aligned PWM operation is shown in the figure below, taken from the RP2040 datasheet.
Image source: RP2040 datasheet section 4.5.2.1
To generate the complementary signal on channel B, the duty cycle is computed as the sum of the pulse count corresponding to the desired duty cycle and the desired deadtime ticks. With a 125MHz clock for the RP2040 and default clock/divider settings, this corresponds to 8ns per tick. The inversion of channel B then ensures the production of the desired complementary setting.
Shown below are waveforms for GP16 (PWM 0A) and GP17 (PWM0B) for 100kHz PWM, 25% duty cycle and a 504ns deadtime. The deadtime can be verified by recognizing that it corresponds to one horizontal division, which is set to 500ns.
Complementary PWM signals with 500ns deadtime
Taking a zoomed out view of the waveform highlights the 100kHz frequency and illustrates the complementary PWM generation over multiple cycles, as shown below.
3 cycles of 100kHz PWM complementary signals
A natural use case for this generated complementary PWM signal is to control a synchronous buck converter to achieve high efficiency step down operation. Since Micropython will limit the design of a fast control loop, applications where the high frequency PWM is coupled with a low-bandwidth controller make for a natural home for this use case. A solar MPPT battery charger would make for an ideal usage scenario. Alternately, if the same configuration technique is applied in C, fast control loops can then be designed and implemented.
I have a question: if I have a pwm with variable duty cycle (e.g. in the case of an inverter), how can I proceed to obtain a complementary pwm? Thank you in advance for your reply.
In the example provided, you can keep calling the duty function with the updated duty cycle.
So you would call pwm16.duty(0.25, 63) for 25% duty cycle with 63 ticks deadtime. You can change the first argument with your desired duty cycle: eg pwm16.duty(0.35, 63) for 35% duty cycle.
Mr. Tahmid, thank you for this article. I hadn't been able to figure out how to generate conflicting pwmers using artificial intelligence and other sources. It was very useful
Very interesting article, Vaiya
ReplyDeletenice
ReplyDeleteDear Tahmid, excellent article,
ReplyDeleteI have a question: if I have a pwm with variable duty cycle (e.g. in the case of an inverter), how can I proceed to obtain a complementary pwm? Thank you in advance for your reply.
Greetings, Costantino
In the example provided, you can keep calling the duty function with the updated duty cycle.
DeleteSo you would call pwm16.duty(0.25, 63) for 25% duty cycle with 63 ticks deadtime. You can change the first argument with your desired duty cycle: eg pwm16.duty(0.35, 63) for 35% duty cycle.
is best f0r feed back?
DeleteYes, you can consider that for feedback.
DeleteMr. Tahmid, thank you for this article. I hadn't been able to figure out how to generate conflicting pwmers using artificial intelligence and other sources. It was very useful
ReplyDelete