BerryPicker
Posts: 177
Joined: Tue Oct 16, 2012 3:03 pm
Location: The East of England

Re: RPIO: An extension of RPi.GPIO with interrupt management

Mon Mar 11, 2013 1:23 pm

metachris wrote:I will implement that.
I look forward to it. If holding off change notification is to become the built-in RPIO switch bounce strategy, it might help understanding if you included in the documentation an example to clarify proper usage. May I suggest that RPIO.add_interrupt_callback provides the 'delayed one shot' function, to flag as an interrupt the change of edge(s), but that it is left to Python code to double check what's happened by 'read input from gpio' as required. This is the way I would usually have software cope with a button pusher or switch flipper trying to break the expected operation.

sej7278
Posts: 249
Joined: Tue Jan 22, 2013 6:43 pm

Re: RPIO: An extension of RPi.GPIO with interrupt management

Mon Mar 11, 2013 5:13 pm

any chance we can get this merged into gpio, or at least packaged into a .deb so it could eventually get into the raspbian repo's?

User avatar
metachris
Posts: 96
Joined: Wed Feb 06, 2013 1:52 pm
Location: Vienna, Austria

Re: RPIO: An extension of RPi.GPIO with interrupt management

Tue Mar 12, 2013 2:00 am

What I can do now is to add .deb packages to the RPIO build toolchain, to produce them with every release. See where it goes from there; I'm open to suggestions.
pythonhosted.org/RPIO

sej7278
Posts: 249
Joined: Tue Jan 22, 2013 6:43 pm

Re: RPIO: An extension of RPi.GPIO with interrupt management

Tue Mar 12, 2013 9:31 am

metachris wrote:What I can do now is to add .deb packages to the RPIO build toolchain, to produce them with every release. See where it goes from there; I'm open to suggestions.
lovely. i did have a go at packaging it myself last night but failed miserably using py2dsc, i guess because it contains elements of C too it needs to be packaged in the normal way.

edit: i tried using dh_make and debuild like the regular GPIO package, it seemed to build all the .so's etc. but the package ends up just containing the docs and not the binaries lol!

also there's an unused py_set_pullupdn() function at line 304 of source/c_gpio/py_gpio.c that needs removing before it will even compile and README.rst needs to be added to the includes in MANIFEST.in

sej7278
Posts: 249
Joined: Tue Jan 22, 2013 6:43 pm

Re: RPIO: An extension of RPi.GPIO with interrupt management

Wed Mar 13, 2013 4:47 pm

any chance of getting 0.9.5 debs, i still can't get them to build even with your debian files!

this is really starting to look more useful than the regular GPIO module, although i'm not 100% sure of using try/finally instead of an if statement or while loop and how to cleanup afterwards, i'm thinking of something like this:

Code: Select all

#!/usr/bin/env python

import RPIO
from threading import Thread
from time import sleep

Thread(target=RPIO.wait_for_interrupts).start()

def gpio_callback():
    """callback routing from gpio input4"""
    print "button pressed"

try:
    RPIO.setmode(RPIO.BCM)
    RPIO.setup(4, RPIO.IN)
    RPIO.add_interrupt_callback(4, gpio_callback, edge='rising', debounce_timeout_ms=20)

    while 1:
        # do my stuff that needs to be in a loop, call the callback and return to the loop
        ...
        sleep(1)

finally:
    RPIO.stop_waiting_for_interrupts()
    RPIO.cleanup()

User avatar
metachris
Posts: 96
Joined: Wed Feb 06, 2013 1:52 pm
Location: Vienna, Austria

Re: RPIO: An extension of RPi.GPIO with interrupt management

Wed Mar 13, 2013 8:07 pm

I'm just running the latests tests right now; RPIO 0.9.5 will be out within the hour; i'll post here when its available. Your code looks good I think; you can replace the Thread with `RPIO.wait_for_interrupts(threaded=True)`, and you don't need to call setmode(BCM) since that's already done by default.

I'll spend some more thought on the shutdown procedures...
pythonhosted.org/RPIO

User avatar
metachris
Posts: 96
Joined: Wed Feb 06, 2013 1:52 pm
Location: Vienna, Austria

