WiringPython - WiringPi for Python


206 posts   Page 1 of 9   1, 2, 3, 4, 5 ... 9
by gadgetoid » Mon Jul 02, 2012 12:32 pm
First and foremost, a million and one thanks to Gordon for doing all the hard work and producing WiringPi in the first place. You can learn more about it here: https://projects.drogon.net/raspberry-pi/wiringpi/

Not knowing if anyone had done it before, I decided to wrap up WiringPi for Python. Unfortunately I'm not a Python programmer, and thus am not best positioned for actually testing the result.

More Python literate folks, however, are free to grab WiringPython from GitHub: https://github.com/Gadgetoid/WiringPython

And let me know if anything goes awry!

Currently, as per WiringPi itself, you will need to run your Python script as root and be sure to call wiringpi.wiringPiSetup() before attempting to use the other functions.
Posts: 75
Joined: Wed Mar 07, 2012 9:58 pm
by texy » Mon Jul 02, 2012 8:10 pm
Hi
So this is an alternative for RPi.GPIO?
Any python examples?
Thanks
Texy
"2.8inch TFT LCD + Touch screen" add-on boards for sale here :
http://www.raspberrypi.org/phpBB3/viewtopic.php?f=93&t=65566
50p goes to the Foundation ;-)
Forum Moderator
Forum Moderator
Posts: 2458
Joined: Sat Mar 03, 2012 10:59 am
Location: Berkshire, England
by gadgetoid » Tue Jul 03, 2012 8:03 am
Wasn't aware of RPi.GPIO before. I don't know if it has shiftOut or serial functions? WiringPython does.

I'll endeavour to produce examples, but since I'm no Python developer they may not be particularly good.

Generally you would:

import wiringpi
wiringpi.wiringPiSetup

IO:
wiringpi.pinMode(1,1) // Set pin 1 to output
wiringpi.digitalWrite(1,1) // Write 1 HIGH to pin 1
wiringpi.digitalRead(1) // Read pin 1

Bit shifting:
wiringpi.shiftOut(1,2,0,123) // Shift out 123 to data pin 1, clock pin 2

Serial:
serial = wiringpi.serialOpen('/dev/ttyAMA0',9600)
wiringpi.serialClose(serial)
Posts: 75
Joined: Wed Mar 07, 2012 9:58 pm
by texy » Tue Jul 03, 2012 8:32 am
Looks good - the bit shifting function would be especially useful. Does the driver access the GPIO via /sys/class/gpio/... files?
Please see this thread -
viewtopic.php?f=32&t=9977

Texy
"2.8inch TFT LCD + Touch screen" add-on boards for sale here :
http://www.raspberrypi.org/phpBB3/viewtopic.php?f=93&t=65566
50p goes to the Foundation ;-)
Forum Moderator
Forum Moderator
Posts: 2458
Joined: Sat Mar 03, 2012 10:59 am
Location: Berkshire, England
by gadgetoid » Tue Jul 03, 2012 8:47 am
At the moment, no. It's based on Gordon's WiringPi which accesses the GPIO via shared memory or some trickery like that.

I believe a /sys/class/gpio version of the underlying library is coming, but I'm not sure when. When it does, it will be added into WiringPython and WiringPiGem.
Posts: 75
Joined: Wed Mar 07, 2012 9:58 pm
by texy » Tue Jul 03, 2012 8:53 am
It seems the /sys/class/gpio method is somewhat slow as it needs to open and close a file every time it accesses one of the gpio lines. Therefore
using the shared memory trickery may be the quickest method. There may be other reasons why its the safest method though.....
Texy
"2.8inch TFT LCD + Touch screen" add-on boards for sale here :
http://www.raspberrypi.org/phpBB3/viewtopic.php?f=93&t=65566
50p goes to the Foundation ;-)
Forum Moderator
Forum Moderator
Posts: 2458
Joined: Sat Mar 03, 2012 10:59 am
Location: Berkshire, England
by gadgetoid » Tue Jul 03, 2012 11:40 am
I'd often assumed /sys/class/gpio to be slow, which is why I haven't explored it in any depth. I get stupendous performance out of the shared-memory mode in C, but obviously using it in Ruby incurs a penalty.

