Raspberry Pi CM5 IoT In C - - PWM Using GPIO5 |
Written by Harry Fairhead | ||||||||||||||||||||||||||||||||||||||||||
Monday, 12 May 2025 | ||||||||||||||||||||||||||||||||||||||||||
Page 2 of 5
Pulse Density ModeSimple PWM isn’t so good for some power control tasks because the frequency is often low. This makes the filtering problem and hence creating a smooth output voltage, more difficult. For example, suppose you want a 1kHz pulse train with a 50% duty cycle to deliver half power or voltage to a device. The mark/space way of doing this switches the GPIO line on for 500µs and off for 500µs. The fluctuations in voltage are very slow and this causes problems for the driven device. A better way would be to spread the high time across all of the clock cycles. For example, if the clock is 1µs then instead of setting the line high for the first 500 clock pulses and then low for the final 500 clock pulses it might be better to distribute 500 high clock pulses throughout the 1000 clock pulses: blocks and spread the on and off times throughout the block to give the overall desired duty cycle. In this case the device would be high for 1µs and low for 1µs and the filtering problems would be much easier to solve. You can see this for a lower clock rate in the diagram below. The top figure shows a standard PWM 50% duty cycle and the bottom image shows the same duty cycle spread across the entire repeat period: The algorithm for achieving the distribution of the "high" time across the full range period is given in the ARM manual as: context = 0; for(i=0;i<range;i++) { context = context + data; if(context >= range){ context = context - range; set line high }else{ Suppose Range is 8 and Duty is 4, giving a 50% duty cycle, then the algorithm generates: clock 1 2 3 4 5 6 7 8 context 4 8 4 8 4 8 4 8 line 0 1 0 1 0 1 0 1 mark/space mode 1 1 1 1 0 0 0 0 Notice that each output pulse is the same width as the clock time rather than the time to count up to Range. Pulse Position ModeIn pulse position mode the counter runs from 0 to Range and the output is only high when the count equals Duty. In this case the output is a single pulse, the width of the clock, at a position determined by Duty. That is, changing Duty changes where the pulse occurs. There are also two serializer modes which allow you to output an arbitrary pulse train. Both modes make use of the duty register as a shift register and the output is composed of either the most significant, Serializer_MSB, or least significant, Serializer_LSB. bit in the shift register. To summarize:
In addition to these modes, the PWM channels can be configured to share a common range and duty register. There is also a shared 32-bit FIFO register, a “first-in, first out” queue with storage for 128 32-bit values that can be used to set the duty of enabled channels. Notice that all four of the PWM channels are fed by a single clock which can be set to a frequency via a programmable divider. The only way that the PWM channels can produce different frequencies is by having different values of range. Clocks and Duty Cycle ResolutionIf you just take the PWM driver at face value then you might believe that you can set any frequency and any duty cycle – this is not the case. Due to hardware limitations, the resolution of the duty cycle depends on the PWM clock frequency and this also governs the highest frequency PWM signal you can create. 25MHz
What happens is that two clock pulses are needed to change the state of the line twice – once high and once low. This corresponds to range=1 and duty=1. You can also see that 50% is the only possible duty cycle apart from 0% and 100%. The number of different duty cycles you can achieve depends on the number of clock pulses in the total PWM period. You can easily work out the number of duty cycles available at any given frequency:
In many applications 8-bit resolution for the duty cycle is considered the minimum acceptable and this sets the highest frequency to about 195kHz, which is high enough for most things. For example, if you want to control a servo motor, see later, then you need a PWM signal with a frequency of 50Hz and at this frequency you can specify the duty cycle down to about 25 bits or around 40 million increments, more than enough for any real servo motor. |
||||||||||||||||||||||||||||||||||||||||||
Last Updated ( Tuesday, 13 May 2025 ) |