Re: RPIO: An extension of RPi.GPIO with interrupt management

Wed Mar 13, 2013 8:54 pm

I've just added a few bugfixes, and released RPIO 0.9.6! This is what changed:
  • Added ``debounce_timeout_ms`` argument to ``RPIO.add_interrupt_callback(..)``
  • Added ``threaded`` argument to ``RPIO.wait_for_interrupts(..)``
  • Interrupt callbacks now receive integer values ``0`` or ``1`` instead of strings
  • Interrupt callbacks with edge=``rising`` or ``falling`` only receive the correct values
  • Added ``RPIO.close_tcp_client(fileno)``
  • Debian .deb packages
  • License changed to GNU Lesser General Public License v3 or later (LGPLv3+)
Install/update RPIO with easy_install for Python 2.x:

Code: Select all

$ sudo easy_install -U RPIO
For Python 3.x:

Code: Select all

$ sudo easy_install3 -U RPIO
Debian packages are available at http://metachris.github.com/rpio/download/latest. You can install them with `sudo dpkg -i python-rpio_0.9.6_armhf.deb`. Links:
Feedback is much appreciated!
pythonhosted.org/RPIO

sej7278
Posts: 249
Joined: Tue Jan 22, 2013 6:43 pm

Re: RPIO: An extension of RPi.GPIO with interrupt management

Wed Mar 13, 2013 9:54 pm

the debouncing stuff seems to help a bit, really i think i need to buy some better switches though, as sometimes it works fine, other times it goes high-low-high no matter what the debouncing is set to (10/20/50/100ms) that might also be down to the speed of the pi too i guess, as it appears to fix itself if you leave it for a couple of seconds before pressing the switch again (or press the switch harder!)

rpio-curses is useful for when you don't want a bunch of print statements in your code