So, whilst shared memory may be faster, it may not necessarily make a difference if the bottleneck is your interpreted language.

I'm not too bothered about running things as root, most of what I do will be inconsequential GPIO tinkering, but I understand why some are.

The ultimate goal is to have both methods available for the user to choose at their discretion depending on whether they favour speed or security.

If anyone wants to benchmark RPi.GPIO and wiringpi in Python, I'd be very interested to see the results.
Posts: 75
Joined: Wed Mar 07, 2012 9:58 pm
by MadCow42 » Tue Jul 03, 2012 12:07 pm
gadgetoid wrote:I'd often assumed /sys/class/gpio to be slow, which is why I haven't explored it in any depth. I get stupendous performance out of the shared-memory mode in C, but obviously using it in Ruby incurs a penalty.

So, whilst shared memory may be faster, it may not necessarily make a difference if the bottleneck is your interpreted language.

I'm not too bothered about running things as root, most of what I do will be inconsequential GPIO tinkering, but I understand why some are.

The ultimate goal is to have both methods available for the user to choose at their discretion depending on whether they favour speed or security.

If anyone wants to benchmark RPi.GPIO and wiringpi in Python, I'd be very interested to see the results.


Just FYI, I've been tinkering with RPi.GPIO for speed improvements - at least for output - and have managed about a 10x improvement on the standard setup by simply holding the files open for multiple writes, instead of opening/closing them for each write (you need to .flush() of course). There's another thread on this forum about GPIO speed where I've posted a link to a quick class that handles this. The RPi.GPIO author is also working on improvements by trying to directly control the registers instead of going through files, but that's longer term work.

Kevin.
Posts: 86
Joined: Sun Jul 01, 2012 12:48 am
by gadgetoid » Tue Jul 03, 2012 12:37 pm
MadCow42 wrote:Just FYI, I've been tinkering with RPi.GPIO for speed improvements - at least for output - and have managed about a 10x improvement on the standard setup by simply holding the files open for multiple writes, instead of opening/closing them for each write (you need to .flush() of course).


That's a clever and logical approach. How particular is the speed improvement to your use-case?

MadCow42 wrote:There's another thread on this forum about GPIO speed where I've posted a link to a quick class that handles this. The RPi.GPIO author is also working on improvements by trying to directly control the registers instead of going through files, but that's longer term work.


As far as I understand it, the problem with direct control is that the system wont allow it until we get ( and I might be talking nonsense here!) a driver in the kernel which exposes these things to userspace somehow. Once that happens, it'd be pretty trivial to make use of it and gain what would, hopefully, be the best of both worlds.

I'll have to look up these threads and learn things!
Posts: 75
Joined: Wed Mar 07, 2012 9:58 pm
by MadCow42 » Tue Jul 03, 2012 12:57 pm
gadgetoid wrote:That's a clever and logical approach. How particular is the speed improvement to your use-case?


