What is WiringPi2 and why do I need it?
WiringPi2 for Python is an excellent GPIO handling system written by Gordon ‘Drogon’ Henderson and packaged for Python by Phil ‘Gadgetoid’ Howard. It uses Arduino-like scripting language. For simple GPIO work, I still tend to use RPi.GPIO because that’s what I first got started with, but WiringPi is a very good alternative. It currently has more features.
One of the reasons (I think) the take-up for WiringPi-Python has been a bit slow, despite its richer feature set, is the lack of documentation. I’m hoping that this series of articles will provide documentation to open the door to more people using WiringPi 2 for Python. The basics in this first article should all work for both WiringPi and WiringPi 2 for Python.
If you’ve used my Gertboard Python software, you may well have used both the original WiringPi AND RPi.GPIO. WiringPi2 is an upgrade with more features added.
All the basic features still work the same way, but Gordon has added a lot more capabilities.
WiringPi2 is written in C, but has been packaged for Python, Ruby and PERL as well.
WiringPi2 for Python is not installed in the standard Raspbian image, so you will have to install it before you can use it. It’s quite easy though, and full instructions for that are found here.
So, once installed, how do you use it?
Near the top of the your Python script you need to import the wiringpi2 module
import wiringpi2 as wiringpi
Then, before you do anything else with wiringpi2, you need to initialise it.
Pins or Ports?
WiringPi2 was written to be similar in style to the Arduino Wiring language. Hence the emphasis on pins and pin numbers.
Many people prefer to use the Broadcom General Purpose Input Output (GPIO) port numbers “to avoid an additional level of abstraction” :) There’s fierce debate about this, which I will leave to those far cleverer than myself. As far as I’m concerned, use whichever system works best for you and the way you think.
To allow everyone to use their own preference, there are various WiringPi modes you can use…
- WiringPi pin mode
- GPIO mode
- Physical pin numbers (header P1 only)
I usually use GPIO mode, but here’s how to set up each of them…
- To initialise WiringPi pin mode
- To initialise GPIO mode
- To initialise Physical P1 header pin mode
Set up the ports
Then before you can use any GPIO ports for input, output or alternative functions you have to set up those ports/pins
where port_number is the GPIO port (or pin) number
X = 0 for input,
X = 1 for output,
X = 2 for alternative function (e.g. PWM on port 18)
Here’s Gordon’s chart…
Here’s how you code each of them
# GPIO port numbers import wiringpi2 as wiringpi wiringpi.wiringPiSetupGpio() wiringpi.pinMode(25, 0) # sets GPIO 25 to input wiringpi.pinMode(24, 1) # sets GPIO 24 to output wiringpi.pinMode(18, 2) # sets GPIO 18 to PWM mode # wiringpi numbers import wiringpi2 as wiringpi wiringpi.wiringPiSetup() wiringpi.pinMode(6, 0) # sets WP pin 6 to input wiringpi.pinMode(5, 1) # sets WP pin 5 to output wiringpi.pinMode(1, 2) # sets WP pin 1 to PWM mode # Physical P1 header pin numbers import wiringpi2 as wiringpi wiringPiSetupPhys() wiringpi.pinMode(22, 0) # sets P1 pin 22 to input wiringpi.pinMode(18, 1) # sets P1 pin 18 to output wiringpi.pinMode(12, 2) # sets P1 pin 12 to PWM mode
It may be a bit confusing, but each of the above three sets of five lines does exactly the same thing from the end-user’s point of view. It’s best if you choose just one system you like and stick to it. But it’s wise to know that they all exist in case you ever need to look at someone else’s code. :)
How to Read Inputs with WiringPi 2
Having initialised your port or pin, you use the following code to read its value…
So, if we’re using GPIO mode, we can read the current value of port 25 with this…
This returns a Boolean value 1 or 0, True or False (1 = 3.3V and 0 = 0V on the port/pin).
If you want to do anything useful with it, you’ll likely want to stuff the value into a variable like this…
my_input = wiringpi.digitalRead(25)
…then because it’s a Boolean variable, you can (but don’t have to) use it in this way in your program logic…
if my_input: print "Input on Port 25 is 1" # then you'd code what you want to happen when port 25 is HIGH else: print "Input on Port 25 is 0" # then you'd code what you want to happen when port 25 is LOW
if my_input: is a short and efficient* way of asking
if my_input == 1:
That’s really all there is to reading input port/pin values. It’s the same regardless of which numbering scheme you chose, but obviously the port/pin numbers are different. :)
How to Write to Outputs with WiringPi 2
Ports/pins are set at either 0 or 1. Having initialised everything, including setting all the ports you want to write to as outputs, use the following command…
wiringpi.digitalWrite(port_or_pin_number, 0) # sets port/pin to 0 (0V)
wiringpi.digitalWrite(port_or_pin_number, 1) # sets port/pin to 1 (3.3V)
Here’s an example using GPIO port numbers…
# GPIO port numbers import wiringpi2 as wiringpi from time import sleep wiringpi.wiringPiSetupGpio() wiringpi.pinMode(24, 1) # sets GPIO 24 to output wiringpi.digitalWrite(24, 0) # sets port 24 to 0 (0V, off) sleep(10) # wait 10s wiringpi.digitalWrite(24, 1) # sets port 24 to 1 (3V3, on) sleep(10) # wait 10s wiringpi.digitalWrite(24, 0) # sets port 24 to 0 (0V, off)
The above code will initialise everything for GPIO mode, set up port 24 as an output (line 5) and then, in line 6, immediately set it to 0 (0V).
Then, in line 7, it waits 10 seconds (which is why we needed to import sleep) after which line 8 switches port 24 to 1 (3V3)
After another 10 second wait (line 9) it will switch off port 24 (line 10) and exit.
Clean up after yourself
The above code exits with port 24 set as output. This isn’t best practice.
It’s a good idea to clean up after yourself when you exit a program, or you’ll get error messages “port is already in use by another program” next time you try to open that port. (Some programs will error out if that happens).
But even more importantly, if a port is set to output and you forget and connect an input source to it, you can “fry” a port. Obviously it’s better not to take that chance.
So it’s a good idea to leave things tidy. The best way to do that is to switch off and set all the ports you’ve used back to inputs again at the end. You should already know enough to do that…
wiringpi.digitalWrite(24, 0) # sets port 24 to 0 (0V, off) – may be unnecessary, but I prefer to do it
wiringpi.pinMode(24, 0) # sets GPIO 24 to input Mode
…so here’s the above program modified to incorporate it. In this case the port is already off, so there’s no need to switch it off again.
# GPIO port numbers import wiringpi2 as wiringpi from time import sleep wiringpi.wiringPiSetupGpio() wiringpi.pinMode(24, 1) # sets GPIO 24 to output wiringpi.digitalWrite(24, 0) # sets port 24 to 0 (0V, off) sleep(10) wiringpi.digitalWrite(24, 1) # sets port 24 to 1 (3V3, on) sleep(10) wiringpi.digitalWrite(24, 0) # sets port 24 to 0 (0V, off) wiringpi.pinMode(24, 0) # sets GPIO 24 back to input Mode
Now let’s do a one input one output circuit
Here’s some simple code to drive this
import wiringpi2 as wiringpi from time import sleep # allows us a time delay wiringpi.wiringPiSetupGpio() wiringpi.pinMode(24, 1) # sets GPIO 24 to output wiringpi.digitalWrite(24, 0) # sets port 24 to 0 (0V, off) wiringpi.pinMode(25, 0) # sets GPIO 25 to input try: while True: if wiringpi.digitalRead(25): # If button on GPIO25 pressed wiringpi.digitalWrite(24, 1) # switch on LED. Sets port 24 to 1 (3V3, on) else: wiringpi.digitalWrite(24, 0) # switch off LED. Sets port 24 to 0 (0V, off) sleep(0.05) # delay 0.05s finally: # when you CTRL+C exit, we clean up wiringpi.digitalWrite(24, 0) # sets port 24 to 0 (0V, off) wiringpi.pinMode(24, 0) # sets GPIO 24 back to input Mode # GPIO 25 is already an input, so no need to change anything
The above code simply reads the button port (GPIO25) 20 times per second. If it detects that the button is pressed, it switches output port (GPIO24) on. If not pressed, it switches the port off (even if it’s already off – it doesn’t matter).
Now you hack the code to make it better
There’s a lot more you could do with this…
- introduce time delays
- one press for on – another press for off
Take the example and make something more of it. Your imagination’s the limit. That’s it for today.
With WiringPi2, I’ll be taking things at a slightly less frantic pace than last week’s 7 part series.
* Using just
if wiringpi.digitalRead(25): is even more efficient, but storing the current reading in a variable catches a snapshot “now”.