my momentary spst switches (i've tried 3 of the same type):
spst.jpg
spst.jpg (3.38 KiB) Viewed 3425 times

User avatar
metachris
Posts: 96
Joined: Wed Feb 06, 2013 1:52 pm
Location: Vienna, Austria

Re: RPIO: An extension of RPi.GPIO with interrupt management

Wed Mar 13, 2013 10:59 pm

By the way, this is the code you posted before how I'd write it with the current RPIO 0.9.6:

Code: Select all

import RPIO
from time import sleep

def gpio_callback(gpio, val):
    """callback routing from gpio input4"""
    print "button pressed"

RPIO.add_interrupt_callback(4, gpio_callback, edge='rising', debounce_timeout_ms=20)
RPIO.wait_for_interrupts(threaded=True)

try:
    while 1:
        # do my stuff that needs to be in a loop, call the callback and return to the loop
        ...
        sleep(1)

finally:
    RPIO.stop_waiting_for_interrupts()
    RPIO.cleanup()
Edit: next thing i'm going add is auto-shutdown of RPIO when the script is done, in order to not having to have the finally block in the above example.
pythonhosted.org/RPIO

sej7278
Posts: 249
Joined: Tue Jan 22, 2013 6:43 pm

Re: RPIO: An extension of RPi.GPIO with interrupt management

Thu Mar 14, 2013 12:59 am

metachris wrote:By the way, this is the code you posted before how I'd write it with the current RPIO 0.9.6:
...
Edit: next thing i'm going add is auto-shutdown of RPIO when the script is done, in order to not having to have the finally block in the above example.
here's my full code with your changes taken into account, essentially when you press the button it pauses or plays the music. i've still got the lcd code using GPIO, i guess its fine to mix it using a different namespace.

at the moment i've not got it running as a daemon, so have to ctrl-c or kill the process, which means gpio isn't tidied up, but i can't see how you'd deal with auto-shutdown in that case. i'm not so keen on the try...finally bit myself either.

are you forking the main GPIO code or merging in changes, as 0.9.7 seems to be based on old 0.4.2a code, is there nothing to be gained in moving to 0.5.0a?

Code: Select all

#!/usr/bin/env python

# import modules
from subprocess import *
from time import *
from hd44780 import hd44780
import RPIO
   
def gpio_callback(gpio_id, val):
    """callback routing from gpio input4"""
    call(["mpc", "-q", "toggle"])


# add rising edge callback to gpio4 input
RPIO.setup(4, RPIO.IN)
RPIO.add_interrupt_callback(4, gpio_callback, edge='rising', debounce_timeout_ms=100)
RPIO.wait_for_interrupts(threaded=True)

# always start playing as soon as we load
call(["mpc", "-q", "play"])

# initialise lcd
lcd = hd44780()
prev_lcdtext = ''

# main program loop
try:
    while 1:
        # get current status
        p = Popen(["mpc", "current"], stdout=PIPE)
        current = p.communicate()[0]
        if current:
            # playing - print mp3 as band/track, or print station
            lcd_text = current.rstrip().replace(' - ', '\n', 1)
        else:
            # stopped - print date/time
            lcd_text = strftime('%a %d %b %H:%M',localtime())
            lcd_text += '\nRaspberry Radio!'

        # update lcd if new track or time
        if lcd_text != prev_lcdtext:
            lcd.message(lcd_text)

        prev_lcdtext = lcd_text

        # pause to reduce load/flicker
        sleep(1)
        
finally:
    # reset gpio
    RPIO.stop_waiting_for_interrupts()
    RPIO.cleanup()

User avatar
metachris
Posts: 96
Joined: Wed Feb 06, 2013 1:52 pm
Location: Vienna, Austria

Re: RPIO: An extension of RPi.GPIO with interrupt management

Thu Mar 14, 2013 1:05 am

Ah great you mention the daemon. If you kill it with a signal, the finally block isn't executed anyway. But it does not really matter, since the call to cleanup is optional (ie. no harm done when not calling it). The stop_waiting_for_interrupts() call is also unnecessary since it just stops the epoll thread, which the kill itself takes care of too. So you can safely remove the whole try..finally block :) (edit: in case you quit with Ctrl+C, the epoll-thread keeps running because stop_waiting_for_interrupts(..) has not been called. RPIO 0.9.7 (coming tomorrow) automatically shuts it down when the script exits).

Re RPi.GPIO 0.5.0: nothing to be gained from this release; it's essentially just the new (not yet fully working) interrupt methods. I'm always willing to merge useful changes into RPIO, and am communicating ideas and suggestions for the other way as well.
pythonhosted.org/RPIO

User avatar
metachris
Posts: 96
Joined: Wed Feb 06, 2013 1:52 pm
Location: Vienna, Austria

Re: RPIO: An extension of RPi.GPIO with interrupt management

Thu Mar 14, 2013 3:11 pm

I've just released RPIO v0.10.0 with the following updates:
  • Auto-cleanup on exit (also shuts down RPIO.wait_for_interrupts(threaded=True))
  • Bugfix in cpuinfo.c: correctly trim over-voltage header
  • rpio-curses: help shows raspberry sysinfo
  • switched argument ordering of wait_for_interrupts to (wait_for_interrupts(threaded=False, epoll_timeout=1))
  • Added RPIO.Exceptions (list of C GPIO exceptions)
The most significant change is that all interrupt interfaces are shut down automatically by RPIO, there is no need to call cleanup_interrupts(..) manually anymore. If 'wait_for_interrupts(threaded=True)' is running, this thread will automatically quit if your main script quits.

You can install and/or update RPIO as usual with easy_install like this:

Code: Select all

$ sudo easy_install -U RPIO
Alternatively you can use 'pip', or 'dpkg' with the debian packages.
As always, feedback is much appreciated!
pythonhosted.org/RPIO

User avatar
metachris
Posts: 96
Joined: Wed Feb 06, 2013 1:52 pm
Location: Vienna, Austria

Re: RPIO: An extension of RPi.GPIO with interrupts, PWM and

Thu Mar 14, 2013 3:15 pm

Re sedj7278: with RPIO 0.10.0, you can write the code like this:

Code: Select all

import RPIO
from time import sleep

def gpio_callback(gpio, val):
    """callback routing from gpio input4"""
    print "button pressed"

RPIO.wait_for_interrupts(threaded=True)
RPIO.add_interrupt_callback(4, gpio_callback, edge='rising', debounce_timeout_ms=20)

while 1:
    # do my stuff that needs to be in a loop, call the callback and return to the loop
    ...
    sleep(1)
pythonhosted.org/RPIO

sej7278
Posts: 249
Joined: Tue Jan 22, 2013 6:43 pm

Re: RPIO: An extension of RPi.GPIO with interrupts, PWM and

Thu Mar 14, 2013 6:18 pm

metachris wrote:Re sedj7278: with RPIO 0.10.0, you can write the code like this:
yup, that's what i came up with, its all working fine now with 0.10.0, interestingly it took a timeout of 200ms to get the switch 100% reliable (confirmed here where it says 157ms) i thought for some reason the maximum was 100, but looking at the code its just n/1000

next up i've got to figure out how to do something else on a long-press of the same button!

User avatar
metachris
Posts: 96
Joined: Wed Feb 06, 2013 1:52 pm
Location: Vienna, Austria

Re: RPIO: An extension of RPi.GPIO with interrupts, PWM and

Thu Mar 14, 2013 6:24 pm

Glad it's working for you! I don't see any debounce issues on my circuits when I use a proper pullup or -down resistor. If you are sure your wiring is correct (eg. like in this example), and you've double checked that no cold soldier points exist, the conclusion would be that the buttons are indeed causing the problems (in which case the question is whether to workaround the buttons restrictions or to get better buttons : ).
pythonhosted.org/RPIO

sej7278
Posts: 249
Joined: Tue Jan 22, 2013 6:43 pm

Re: RPIO: An extension of RPi.GPIO with interrupts, PWM and

Thu Mar 14, 2013 7:20 pm

metachris wrote:Glad it's working for you! I don't see any debounce issues on my circuits when I use a proper pullup or -down resistor. If you are sure your wiring is correct (eg. like in this example), and you've double checked that no cold soldier points exist, the conclusion would be that the buttons are indeed causing the problems (in which case the question is whether to workaround the buttons restrictions or to get better buttons : ).
the linked site proves the buttons are a bit naff, also i'm not using a pull-up (or rc circuit) due to using the voltage-divider, but as i recall i didn't have issues when using the 10k pull-up.

i've got long-press working now btw:

Code: Select all

def gpio_callback(gpio_id, val):
    """hold gpio4 to stop or press to play/pause"""
    call(["mpc", "-q", "toggle"])
    sleep(0.5)
    if RPIO.input(4):
        call(["mpc", "-q", "stop"])

joshmosh
Posts: 62
Joined: Fri Aug 03, 2012 12:04 pm

Re: RPIO: An extension of RPi.GPIO with interrupts, PWM and

Tue Mar 19, 2013 9:30 am

Hi Chris,
it has been quiet on this topic for a while, so I will take the chance to chip in ;)
With version 0.10 I am back in the game, because with the new features you have included, it fits very well to my requirements. The core of my project is now working, based on your RPIO - thanks a lot.

