With only one hardware PWM pin on Raspberry Pi it can be quite a problem with Arduino users like me.There are various hardware solutions available to overcome this problem.Many ADC(analog to digital converters) IC are available which can be interfaced via I2C bus.In this post I will be using WiringPi library which can bit-bang any GPIO pins and generate PWM signal. Even though the PWM signals are generated by individual threads with high priority using a real-time scheduler, there may be instances where it may get temporarily descheduled for a fraction of a second and cause jitters.
Installing the Library:-
WiringPi is maintained under GIT for ease of change tracking.If you do not have GIT installed, then under any of the Debian releases, you can install it with-
sudo apt-get install git-core
To obtain WiringPi using GIT:
git clone git://git.drogon.net/wiringPi
If you have already used the clone operation for the first time, then
cd wiringPi
git pull origin
Will fetch an updated version then you can re-run the build script below.
To build/install there is a new simplified script:
cd wiringPi
./build
The new build script will compile and install it all for you – it does use the sudo command at one point, so you may wish to inspect the script before running it.
Example Code:-
This code uses both the hardware and software PWM functions.
Installing the Library:-
WiringPi is maintained under GIT for ease of change tracking.If you do not have GIT installed, then under any of the Debian releases, you can install it with-
sudo apt-get install git-core
To obtain WiringPi using GIT:
git clone git://git.drogon.net/wiringPi
If you have already used the clone operation for the first time, then
cd wiringPi
git pull origin
Will fetch an updated version then you can re-run the build script below.
To build/install there is a new simplified script:
cd wiringPi
./build
The new build script will compile and install it all for you – it does use the sudo command at one point, so you may wish to inspect the script before running it.
Example Code:-
This code uses both the hardware and software PWM functions.
//////--------------------------------------------------------------------------- ////// Name: pwm.c ////// Compiled with: gcc pwm.c -I/usr/local/include -L/usr/local/lib -lwiringPi -lpthread -o pwm ////// Schematic: .------. ////// | o o | ////// RPi | o o |12 ////// | o o-|-----(->|)-----\/\/\/\--o GND ////// | o o |11 LED1 220 ////// | o o-|-----(->|)-----\/\/\/\--o GND ////// | o o | LED2 220 ////// | o o-| ////// ////// Notes: //////--------------------------------------------------------------------------- #include <stdio.h> #include <stdlib.h> #include <signal.h> #include <wiringPi.h> #include <softPwm.h> void control_event(int sig); int HARD_PWM_PIN=1; //Hardware PWM Pin(GPIO18-12) int SOFT_PWM_PIN=0; //Software PWM Pin(GPIO0-11) int DELAY_MS=10; int main(void) { (void)signal(SIGINT,control_event); (void)signal (SIGQUIT,control_event); printf("Hardware and software based PWM test on LED\n"); if(getuid()!=0) //wiringPi requires root privileges { printf("Error:wiringPi must be run as root.\n"); return 1; } if(wiringPiSetup()==-1) { printf("Error:wiringPi setup failed.\n"); return 1; } pinMode(HARD_PWM_PIN,PWM_OUTPUT); //setup hardware pwm softPwmCreate(SOFT_PWM_PIN,0,100); //setup software pwm pin int up; int down; while(1) { for(up=1;up=5;down--) { pwmWrite(HARD_PWM_PIN,down); softPwmWrite(SOFT_PWM_PIN,down); delay(DELAY_MS*2); } delay(DELAY_MS*5); } } void control_event(int sig) { printf("\b\bExiting...\n"); pwmWrite(HARD_PWM_PIN,0); softPwmWrite(SOFT_PWM_PIN,0); delay(100); //wait a little for the pwm to finish write exit(0); }Limitations:- To minimize CPU usage the minimum default pulse width is set to 100μs thereby generating a PWM of 100 Hz. Lowering the range can give you a higher frequency at an expense of resolution and vice versa. Delays less than 100μs will dramatically increase the CPU usage and controlling other pins would be impossible.However, within these limitations controlling an LED or Motor is quite practical.