It's a pretty general improvement for any high-speed writes. My 10x figure was simply comparing 10000 sequential writes to the same pin (True, False...). I'm using the Pi to drive stepper motors through an 8-bit shift register (about 25 GPIO operations per step... but I'm also changing that approach to reduce it), so I needed faster speed than I was getting with the standard output method.

See: www.cazabon.com/temp/GPIO_OUT_class.py

Kevin.
Posts: 86
Joined: Sun Jul 01, 2012 12:48 am
by gadgetoid » Tue Jul 03, 2012 1:26 pm
Nice work. I found your other thread, hacked up that script, and posted a benchmark that includes WiringPython.

If you don't mind running as root, there's no contest.

If you ever get the chance to give WiringPython a try in your real-world use case, I'd love to know how it fares. For raw performance it appears better, but it's not a well constructed or particularly friendly class.

I need to take a leaf from RPi.GPIO's book and add some constants for HIGH/LOW INPUT/OUTPUT/PWM_OUT plus LSB_FIRST and MSB_FIRST for ShiftOut. I'm presently not sure how to go about that, though!
Posts: 75
Joined: Wed Mar 07, 2012 9:58 pm
by MadCow42 » Tue Jul 03, 2012 1:58 pm
gadgetoid wrote:If you ever get the chance to give WiringPython a try in your real-world use case, I'd love to know how it fares. For raw performance it appears better, but it's not a well constructed or particularly friendly class.


I'm just driving LEDs for the moment - the rest of the IC's I need aren't arriving until later this week. But, I should be driving the steppers in real life by next week sometime. I don't need the 50kHz performance that your example achieved for my application, but it would allow me more precise/consistent timing of my stepping, as well as more room for overhead. I'd probably end up writing a wrapper so that I could use either method with the same calls. I'll let you know!

Thanks for the input and info!
Kevin.
Posts: 86
Joined: Sun Jul 01, 2012 12:48 am
by texy » Tue Jul 03, 2012 9:16 pm
gadgetoid wrote:First and foremost, a million and one thanks to Gordon for doing all the hard work and producing WiringPi in the first place. You can learn more about it here: https://projects.drogon.net/raspberry-pi/wiringpi/

Not knowing if anyone had done it before, I decided to wrap up WiringPi for Python. Unfortunately I'm not a Python programmer, and thus am not best positioned for actually testing the result.

More Python literate folks, however, are free to grab WiringPython from GitHub: https://github.com/Gadgetoid/WiringPython

And let me know if anything goes awry!

Currently, as per WiringPi itself, you will need to run your Python script as root and be sure to call wiringpi.wiringPiSetup() before attempting to use the other functions.



Run out of time now, but I can't seem to download from github. I can view each of the files, but it wont let me download a zip or tar.gz file, ie all in one go?
It'll be very painful indeed to view each as raw, then save etc.
So I try and download from my windows laptop, so still problems.
Is there a CLI command to download the zip ?
Texy
"2.8inch TFT LCD + Touch screen" add-on boards for sale here :
http://www.raspberrypi.org/phpBB3/viewtopic.php?f=93&t=65566
50p goes to the Foundation ;-)
Forum Moderator
Forum Moderator
Posts: 2458
Joined: Sat Mar 03, 2012 10:59 am
Location: Berkshire, England
by gadgetoid » Wed Jul 04, 2012 7:51 am
I pushed the zip into my Dropbox, see if you can get it from there: http://db.tt/3R4UQ7WO

Alternatively you could install git and grab the files with "git clone https://github.com/Gadgetoid/WiringPython.git"
Posts: 75
Joined: Wed Mar 07, 2012 9:58 pm
by Hartspoon » Fri Jul 06, 2012 1:45 am
You say here and on the benchmark thread that your solution has to be run as root, and therefore, sacrifices security. But on the eLinux wiki, it's written that any python script willing to control GPIO has to be run as root, and this includes the RPi.CPIO module.

Plus, there is a stand-alone version of WiringPi that allows you to control GPIO as a normal user! So the wiki is apparently wrong about that point, or at least missing something.

Maybe I'm missing something. Maybe the security problem is somewhere else and not on the root privileges, or the wiki's wrong about the necessity of having these privileges to control GPIO (spoiler alert: it seems to be), but if it isn't, it seems that your wrapper and WiringPi can be both fast and safe, or at least as safe as RPi.GPIO.

I haven't tried anything for now, but I'll do tomorrow.

Gordon Henderson's post about WiringPi and the stand-alone version: https://projects.drogon.net/raspberry-pi/wiringpi/
The wiki section mentioning Python, RPi.GPIO, GPIO and root: http://elinux.org/Rpi_Low-level_periphe ... 8Python.29
Posts: 4
Joined: Thu Jul 05, 2012 12:20 am
by texy » Fri Jul 06, 2012 8:22 am
Finally got some time to play with wiringpi, but failed at the first hurdle - I cannot install it !
It cannot find Python.h
I have tried a 'find / -name Python.h' .....and it is nowhere to be found on my system :?:

