Pi IoT In C Using Linux Drivers - The PWM Driver |
Written by Harry Fairhead | ||||
Monday, 10 May 2021 | ||||
Page 1 of 3 Many programmers are unaware that there is a perfectly good PWM driver that will let you do just about anything you want to, without having to resort to any clever programming. This content comes from my newly published book: Raspberry Pi IoT In C Using Linux DriversBy Harry FairheadBuy from Amazon. Contents
<ASIN:1871962641> <ASIN:B08W9V7TP9> One way around the problem of getting a fast response from a microcontroller is to move the problem away from the processor. In the case of the Pi's processor there are some built-in devices that can use GPIO lines to implement protocols without the CPU being involved. In this chapter we take a close look at pulse width modulation (PWM) including generating sound and driving LEDs. When performing their most basic function, i.e. output, the GPIO lines can be set high or low by the processor. How quickly they can be set high or low depends on the speed of the processor. Using the GPIO line in its Pulse Width Modulation (PWM) mode you can generate pulse trains up to 4.8MHz, i.e. pulses just a little more than 0.08µs. The reason for the increase in speed, a factor of at least 100, is that the GPIO is connected to a pulse generator and, once set to generate pulses of a specific type, the pulse generator just gets on with it without needing any intervention from the GPIO line or the processor. In fact, the pulse output can continue after your program has ended if you forget to reset it. Of course, even though the PWM line can generate pulses as short as 0.1µs, it can only change the pulses it produces each time that the processor can modify them. For example, you can't use PWM to produce a single 0.1µs pulse because you can't disable the PWM generator in just 0.1µs. This said, hardware generated PWM is available on the Pi and there is a good PWM driver that makes it very easy to use. In book, but not in this extract
The PWM DriverAll Pi models have two PWM channels implemented in hardware, but on models earlier than the Pi 4 these are also used to generate audio. What this means is that if you want to use hardware PWM on a Pi Zero or earlier you have to disable or at least not use audio at the same time. You can use both on a Pi 4, but notice that the PWM channels and the audio share the same clock signal and this can still cause problems. The two PWM hardware modules can be configured to drive different GPIO lines. For the Pi the standard configuration is to have PWM0 drive either GPIO18 or GPIO12 and PWM1 drive either GPIO13 or GPIO19. There are two PWM drivers available. One that activates a single PWM channel and one that activates both the available channels. The documentation for both is: Name: pwm Info: Configures a single PWM channel Legal pin,function combinations for each channel: PWM0:12,4(Alt0) 18,2(Alt5) 40,4(Alt0) 52,5(Alt1) PWM1:13,4(Alt0) 19,2(Alt5) 41,4(Alt0) 45,4(Alt0) 3) So be careful mixing audio and PWM. 4) Currently the clock must have been enabled and configured by other means.
Params:pin Output pin (default 18) - see table func Pin function (default 2 = Alt5) - see above clock PWM clock frequency (informational) Name: pwm-2chan Note: There is a relatively recent (late 2019) patch to the driver that fixes a problem at high PWM frequencies. Use: sudo apt update followed by sudo apt full-upgrade to make sure you have the up-to-date driver. In simple terms you can use one or two channels of PWM and you would be well advised to use GPIO18 for PWM0 and GPIO19 for PWM1 on all modern Pis. Notice that you cannot currently use the driver to set the frequency of the PWM clock, but this is automatically enabled at a default frequency. You can find what the frequency is using: vcgencmd measure_clock pwm at the command prompt. It only reports an accurate value if the PWM driver is loaded and enabled. On a Pi Zero and a Pi 4 it reports 99995000, i.e. approximately 100Mhz, and empirical measurements give the effective clock rate, after division by 5, as 20MHz for both the Pi 4 and Pi Zero. The clock rate is important because it determines the resolution of the duty cycle – see later. If you load either driver by adding: dtoverlay=pwm or dtoverlay=pwm-2chan to boot/config.txt, you will discover that on reboot you have a new pwmchip0 folder in the /sys/pwm folder. The pi driver is configured to see the PWM hardware as a single PWM “chip”. To work with either PWM channel you have to export it. In this context exporting means that you claim sole use of the channel. To do this you have to write a “0” or a “1” to the export file in the pwmchip0 folder. To unexport you do do the same to the unexport file in the pwmchip0 folder. After you have exported the channel you will see new folders, pwm0 and pwm1 in the pwmchip0 folder. Of course you only see the folders you have exported and you can only export pwm0 if you have use the PWM driver. Within the pwmx folder you will find the following important files: period period in nanoseconds duty_cycle duty cycle in nanoseconds enable write 1 to enable, 0 to disable So all you have to do is:
Notice that as this is hardware PWM, once you have set and enabled the channel, the PWM generation continues after the program ends. A simple program to use PWM0 is: #define _DEFAULT_SOURCE #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <fcntl.h> FILE *doCommand(char *cmd) { FILE *fp = popen(cmd, "r"); if (fp == NULL) { printf("Failed to run command %s \n\r", cmd); exit(1); } return fp; } void checkPWM() { FILE *fd = doCommand("sudo dtparam -l"); char output[1024]; int txfound = 0; char indicator[] = "pwm-2chan"; char command[] = "sudo dtoverlay pwm-2chan"; while (fgets(output, sizeof(output), fd) != NULL) { printf("%s\n\r", output); fflush(stdout); if (strstr(output, indicator) != NULL) { txfound = 1; } } if (txfound == 0) { fd = doCommand(command); sleep(2); } pclose(fd); } int main(int argc, char **argv) { checkPWM(); int fd = open("/sys/class/pwm/pwmchip0/export", The checkPWM function dynamically loads the pwm-2chan driver – you can change it to pwm if you only need one channel. It exports the channel and then sets the period to 100Hz with an 80% duty cycle. A delay of 1 second is included after the export to allow the system to create the folders and files. <ASIN:B06XFZC3BX> <ASIN:B0748MPQT4> <ASIN:B08R87H4RR> <ASIN:B07V5JTMV9> |
||||
Last Updated ( Wednesday, 12 May 2021 ) |