Dear Monks
I thought I share this small Perl program demonstrating the possibility to do PWM (Pulse Wide Modulation) on Raspberry Pi in order to control the intensity of a led. This is a common introduction example to try for people learning about electronics on Raspberry Pi. Well documented examples for python exists, but not for Perl.
The reason I share this here, is that the current CPAN module Device::BCM2835 doesn't define the necessary function to do this (that I see). So it took me some tinkering before I could control the PWM from Perl. Novice users of Perl may find this example code the thing they need.
The solution I apply is the use of the Inline::C module to call some small wrapper functions I wrote in C around an existing C example I found on the internet. They call in turn the bcm2835 functions needed. This is tested on a raspberry pi B, revision 2 unit, using a single led and a single resistor.
Be aware that on later versions of Raspberry Pi the GPIO pin layout is different and you have to use other constants in the functions calls in the C code. So YMMV, but enough documentation exists on the internet to figure out the correct values.This code assumes you have installed the Inline::C module, Time::HiRes module, and the bcm2835 C library on your device. See Device::BCM2835 module for the appropriate links to the C library. It is not installed by default. Run as root on Raspberry Pi because you need to have access to some low level functions.
Today I'm not proficient in XSLoader to update the Device::BCM2835 module itself, but if I have some spare time, I will look into it. Would be a nice additional skill to master.
Any thoughts or comments appreciated.
Martell
# pwm.pl use Time::HiRes qw( usleep); use Inline C => Config => LIBS => '-lbcm2835'; use Inline C; # # Simple loops 10 times through some intensity values for # the led. # # You can give a integer (0 .. 1024) on the command line # to set the final brightness level at the end of the # script. # # No secured in any way against bad input, errors, ... # print "start\n"; if (!pwm_prepare()) { print "prepare led succeeded\n"; my @levels = (0,1,2,4,8,16,32,64,128,256,512,1024); for (my $i = 0; $i < 10; $i++) { foreach my $level (@levels) { # print "level: $level\n"; pwm_set_led_intensity($level); usleep(50000); } } pwm_set_led_intensity($ARGV[0]); pwm_clean(); print "the end\n"; } __END__ __C__ #include <stdio.h> #include <bcm2835.h> // PWM output on RPi Plug P1 pin 12 (which is GPIO pin 18) // in alt fun 5. // Note that this is the _only_ PWM pin available on the RPi IO header +s #define PIN RPI_GPIO_P1_12 // and it is controlled by PWM channel 0 #define PWM_CHANNEL 0 // This controls the max range of the PWM signal #define RANGE 1024 int pwm_prepare(); void pwm_clean(); void pwm_set_led_intensity (int level); int pwm_prepare() { if (!bcm2835_init()) return 1; // Set the output pin to Alt Fun 5, to allow PWM channel 0 to be o +utput there bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_ALT5); // Clock divider is set to 16. // With a divider of 16 and a RANGE of 1024, in MARKSPACE mode, // the pulse repetition frequency will be // 1.2MHz/1024 = 1171.875Hz bcm2835_pwm_set_clock(BCM2835_PWM_CLOCK_DIVIDER_16); bcm2835_pwm_set_mode(PWM_CHANNEL, 1, 1); bcm2835_pwm_set_range(PWM_CHANNEL, RANGE); return 0; } void pwm_clean() { bcm2835_close(); return; } void pwm_set_led_intensity (int level) { if (0 <= level && level <= 1024) { bcm2835_pwm_set_data(0,level); } return; }
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: PWM on raspberrypi with bcm2835
by jmlynesjr (Deacon) on Jun 26, 2016 at 17:29 UTC |