I have a suggestion for an (in my view) improvement and a question.
The question: how would I include timer events as callbacks ? I would like to integrate routines that are called at a certain time, very similar to cronjobs, but integrated in my server program. You have already included TCP callbacks, which - at least for me - is very useful.

The suggestion: currently I need to run my Python code with root privileges. I know that this cannot be avoided, because of the access to the GPIO pins. But perhaps the part which requires root privileges can be sort of isolated ? In the MagPpi magazine issue 7 there is an article dealing with GPIO. The author has written a small program in C that exports or imports GPIO pins and this of course requires root privileges. But all other handling can be done with standard user logins.
Perhaps something to think about ?

Again, thank you for the additional features you have added - it makes RPIO a real useful tool for me !

Please keep up the good work.

Cheers
Josh

sej7278
Posts: 249
Joined: Tue Jan 22, 2013 6:43 pm

Re: RPIO: An extension of RPi.GPIO with interrupts, PWM and

Tue Mar 19, 2013 12:27 pm

joshmosh wrote:The suggestion: currently I need to run my Python code with root privileges. I know that this cannot be avoided, because of the access to the GPIO pins. But perhaps the part which requires root privileges can be sort of isolated ? In the MagPpi magazine issue 7 there is an article dealing with GPIO. The author has written a small program in C that exports or imports GPIO pins and this of course requires root privileges. But all other handling can be done with standard user logins.
really though, all you could do with gpio's without root would be reading from them.