What am I doing wrong, or are the instructions somewhat incomplete (for a newbe) ?

Texy
"2.8inch TFT LCD + Touch screen" add-on boards for sale here :
http://www.raspberrypi.org/phpBB3/viewtopic.php?f=93&t=65566
50p goes to the Foundation ;-)
Forum Moderator
Forum Moderator
Posts: 2458
Joined: Sat Mar 03, 2012 10:59 am
Location: Berkshire, England
by gadgetoid » Fri Jul 06, 2012 12:19 pm
texy wrote:Finally got some time to play with wiringpi, but failed at the first hurdle - I cannot install it !
It cannot find Python.h
I have tried a 'find / -name Python.h' .....and it is nowhere to be found on my system :?:

What am I doing wrong, or are the instructions somewhat incomplete (for a newbe) ?

Texy


You should probably "apt-get install python-dev"

I'll put that in the guide if it works for you. I've installed so many dev libraries that I forget these things don't normally work out of the box!

I've just updated the repo with some new fixes, after getting feedback on my wiringPiGem. There were some problems with the horrible auto-generated bindings ( I'd hand write them if I knew enough C! ) which I was able to track down to the old version of SWIG I was using. I've since updated to 2.0.7 and regenerated them.
Posts: 75
Joined: Wed Mar 07, 2012 9:58 pm
by gadgetoid » Fri Jul 06, 2012 12:25 pm
Hartspoon wrote:But on the eLinux wiki, it's written that any python script willing to control GPIO has to be run as root, and this includes the RPi.CPIO module.


This is not generally true, and WiringPython will ultimately not require root when the latest updates from Gordon are merged in.

What RPi.GPIO is doing, is exporting the /sys/class/gpio interface for you. This sets a GPIO pin to be either input/output and makes it accessible to the average user. Root is required to do this, but is not required to read/write to it.

Gordon has added functionality to his gpio binary that will let you export the /sys/class/gpio interfaces you need before running your script, you could do this with a shell script as root for example.

This means that the script, if it uses the future version of WiringPython which will not do the exports for you, will be able to run without root.

There's no reason why RPi.GPIO couldn't implement similar functionality and prompt you to export the necessary interfaces before running your Python script. Once exported, I believe the pins are available in userland in the chosen mode until you reboot; so if you use specific pins in specific ways you could even write a script to do this at startup.
Posts: 75
Joined: Wed Mar 07, 2012 9:58 pm
by canyon » Fri Jul 06, 2012 2:28 pm
@texy, @gadgetoid:
I had the same problem: I've just installed python-dev as gadgetoid suggested, and wiringpi.py is now there. I haven't had a chance to play with it yet, it seems to import successfully:
>>> import wiringpi
>>> wiringpi
<module 'wiringpi' from 'wiringpi.py'>
>>>

Thanks!
Posts: 31
Joined: Sun Jan 29, 2012 9:47 am
by texy » Sat Jul 07, 2012 9:54 am
Hi,
just to confirm, yes I needed to install python-dev as well.
I have a problem however. I am not able to switch an LED, using the following code:

Code: Select all
#!/usr/bin/python
# -*- coding: utf-8 -*-
import wiringpi
import time

def main():
    wiringpi.wiringPiSetup()
    wiringpi.pinMode(17, 1)
    for i in range(5):
        wiringpi.digitalWrite(17, 0)
        time.sleep(1)
        wiringpi.digitalWrite(17, 1)
        time.sleep(1)

if __name__ == "__main__":
  main()


The program runs without error, but does not switch on or off the LED which is connected to physical pin 11. Note I have tried both 17 and 11 in the above program. Similair code is working fine for the conventional RPi.GPIO method.
Any idea's?

