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; }

In reply to PWM on raspberrypi with bcm2835 by martell

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.