you most certainly should never be allowed to set them up or write to them as a regular user and the magpi script is just using setuid, so i don't see the point really.

if you're worried about running as root, then either setuid your program or setup sudoers carefully.

User avatar
jojopi
Posts: 3085
Joined: Tue Oct 11, 2011 8:38 pm

Re: RPIO: An extension of RPi.GPIO with interrupts, PWM and

Tue Mar 19, 2013 1:01 pm

sej7278 wrote:really though, all you could do with gpio's without root would be reading from them.
With the kernel /sys/class/gpio interface, you can give a user or group read or write access to specific GPIO pins. It is just unfortunate that some libraries insist on direct access to the hardware registers instead, and have given little thought to privilege delegation themselves.

joshmosh
Posts: 62
Joined: Fri Aug 03, 2012 12:04 pm

Re: RPIO: An extension of RPi.GPIO with interrupts, PWM and

Tue Mar 19, 2013 2:16 pm

sej7278 wrote:
joshmosh wrote:The suggestion: currently I need to run my Python code with root privileges. I know that this cannot be avoided, because of the access to the GPIO pins. But perhaps the part which requires root privileges can be sort of isolated ? In the MagPpi magazine issue 7 there is an article dealing with GPIO. The author has written a small program in C that exports or imports GPIO pins and this of course requires root privileges. But all other handling can be done with standard user logins.
really though, all you could do with gpio's without root would be reading from them.

you most certainly should never be allowed to set them up or write to them as a regular user and the magpi script is just using setuid, so i don't see the point really.

if you're worried about running as root, then either setuid your program or setup sudoers carefully.
My point is that the only piece of code in the magpi example is pretty small and not too complex, so the chance that it runs havoc is minimal. It is only used to export or unexport pins, nothing else. After having exported a pin, you can read and (!) write these (and only these) exported pin as standard user. If this user program does evil things, potential harm is limited.
I am worried about running as root because I want to protect the system from myself and my bad code ;), not against attacks from the outside.

Josh

dauhee
Posts: 59
Joined: Fri Sep 07, 2012 1:50 pm

Re: RPIO: An extension of RPi.GPIO with interrupts, PWM and

Wed Mar 20, 2013 9:30 pm

yes timer event callbacks would be fantastic. it would enable me to use RPIO as the framework for my application. This library has saved me so much work already !!!!

pzc
Posts: 5
Joined: Sat Aug 18, 2012 4:36 pm

Re: RPIO: An extension of RPi.GPIO with interrupts, PWM and

Sun Mar 24, 2013 6:11 pm

Hi Chris,
Great job on RPIO!
I have my RPi connected to a Gertboard and I'm using it to create a (Knight Rider) KITT-like chasing dot pattern on the LEDs.
I'm using your PWM function to modulate the LED brightness in an attempt to replicate 'bulbs' (with slow on and slow off) rather than the instant on-off of the LEDs.
I get weird results when I try to write an individual PWM waveform to each of the 12 LEDs. All the LEDs seem to follow the waveform written to the last LED instead of their own waveform...
Maybe I'm taking RPIO into unchartered territory?! ("Here there be dragons")
Many thanks in advance for any help you can offer...

Code: Select all

# Produce a KITT-like display on the Gertboard LEDs

# Install all 12 "out" links on the Gertboard
# Connect:
#   GP7-B12
#   GP8-B11
#   GP9-B10
#   GP10-B9
#   GP11-B8
#   GP17-B7
#   GP18-B6
#   GP27-B5
#   GP22-B4
#   GP23-B3
#   GP24-B2
#   GP25-B1


from RPIO import PWM
from time import sleep
import numpy as np

