Today, mastering the programming of PWM modules in microcontrollers is important not only for power electronics professionals, who use these modules to control energy flow in converters, but also for anyone who wants to generate an analog signal for any application.
Of course you can use some available libraries, but these are usually limited to simple applications and don't allow you to explore the capabilities of currently available PWM modules.
Many high-performance microcontrollers, such as the iMXRT1062 used in the Teensy 4.1, lack D/A converters. Others that do have an embedded D/A converter have a small number of channels and low resolution. Using external D/A converters with an I2C interface can be an alternative, but only for low sampling rates, as the transmission speed becomes a bottleneck for the system. See an example on Fast Function to Write Samples in the MCP4725. Therefore, using a PWM module as an analog output can be an interesting alternative.
It is important to emphasize that using the PWM module as a D/A converter implies the use of external (analog) low-pass filters, which result in phase delays and distort the signal as the modulating signal approaches the filter's cutoff frequency.
The purpose of this project is to present some operational details to clarify how pulse width modulation operates within the FlexPWM module. A code is presented that operates a timer count in small values ( Code 1), allowing us to monitor the entire PWM carrier cycle. Finally, another code with sinusoidal pulse width modulation (SPWM) is presented ( Code 2 ), which can serve as a basis for other applications by the reader.
This presentation does not intend to be exhaustive, since the FlexPWM module has several configuration features, catering to numerous possibilities in a wide range of PWM applications. The aim here is to provide an initial introduction, allowing the reader to easily enter the subject and, by the end of the presentation, be able to explore it independently.
Teensy 4.1 FlexPWM Module
Unlike the PWM modules found in many microcontrollers, which can have an up-counting mode (analogous to a sawtooth wave) and an up-and-down-counting mode (analogous to a triangular wave), the iMXRT1062 only features ascending counting mode, which can operate in the range of 0 to TOP or -TOP to TOP-1. The range -TOP to TOP-1 (two's complement counting) is typically used because it simplifies the calculation of the values to be loaded into the comparison registers.
FlexPWM has 7 comparison registers:
INIT - initial count value
VAL0 - generally determines the center of the count (not necessarily), where an interrupt request and reloading of the comparison registers can be made (double sampling)
VAL1 - determines the end of the cycle (TOP-1 value in this presentation), where an interrupt request and reloading of the comparison registers can be made; the counter is loaded with INIT on the next clock pulse
VAL2 - PWM output A goes high when the counter reaches this value
VAL3 - PWM output A goes low when the counter reaches this value
VAL4 - PWM output B goes high when the counter reaches this value
VAL5 - PWM output B goes low when the counter reaches this value
The generated PWM output pulse can be center-aligned or edge-aligned. For rising-edge alignment, as an example, INIT = VAL2 = VAL4 will be configured, with the pulse width defined only by VAL3 (PWMA) and VAL5 (PWMB).
For center alignment and two's complement counting from -TOP to TOP-1, half the pulse width (HPW) can range from 1 to TOP-1, with register VAL2 = -HPW and VAL3 = HPW. If the module is configured to operate in complementary PWMA and PWMB output mode, it is not necessary to define VAL4 and VAL5. This is the option in the Code 1 shown below, which was used to generate the CLK, PWMA and PWMB signals shown in Figs. 1, 2 and 3.
Fig. 1 shows an example of two's complement counting from -5 to 4, with the counter clock at 1kHz. The counter clock signal, the PWMA signal (oscilloscope signals), and an estimate of the counter state are shown.
Normally, the count limits from TOP to TOP-1 are used so that the relationship between the counter clock frequency Ftimer_clk and the carrier frequency Fcarrier is determined by (1). Note that zero is one of the states of the counter.
Fig. 1 - Clock, PWMA signal for 10-step counting, TOP = 5, INIT = -5, VAL1 = 4, VAL2 = -2 and VAL3 = 2
It can be seen in Fig. 2 that the clock signal has a frequency 10 times higher than that of the PWMA signal, as defined in (1).
In Fig. 3 it can be observed that the PWMA and PWMB signals are complementary. In this case, the INDEP bit (See page 3144 of [1]) was kept low. Thus, the modulating signal is defined only by VAL2 and VAL3. If the reader chooses INDEP=1, the PWMA and PWMB outputs will be independent and the comparison registers VAL4 and VAL5 also need to be defined.
There is no problem in considering the count from -TOP to TOP, but in this case the relationship between the frequencies will not be that defined in (1), since we will have one more clock pulse in the carrier period, which may go unnoticed for high values of TOP. Also in this case, the calculation of the exact duty cycle will be slightly different for considering VAL2 = -HPW and VAL3 = HPW. Because of this, the count from TOP to TOP-1 is usually maintained, with the duty cycle determined by (2) as a function of half the pulse width (HPW).
To emphasize the relationship presented in (1), a small value for TOP was chosen (Fig.1, TOP=5). In this case, for a timer clock equal to IPG (150MHz in Teensy 4.1), this would imply a carrier frequency of 15MHz and the clock and PWM signals would be difficult to visualize on a common oscilloscope with a low sampling rate.Thus, in the Code 1 , submodule 3 of FlexPWM1 was used as a kind of prescale for submodule 2 of FlexPWM4 to allow a 1KHz clock, as shown in Fig. 2. For this, it was necessary to establish a connection from the PWMA signal of FlexPWM1, submodule 3, to the external clock of FlexPWM4 via XBAR and external jumper.
In addition to enabling the module to operate at a low frequency, another advantage of this strategy is that the clock signal passes through an external connection (pin 32), making it possible to observe it on an oscilloscope.
Using the Code 1 as a reference, the reader can easily change the counting range (INIT and VAL1) and check what happens to the carrier frequency on a common oscilloscope.
To facilitate signal manipulation, an expansion board was used as shown in Fig. 4, where signal 1A3 (FlexPWM1, submodule 3, PWMA) is connected to pin 32. Before making this connection, ensure that in the Code 1 pin 32, multiplexed to XBAR1_INOUT10, is configured as an input, otherwise damage may occur to the respective GPIOs involved.
Fig. 4 - Teensy 4.1 Expansion Board used to manipulate the signals
Sinusoidal Pulse Width Modulation (SPWM)
As previously mentioned, many microcontrollers feature counters with a counting analogous to a triangular wave in the generation of SPWM signals. The counter in the iMXRT1062's FlexPWM module only counts in up-counting mode. Regardless of the counting method, the same result can be achieved. Fig. 5 shows a comparison of the two counting methods for the same carrier frequency and modulating signal. To facilitate comparison, the triangular signal and the sawtooth signal were synchronized at the zero crossing. In terms of modulating signal amplitude, the two methods exhibit distinct proportions.
In counting analogous to the triangular wave, the PWMA signal is clear on compare match when up-counting and set on compare match when down counting. In this case, the sinusoidal modulating signal has a maximum amplitude equal to TOP/2-1 and an offset of TOP/2.
For sawtooth wave analog counting, the PWMA signal is set when matching the carrier with the negative modulating signal (VAL2) and clear when matching the carrier with the positive modulating signal (VAL3). The polarity of the output signals can be configured using the POLA and POLB bits (See page 3161 of [1]). In this case, the sinusoidal modulating signal has a maximum amplitude equal to TOP/2-1 and an offset of TOP/2. The counter in both cases has the same number of steps, but the signal amplitude in the second case (TOP=10) is half that seen in the first (TOP=20).
In power electronics, the duty cycle is typically limited to the range of 10 to 90% due to switching transient duration considerations, implying stress on the switches for two very close consecutive switching operations; avoiding magnetic saturation in filters and transformers; and maintaining compliance with the specified dead time in the case of complementary switch operation, as in full-bridge converters. In these applications, it is preferable to configure the dead time in the gate driver circuit, as modern gate drivers allow for this configuration, in addition to other important functions such as short-circuit protection.
The modulating signal seen through a low-pass filter is also shown in Fig. 5. Note that due to the filter's phase delay, the PWM signal is delayed relative to the modulating signal. From Fig. 5, it can be concluded that the two SPWM modes generate the same result. Thus, regardless of which mode exists in the microcontroller used, for the same speed and resolution levels, a SPWM of the same quality can be generated.
Fig. 5 - SPWM Comparison: Triangular Wave and Sawtooth Wave
SPWM Code Example
A program example for generating a sinusoidal PWM signal is presented in Code 2 .
The modulating signal (fundamental and third harmonic) is calculated in real time at a sampling rate of 20kHz. The frequency of the fundamental component of the modulating signal is 50Hz.
Every 5 seconds, the third harmonic component is inserted/removed from the modulating signal by the ISR code. The reader can easily change the code to modify the modulating signal, for example, to insert a control law, in the case of feedback control of a converter. Of course, there are more details, such as the use of the A/D converter for reading plant signals, but this will be left for another presentation.
To visualize the resulting analog signals, a low-pass filter (two cascaded RC sections, integrated into the expansion board) with a cutoff frequency of 3189.5 Hz will be used, as shown in Fig. 6. The frequency response of the filter is shown in Fig. 7. Neglecting the loading of one section on the other, it can be observed that the carrier signal (20 kHz) will be attenuated by -32 dB (x0.025).
Fig. 6 - Low-Pass Filter.
Fig. 7 - LPF Bode Diagram.
SPWM Results
Fig. 8 shows the filtered PWMA and PWMB signals when the reference is a pure sine wave. Fig. 9 shows the same outputs when the reference has, in addition to the fundamental, a third harmonic component.
Fig.8 - Filtered PWMA and filtered PWMB for a pure sine wave reference.
Fig.9 - Filtered PWMA and filtered PWMB for a sinusoidal reference with third harmonic
In Fig. 10, the evolution of the pulse width can be observed as the modulating signal varies.
Fig. 10 - Evolution of pulse width according to the modulating signal.
Observations and Recommendations
If you intend to use an external power source for the Teensy 4.1 (as used with the expansion board, Fig. 4), remember to open the connection between the V_in and V_USB pads [2].
It is possible to use an external clock generator connected to pin 32 as the clock for FlexPWM4 (see Code 1 below), but in this case note that the signal must be at the LVTTL level, 3.3V. The Teensy 4.1 pins are not 5V tolerant [2].
Using Teensyduino-style code makes life easier for the user by simplifying some details, but in some cases this can be a problem. Some strange FlexPWM operations were identified in relation to the register reset condition presented in the manual [1], suggesting that these registers were modified during the startup process. Anyway, some of them were reconfigured to the reset value. Some comments are presented in codes 1 and 2 (see below).