RPi::WiringPi::FAQ - FAQ and Tutorial for RPi::WiringPi
This document will hopefully provide enough information in a sane way to get you well on your way with manipulating your Raspberry Pi with the RPi::WiringPi and related distributions.
In this document we use constants that are provided with the :all tag in RPi::WiringPi::Constant module.
:all
HIGH - connected to 3.3v (positive) LOW - connected to 0v (ground) floating - state where a pin is not stable at HIGH or LOW PWM - Pulse Width Modulation (potentiometer-like) INPUT - pin is listening only OUTPUT - pin is active in turning things on/off PWM_OUT - pin is OUTPUT, but PWM capable GPIO_CLOCK - pin is used for timing PUD - internal pull up/down resistor PUD_UP - PUD resistor pulled to HIGH PUD_DOWN - PUD resistor pulled to LOW EDGE_FALLING - a state when a pin goes from HIGH to LOW EDGE_RISING - a state when a pin goes from LOW to HIGH EDGE_BOTH - both of the above states DPOT - digital potentiometer
If you want to avoid using your system installed Perl installation to use this software (or you want to use interrupts), you should do some pre-configuration of your system. Note that the system installed Perl does not use threads, which is required for interrupts to function.
As your normal, every day user, install perlbrew, Then install an instance of Perl, and switch to it:
perlbrew install perl-5.24.0 perlbrew switch perl-5.24.0
To use sudo to run your scripts within the appropriate Perl installation, you need to modify the /etc/sudoers file. Prepend the string value for the secure_path directive to include the path to the new perlbrew managed perl, followed by a colon. For example: /home/pi/perl5/perlbrew/perls/perl-5.24.0/bin:. Leave the existing part of the string in place.
sudo
/etc/sudoers
secure_path
perlbrew
/home/pi/perl5/perlbrew/perls/perl-5.24.0/bin:
Now, you can do everything with the normal user account, using their personal installation of Perl, and you just need sudo to run your scripts, leaving your default system installation intact.
The first thing you need to do is call an appropriate setup method. We do that automatically. See new() to see how to use non-default setup routines. By default, we use the GPIO pin numbering scheme. Run the included pinmap program to get a printout of a chart containing the various pin numbers for the different mapping schemes.
pinmap
my $pi = RPi::WiringPi->new;
The board revision is the same as the GPIO pin layout on the board:
my $revision = $pi->gpio_layout;
The RPi::WiringPi::Pin class provides you with objects that directly map to the Raspberry Pi's onboard GPIO pins. You generate a pin object through the main $pi object we created above.
$pi
my $pin = $pi->pin(27); # set the mode to output, presumably to power an external device $pin->mode(OUTPUT); # by default, pins are set to LOW (ie. 0 voltage). Turn it on... $pin->write(HIGH); # get the current status of a pin (HIGH or LOW) my $state = $pin->read; # get a pin's pin number my $num = $pin->num;
All GPIO pins on the Raspberry Pi have built-in pull up/down resistors to prevent pins being in a "floating" state when not connected to either ground or power. This is very important in many situations, particularly when using interrupts.
# HIGH when not in use $pin->pull(PUD_UP); # LOW when not in use $pin->pull(PUD_DOWN);
Pulse Width Modulation kind of acts like a potentiometer (or a variable switch... like a light dimmer). They are used to send pulses of electricity to a device across time. It is required for things like stepper motors, or dimming an LED. Note that only physical pin 12 on the Raspberry Pi has hardware-based PWM (GPIO #18).
12
# set the pin to PWM_OUT mode. Must be physical pin 12 $pin->mode(PWM_OUT); # values are 0-1023 which represent 0% to 100% power $pin->pwm(512); # pin output is ~50% # make pin go from off to bright gradually... # requires Time::HiRes qw(usleep); my $pin = $pi->pin(18); $pin->mode(PWM_OUT); for (0..1023){ $pin->pwm($_); usleep 50000; }
Built in is the ability to have Perl code you define executed when a pin's edge changes (a pin goes from LOW to HIGH or vice-versa). This code acts as an interrupt handler. The Interrupt Service Request that listens for the change runs in a separate C thread than your application.
Interrupts are useful in many cases, but think of a button; you want an action to happen when someone presses a physical button on your prototype, but you obviously want to be doing other things while waiting for that button press.
# set an interrupt handler for when the pin goes from # LOW to HIGH. The second parameter is the string name # of the Perl subroutine at the bottom of this example $pin->interrupt_set(EDGE_RISING, 'handler'); # HIGH to LOW $pin->interrupt_set(EDGE_FALLING, 'handler'); # HIGH and LOW (handler will be called on both changes) $pin->interrupt_set(EDGE_BOTH, 'handler'); sub handler { print "in handler\n"; # do other stuff, perhaps turning on/off other pins }
Although we've already used interrupts from within a pin object, you can use them separately as well.
my $interrupt = $pi->interrupt; # set an EDGE_RISING interrupt on pin 27 # callback is the string name of your handler # subroutine that'll be called when an interrupt # has occurred $interrupt->set(27, EDGE_RISING, 'callback'); sub callback { ... }
Allows you to write to and read from devices attached to the SPI bus, using the external RPi::SPI distribution. Please refer to that documentation for full usage instructions.
# generate a new SPI object my $channel = 0; # /dev/spidev0.0 my $spi = $pi->spi($channel); my $buf = [0x01, 0x02]; my $len = 2; # write the two bytes in the buffer to channel /dev/spidev0.0 $spi->rw($buf, $len); # do a read-only call. Send in the number of bytes you want back as dummy # bytes (ie. 0) my $dummy = [0x00, 0x00, 0x00]; my @read_buf = $spi->rw($dummy, 3);
This functionality is brought in from RPi::ADC::ADS. Please refer to that documentation for full usage instructions.
# fetch a new ADC object my $adc = $pi->adc; # fetch the voltage level on pin A0 on the ADC my $v = $adc->volts(0); # fetch the percentage of input on pin A0 my $p = $adc->percent(0);
This functionality is brought in from RPi::DigiPot::MCP4XXXX. Please refer to that documentation for full usage instructions.
my $cs = 18; # GPIO pin connected to dpot CS pin my $channel = 0; # SPI channel /dev/spidev0.0 my $dpot = $pi->dpot($cs, $channel); # set to 50% output $dpot->set(127); # shutdown (sleep) the potentiometer $dpot->shutdown;
This software has the capability to utilize 74HC595 shift registers.
Each register contains 8 digital outputs, and four can be daisy-chained together for a total of 32 extra output pins.
Each register (or chain of registers) require only three GPIO pins.
We'll get right into the code:
# the new register pins will start at GPIO 100. # this can be any number outside of existing GPIO my $base = 100; # the number of pins on the register(s) you plan on # using. Maximum eight per register my $num_pins = 8; # the GPIO pin number that the register's DS pin (14) # is connected to my $data = 5; # the GPIO pin number that the register's SHCP pin (11) # is connected to. This is the register's clock my $clk = 6; # the GPIO pin number that the register's STCP pin (12) # is connected to. This is the register's latch pin my $latch = 13; # initialize the register $pi->shift_register($base, $num_pins, $data, $clk, $latch); # now you have full access to the register's eight outputs # through standard methods for (100..107){ my $pin = $pi->pin($_); $pin->write(HIGH); }
Typical 16-pin, 2-4 row and 16-20 column LCD screens work here. You can use 4-bit or 8-bit mode (4-bit requires 6 GPIO pins, 8-bit requires 10). If you need a higher rate of data transmission to the LCD, use 8-bit mode. Typically, 4-bit has always worked perfectly for me.
Before an LCD can be used, it must be initialized. This may look like a lot, but you only need to do it once. Essentially, you're configuring all pins up front.
NOTE: When in 4-bit mode, although you're setting d0 through d3 pins up and leaving d4 through d7 as 0, the wiring must connect to LCD pins d4 through d7. Look at LCD pin 4-7 as LCD pin 0-3 when in 4-bit mode.
d0
d3
d4
d7
0
my $lcd = $pi->lcd; my %lcd_args = ( rows => 2, # number of display rows, 2 or 4 cols => 16, # number of display columns 16 or 20 bits => 4, # data width in bits, 4 or 8 rs => 1, # GPIO pin for the LCD RS pin strb => 2, # GPIO pin for the LCD strobe (E) pin d0 => 3, # ... # d0-d3 GPIO pinout numbers d3 => 6, # d4 => 7, # set d4-d7 to all 0 (zero) if in 4-bit mode ... # otherwise, set them to their respective d7 => 11 # GPIO pins ); $lcd->init(%lcd_args);
Now that we've initialized the LCD, we're ready to use it.
# turn the display on/off. It's on by default $lcd->display(ON); # or OFF # put the cursor at col 0, row 0 $lcd->home; # clear the display and move cursor to home $lcd->clear;
# move the cursor to a position $lcd->position(0, 0); # col 0 (first slot), row 0 (top row) $lcd->position(0, 1); # col 0 (first slot), row 1 (bottom row on 2 row LCD) $lcd->positon(5, 1); # col 5 (6th slot), row 1 # turn on/off cursor (on by default) $lcd->cursor(OFF); # or ON # make the cursor blink (off by default) $lcd->cursor_blink(ON); # or OFF
By default, output starts at col 0 and row 0 of the display. Use position() to move it around before outputting.
position()
# print out a string $lcd->print("My name is stevieb");
Here's a trivial script that outputs information to specific LCD positions (we'll start right after an LCD init()).
init()
my $perl_ver = '5.24.0'; my $name = 'stevieb'; $lcd->home; $lcd->print("${name}'s RPi, on"); $lcd->position(0, 1); $lcd->print("Perl $perl_ver...");
Built in is support for the BMP085 and BMP180 barometric pressure and altimiter sensors, which also include a temperature sensor.
A full use-case example of using the barometric/temperature sensor:
my $pin_base = 200; # any number higher than the highest GPIO my $bmp = $pi->bmp($pin_base); my $f = $bmp->temp; my $c = $bmp->temp('c'); my $p = $bmp->pressure; # kPa
The included RPi::WiringPi::Util module contains a few helper-type methods for internal and external use. Most of these you won't need, but others are very helpful when writing your own scripts that go beyond trivial.
You can transform pin numbers from one scheme to another, get full pin number maps/translation hashes, manually export and unexport GPIO pins etc.
It's worth having a look at...
Steve Bertrand, <steveb@cpan.org>
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.18.2 or, at your option, any later version of Perl 5 you may have available.
To install RPi::WiringPi, copy and paste the appropriate command in to your terminal.
cpanm
cpanm RPi::WiringPi
CPAN shell
perl -MCPAN -e shell install RPi::WiringPi
For more information on module installation, please visit the detailed CPAN module installation guide.