T.
"2.8inch TFT LCD + Touch screen" add-on boards for sale here :
http://www.raspberrypi.org/phpBB3/viewtopic.php?f=93&t=65566
50p goes to the Foundation ;-)
Forum Moderator
Forum Moderator
Posts: 2458
Joined: Sat Mar 03, 2012 10:59 am
Location: Berkshire, England
by gadgetoid » Sat Jul 07, 2012 2:31 pm
It could be something to do with the different pin numberings. Try pin 0 instead of pin 17.

Gordon's pin mappings are here: https://projects.drogon.net/raspberry-pi/wiringpi/pins/

You might be able to use:

wiringpi.wiringPiGpioMode(1)

To switch it into a more familiar (GPIO) pin numbering mode.

Sorry about the complete and total lack of documentation. I'll thoroughly test and document it soon, but at the moment I'm strapped for time!
Posts: 75
Joined: Wed Mar 07, 2012 9:58 pm
by texy » Sat Jul 07, 2012 3:00 pm
Brilliant!
Using '0' is working, and also using '17' with
wiringpi.wiringPiGpioMode(1)
is behaving as it should do ;)

I have also converted my pcd8544 LCD program to using wiringpi and the time as gone down to 0.322 seconds.
The next thing to tackle is using the ShiftOut feature. I assume the '0' in the example above relates to lsb first rather than msb?

Texy
"2.8inch TFT LCD + Touch screen" add-on boards for sale here :
http://www.raspberrypi.org/phpBB3/viewtopic.php?f=93&t=65566
50p goes to the Foundation ;-)
Forum Moderator
Forum Moderator
Posts: 2458
Joined: Sat Mar 03, 2012 10:59 am
Location: Berkshire, England
by gadgetoid » Sat Jul 07, 2012 3:10 pm
Great news that it works!

Aye, LSBFIRST = 0, MSBFIRST = 1.

I'm hoping to include a .py wrapper which will have constants for these.

Good luck with shiftOut, I'm eager to learn how all these things are done in Python specifically. I've already written a helper for Ruby which shifts out an arbitrary length array of 1s and 0s, and I'd like to port it.
Posts: 75
Joined: Wed Mar 07, 2012 9:58 pm
by texy » Sun Jul 08, 2012 9:53 am
Hi,
I would expect this code :
Code: Select all
def SPI(c):
  # data = DIN
  # clock = SCLK
  # MSB first
  # value = c
  for i in xrange(8):
    wiringpi.digitalWrite(DIN,((c & (1 << (7-i))) > 0))
    wiringpi.digitalWrite(SCLK, 1)
    wiringpi.digitalWrite(SCLK, 0)


to be replaced with
Code: Select all
def SPI(c):
  # data = DIN
  # clock = SCLK
  # MSB first
  # value = c
  wiringpi.shiftOut(DIN, SCLK, 1, c)


...but I get a blank screen.
Any idea's ?
Incidently, the time is now down to 0.125 seconds !
T.
"2.8inch TFT LCD + Touch screen" add-on boards for sale here :
http://www.raspberrypi.org/phpBB3/viewtopic.php?f=93&t=65566
50p goes to the Foundation ;-)
Forum Moderator
Forum Moderator
Posts: 2458
Joined: Sat Mar 03, 2012 10:59 am
Location: Berkshire, England
by gadgetoid » Sun Jul 08, 2012 10:39 am
It looks right. Have you hooked up anything to the Data pin to see if it's toggling as expected?

You can see the inner-workings of shiftOut here: https://github.com/Gadgetoid/WiringPi/b ... ingShift.c

It could very well be that shiftOut is borked in WiringPython due to discrepancies between data-types in Python and C.

I applied a patch to the bindings setup file in Ruby which makes shiftOut work, but might cause problems in Python. Namely: "%apply unsigned char { uint8_t };"

What's the content of your Value?

I'll have to find the time to put together my own tests and see if I can make things work.
Posts: 75
Joined: Wed Mar 07, 2012 9:58 pm