try:
    # define the list of ports for the Gertboard
    ports = [25, 24, 23, 22, 27, 18, 17, 11, 10, 9, 8, 7]

    # define the LED intensities
    # (10 longer than required, 5 extra 'each end')
    # (so sequence starts with all LEDs switched off)
    intens = [200,400,1990,400,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

    # make a copy of ports and then reverse it as we need both directions
    ports_rev = ports[:]
    ports_rev.reverse()

    delay = 1                   # set a delay

    servo = PWM.Servo()         # Set up PWM

    for loop in range(10):      # repeat n times
        for step in range(len(intens)):
            for port in range(len(ports)):  # set the intensity of each port
                servo.set_servo(ports[port], intens[(port+5)])
            intens = np.roll(intens, 1)
            sleep(delay)
        for step in range(len(intens)):
            for port in range(len(ports_rev)):  # set the intensity of each port
                servo.set_servo(ports_rev[port], intens[(port+5)])
            intens = np.roll(intens, 1)
            sleep(delay)

except KeyboardInterrupt:           # trap a CTRL+C keyboard interrupt
    print 'CTRL+C received...'
    
for port in ports:                       # cleanup
	servo.stop_servo(port)

saltydog
Posts: 39
Joined: Mon Dec 24, 2012 10:40 am

Re: RPIO: An extension of RPi.GPIO with interrupts, PWM and

Wed Apr 24, 2013 12:02 am

pzc wrote: I get weird results when I try to write an individual PWM waveform to each of the 12 LEDs.
Did you ever sort that out?

I get a similar thing when dimming multiple LEDs. Dimming a single led works fine. Results are not as expected when dimming multiple LEDs, using both PWM.servo and low level PWM method/s.

Chris

michaelperakis
Posts: 14
Joined: Sun Jan 19, 2014 7:10 pm

Re: RPIO: An extension of RPi.GPIO with interrupts, PWM and

Sun Jan 19, 2014 7:18 pm

Dear all,

I use the following code:

Code: Select all

import RPIO

def do_something(gpio_id, value):
    print("New value for GPIO %s: %s" % (gpio_id, value))

RPIO.add_interrupt_callback(17, do_something, edge='rising')
RPIO.add_interrupt_callback(18, do_something, edge='falling')
RPIO.add_interrupt_callback(19, do_something, edge='both', threaded_callback=True)
RPIO.wait_for_interrupts()
as posted at the beginning but I get an error about GPIO 17,18,19 not being setup (or something similar).
Does anyone know why this is happening?

I am using 18 as input having a button connected on and have changed the above code such as where 17 -> 18 and 18 ->17 in order to detect the rising effect when pressing the button.

Any suggestions?

BR
M.

texy
Forum Moderator
Forum Moderator
Posts: 5160
Joined: Sat Mar 03, 2012 10:59 am
Location: Berkshire, England

Re: RPIO: An extension of RPi.GPIO with interrupts, PWM and

Sun Jan 19, 2014 8:08 pm

michaelperakis wrote:Dear all,

I use the following code:

Code: Select all

import RPIO

def do_something(gpio_id, value):
    print("New value for GPIO %s: %s" % (gpio_id, value))

RPIO.add_interrupt_callback(17, do_something, edge='rising')
RPIO.add_interrupt_callback(18, do_something, edge='falling')
RPIO.add_interrupt_callback(19, do_something, edge='both', threaded_callback=True)
RPIO.wait_for_interrupts()
as posted at the beginning but I get an error about GPIO 17,18,19 not being setup (or something similar).
Does anyone know why this is happening?

I am using 18 as input having a button connected on and have changed the above code such as where 17 -> 18 and 18 ->17 in order to detect the rising effect when pressing the button.

Any suggestions?

BR
M.
Hi,
you need to show us the complete code, not just a snippet, and also a paste of the error message you are getting. Is it something like :

Code: Select all

RuntimeWarning: This channel is already in use, continuing anyway. Use GPIO.setwarnings(False) to disable warnings.
Texy
Various male/female 40- and 26-way GPIO header for sale here ( IDEAL FOR YOUR PiZero ):
https://www.raspberrypi.org/forums/viewtopic.php?f=93&t=147682#p971555

Return to “Python”