Jul 232013
 

Basic Input/Output with WiringPi 2

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…

  1. WiringPi pin mode
  2. GPIO mode
  3. Physical pin numbers (header P1 only)

I usually use GPIO mode, but here’s how to set up each of them…

  1. To initialise WiringPi pin mode
    wiringpi.wiringPiSetup()
  2. To initialise GPIO mode
    wiringpi.wiringPiSetupGpio()
  3. To initialise Physical P1 header pin mode
    wiringpi.wiringPiSetupPhys()

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

wiringpi.pinMode(port_or_pin_number, X)

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…

Pin numbering schemes for WiringPi2-python

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…
wiringpi.digitalRead(port_or_pin_number)

So, if we’re using GPIO mode, we can read the current value of port 25 with this…
wiringpi.digitalRead(25)

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

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
  • flashing
  • 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.

In part 2, we’ll cover more advanced features like pull-ups/pull-downs and PWM.
In part 3, we’ll cover some of the new advanced features of WiringPi2 for Python.

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”.

  23 Responses to “How to use WiringPi2 for Python on the Raspberry Pi in Raspbian part 1”

  1. Nice, good post!!

  2. Hello,

    Thank you for this great tutorial, but i have a problem. This is my program:

    import wiringpi2 as wiringpi
    from time import sleep
    wiringpi.wiringPiSetupPhys()
    wiringpi.pinMode(11, 1)
    wiringpi.digitalWrite(11, 1)
    sleep(10)
    wiringpi.digitalWrite(11, 0)

    When I launch this program by the Python environement it’s work great (the LED is on for 10 sec) : http://image.noelshack.com/fichiers/2014/24/1402857730-terminal-marche.jpg

    But when i launch it by the Python Shell or the terminal with “# python /home/pi/Desktop/lampe.py” it dosen’t work (nothing happens):
    http://image.noelshack.com/fichiers/2014/24/1402857730-terminal-marchepas.jpg
    http://image.noelshack.com/fichiers/2014/24/1402857731-python-shell.jpg

    Can you help me ?

    Thank you

  3. Is there a wiring pi pin-out for the Raspberry pi 2 40 pin IO connector?

  4. I have been trying to do PWM with a PiFace and I believe wiringPi to be my best chance, I have the motor wired based off a video from gordon using a transistor but I was wondering if you could say more about this PWM mode on GPIO 2. Im very new and Im not exactly sure how this works etc.

  5. Do you know this might interface with the lol_dht22 driver for temperature/humidity readings?

  6. Will wiringpi2 work for a Raspberry Pi 2 running Ubuntu 14.04?

  7. is speed of wiringPi for python is same as the C code ?

    • Nope. Even if the underlying backend is written in C, your program running over the top is written in Python, so the speed of the python interpreter will still be the limiting factor.

  8. Hi,
    thanks for the tuto
    i cant seems to use digitalWrite to turn on/off the relay but i can turn it on/off by changing the mode to in and out.
    any idea?

    # GPIO port numbers
    import wiringpi as wiringpi
    from time import sleep

    wiringpi.wiringPiSetupGpio()

    wiringpi.pinMode(18, 1)
    #wiringpi.digitalWrite(18, 1)
    print ‘Power ON’

    sleep(5)

    #wiringpi.digitalWrite(18, 0)
    wiringpi.pinMode(18, 0)
    print ‘Power OFF’

    • Hi Louis, A very late reply i know, but for anyone that has the same issue…

      Sound like your relays are “active low”, meaning they switch on when the pin is low and off whwn the pin goes hi.

      When you set the pin as output, it defaults to low, switching you relay on.
      If you write the input high, the relay turns off. if you do this striaght away the relay never turns on
      When you switch back to input it stops driving the pin so the relay turns off anyway.

  9. Hi,

    I just wrote a short PWM program and couldn’t make it work on an up-to-date version of Raspbian (I did spot the deprecated name ‘wiringpi2’ in favour of ‘wiringpi’ mentioned in the comments).

    I then ran the example code from the article and got exactly the same problem. In the IDLE debugger the software freezes at the line ‘wiringpi.wiringPiSetupGpio()’. Any ideas?

    I’ve previously had wiringpi2 running on an earlier version of Raspbian.

  10. Does wiringpi for python support SPI API?

  11. Hi,
    I am working on an adc for which I want to use the clk on the gpio pin 7 of raspberry pi. Can you help me with achieving this? I tried with the Rpi.gpio but it gives an error about the ALT0.

Leave a Reply