metachris / rpio Goto Github PK
View Code? Open in Web Editor NEWRPIO is a GPIO toolbox for the Raspberry Pi.
Home Page: https://pypi.python.org/pypi/RPIO
License: GNU Lesser General Public License v3.0
RPIO is a GPIO toolbox for the Raspberry Pi.
Home Page: https://pypi.python.org/pypi/RPIO
License: GNU Lesser General Public License v3.0
On line 462 of pwm.c
return fatal("Error: cannot add pulse to channel %d: width_start+width exceed max_width of %d\n", channels[channel].width_max);
two integer arguments are needed for fatal() function.
Platform Raspberry Pi Version 2 (the latest incarnation, runs at 1GHz)
Raspbian dated 2015-02-16
Python 3.4.3 and Python 3.2.3
RPIO was downloaded and installed on 2015-04-30
Problem:
Regards,
Tim Cole
[email protected]
I tried installing using the easy_install and it fails not being able to load the _GPIO.so
When trying the git clone and setup.py install it fails looking for Python.h
I initially added this to Issue #31, but on reflection it is actually a different problem so I now add it separately here.
I have been converting a program from using RPi.GPIO to use RPIO because I need to control the interrupt threading. I now have my interrupt threading working, such that interrupt handling code for the first interrupt runs to completion before the second interrupt is handled etc. BUT I have a new problem in that my routines using RPIO detect events (triggers) that are not actually present - even if I disconnect all wires from the trigger pins, events are detected and interrupts called. Apart from being unable to control threading, my hardware works properly with RPi.GPIO, with no unexpected interrupts occurring. So what is wrong?
I think it must be something simple with the add_interrupt_callbacks near the end, but I can't work out what.
My full code using RPIO (which triggers interrupts repeatedly) is below, followed by the equivalent version for RPi.GPIO (which works except for being unable to control threading)
What might be wrong?
PS: I know I have a logic flaw with the "don't respond to sounds if the piezo is sounding" handling. I will deal with that later.
Non-working RPIO version:
'''
import RPIO as RPIO
import time
on = 1
off = 0
sounder = off
RPIO.setwarnings(False) # Turn off warning messages (occur when run program after 1st time)
P0 = 17 # BCM 17
P1 = 18 # BCM 18
P2 = 27 # BCM 27 (21 on Revision 1)
P3 = 22 # BCM 22
P4 = 23 # BCM 23
P5 = 24 # BCM 24
P6 = 25 # BCM 25
P7 = 4 # BCM 4
CE1 = 7 # BCM 7
CE0 = 8 # BCM 8
SCLK = 11 # BCM 11
MISO = 9 # BCM 9
MOSI = 10 # BCM 10
RXD = 15 # BCM 15
TXD = 14 # BCM 14
SCL = 3 # BCM 3 (would be 1 on Revision 1)
SDA = 2 # BCM 2 (would be 0 on revision 1)
RPIO.setup(P0, RPIO.IN, pull_up_down=RPIO.PUD_UP) # Doorbell push; pressing will ground this pin
RPIO.setup(P1, RPIO.IN, pull_up_down=RPIO.PUD_UP) # Magnetic contact; normally grounded; removing magnet lets it go high
RPIO.setup(P2, RPIO.IN) # PIR; goes ON with movement detected
RPIO.setup(P3, RPIO.IN) # Sound detector; goes OFF when sound detected
RPIO.setup(P4, RPIO.OUT)
RPIO.setup(P5, RPIO.OUT)
RPIO.setup(P6, RPIO.OUT)
RPIO.setup(P7, RPIO.OUT)
RPIO.output(P4, off) # Piezo sounder
RPIO.output(P5, on) # For relay, set ON as this leaves relay quiescent to save power
RPIO.output(P6, on) # Relay
RPIO.output(P7, on) # Relay
time.sleep(1) # pause to allow inputs to settle before enabling interrupts
def flash(pin, ontime, offtime, count, first):
global on
global off
second = 1 - first # second state is opposite to the first one
for i in range (1, count+1): # needs +1 so it loops the correct number of times ?why
RPIO.output (pin, first)
time.sleep(ontime)
RPIO.output(pin, second)
if i <> count: # this is to avoid a wait at the end
time.sleep(offtime)
def incident (pin, dummyvar): # something has caused an alarm; needs a 2nd parameter
global on
global off
global sounder
print(' ')
print('Incident detected - now decode what it was. Pin '+str(pin)+'; Value '+str(dummyvar))
if pin == P0: # doorbell
print('Doorbell pushed - sound piezo and flash light')
sounder = on # set flag to ignore sound detection
RPIO.output(P4, on) # piezo on
flash(P7, 0.5, 0.5, 3, off) # pulse relay 3x 0.5 sec
RPIO.output(P4, off) # Piezo off
sounder = off
print('Ended doorbell actions')
elif pin == P1: # Magnetic contact, Magnet removed
print('Magnet removed - flash light')
flash(P7, 1, 0.5, 5, off) # pulse relay
print('Ended magnet removed actions')
elif pin == P2: # PIR detected motion
print('Motion detected - flicker light')
flash(P7, 2, 0.2, 3, off) # flicker relay
print('Ended Motion detected actions')
elif pin == P3: # Sound detected
if sounder == off: # only react to sound detection if piezo is not sounding !!
print ('Sound detected - turn light on whilst playing 4 bleeps')
RPIO.output(P7,off) # turn light on
sounder = on # set flag to ignore sound detection
flash(P4, 1, 1, 4, on) # sound piezo 4x for 1 second
sounder = off
RPIO.output(P7,on) # turn light back off
print('Ended sound detected actions')
else: # No actions if piezo is sounding
print('Ignoring sound detected as Piezo is sounding')
else: # unknown trigger
print ('Unidentified trigger')
RPIO.add_interrupt_callback(P0, incident, edge='falling', threaded_callback=False, debounce_timeout_ms=3000) # ignore repeat doorbell presses within 3000mSec (3 sec)
RPIO.add_interrupt_callback(P1, incident, edge='rising', threaded_callback=False, debounce_timeout_ms=3000) # magnetic contact. Switch normally grounds P1; when magnet removed, pull-
up causes HIGH
RPIO.add_interrupt_callback(P2, incident, edge='rising', threaded_callback=False, debounce_timeout_ms=15000) # PIR ignore repeats within 15 sec
RPIO.add_interrupt_callback(P3, incident, edge='falling', threaded_callback=False, debounce_timeout_ms=30000) # sound detector ignore repats within 30 sec
try:
print('Monitoring started ...')
print('Press CTRL-C to exit')
RPIO.wait_for_interrupts(threaded=False) # False make the main prog stop here - then the following loop is not needed
while True: # just wait forever ...
time.sleep(10000)
RPIO.cleanup()
except KeyboardInterrupt:
print ('Ending monitoring')
RPIO.cleanup() # Cleanup on CTRL-C
RPIO.cleanup()
'''
Working (apart from threading) RPi.GPIO version:
'''
import RPi.GPIO as IO
import time
on = 1
off = 0
sounder = off
IO.setmode(IO.BCM) # This version set to use BCM (Broadcom, the processor chip) GPIO numbers
IO.setwarnings(False) # Turn off warning messages (occur when run program after 1st time)
P0 = 17 # BCM 17
P1 = 18 # BCM 18
P2 = 27 # BCM 27 (21 on Revision 1)
P3 = 22 # BCM 22
P4 = 23 # BCM 23
P5 = 24 # BCM 24
P6 = 25 # BCM 25
P7 = 4 # BCM 4
CE1 = 7 # BCM 7
CE0 = 8 # BCM 8
SCLK = 11 # BCM 11
MISO = 9 # BCM 9
MOSI = 10 # BCM 10
RXD = 15 # BCM 15
TXD = 14 # BCM 14
SCL = 3 # BCM 3 (would be 1 on Revision 1)
SDA = 2 # BCM 2 (would be 0 on revision 1)
IO.setup(P0,IO.IN,pull_up_down=IO.PUD_UP) # Doorbell push
IO.setup(P1,IO.IN,pull_up_down=IO.PUD_UP) # Magnetic contact
IO.setup(P2,IO.IN) # PIR
IO.setup(P3,IO.IN) # Sound detector
IO.setup(P4,IO.OUT)
IO.setup(P5,IO.OUT)
IO.setup(P6,IO.OUT)
IO.setup(P7,IO.OUT)
IO.output(P4,off) # Piezo sounder
IO.output(P5,on) # For relay, set ON as this leaves relay quiescent to save power
IO.output(P6,on) # Relay
IO.output(P7,on) # Relay
def flash(pin, ontime, offtime, count, first):
global on
global off
second = 1 - first # second state is opposite to the first one
for i in range (1, count+1): # needs +1 so it loops the correct number of times ?why
IO.output (pin, first)
time.sleep(ontime)
IO.output(pin, second)
if i <> count: # this is to avoid a wait at the end
time.sleep(offtime)
def incident (pin): # something has caused an alarm
global on
global off
global sounder
print(' ')
print('Incident detected - now decode what it was. Pin '+str(pin))
if pin == P0: # doorbell
print('Doorbell pushed - sound piezo and flash light')
IO.output(P4, on) # piezo on
sounder = on # set flag to ignore sound detection
flash(P7, 0.5, 0.5, 3, off) # pulse relay 3x 0.5 sec
IO.output(P4, off) # Piezo off
sounder = off
print('Ended doorbell actions')
elif pin == P1: # Magnetic contact, Magnet removed
print('Magnet removed - flash light')
flash(P7, 1, 0.5, 5, off) # pulse relay
print('Ended magnet removed actions')
elif pin == P2: # PIR detected motion
print('Motion detected - flicker light')
flash(P7, 2, 0.2, 3, off) # flicker relay
print('Ended Motion detected actions')
elif pin == P3: # Sound detected
if sounder == off: # only raect to sound detection if piezo is not sounding !!
print ('Sound detected - turn light on whilst playing 4 bleeps')
IO.output(P7,off) # turn light on
sounder = on # set flag to ignore sound detection
flash(P4, 1, 1, 4, on) # sound piezo 4x for 1 second
sounder = off
IO.output(P7,on) # turn light back off
print('Ended sound detected actions')
else: # No actions if piezo is sounding
print('Ignoring sound detected as Piezo is sounding')
else: # unknown trigger
print ('Unidentified trigger')
IO.add_event_detect(P0,IO.RISING, callback=incident, bouncetime=3000) # ignore doorbell presses within 3000mSec (3 sec)
IO.add_event_detect(P1,IO.RISING, callback=incident, bouncetime=3000) # magnetic contact. With temp switch, detects RELEASING button (but no matter)
IO.add_event_detect(P2,IO.RISING, callback=incident, bouncetime=15000) # PIR ignore repeats within 15 sec
IO.add_event_detect(P3,IO.FALLING, callback=incident, bouncetime=30000) # sound detector ignore repats within 30 sec
try:
print('Monitoring started ...')
print('Press CTRL-C to exit')
while True: # just wait forever ...
time.sleep(10000)
except KeyboardInterrupt:
print ('Ending monitoring')
IO.cleanup() # Cleanup on CTRL-C
IO.cleanup()
According to this post, DMA channels 0, 1, 2, 3, 6 and 7 are already in use (by the GPU for 1, 3, 6, 7, the frame buffer for 0 and the SD card for 2).
Thus, those channels should not be used for PWM (this leaves channel 4 and 8+). Using channel 2 is known to cause problems with the SDCard (read-only error and console error "command not found").
Using by default channel 4 at initialisation would be good.
Also, adding this information to the PWM documentation would help people avoiding mistakes.
Finally, the PWM documentation could be enriched with more information about the simultaneous use of one channel by several outputs (each at its own PWM rate), as explained in the post linked above.
diff --git a/README.rst b/README.rst
index cfb3dd8..7af0f9c 100644
--- a/README.rst
+++ b/README.rst
@@ -1,6 +1,6 @@
RPIO is an advanced GPIO module for the Raspberry Pi.
-* PWM via DMA (up to 1<C2><B5>s resolution)
+* PWM via DMA (up to 1us resolution)
* GPIO input and output (drop-in replacement for `RPi.GPIO <http://pypi.python.org/pypi/RPi.GPIO>`_)
* GPIO interrupts (callbacks when events occur on input gpios)
* TCP socket interrupts (callbacks when tcp socket clients send data)
diff --git a/debian/rules b/debian/rules
index 498c100..c3edfda 100755
--- a/debian/rules
+++ b/debian/rules
@@ -1,11 +1,13 @@
#!/usr/bin/make -f
# -*- makefile -*-
-PYTHON2=$(shell pyversions -vr)
-PYTHON3=$(shell py3versions -vr)
+#export DH_VERBOSE=1
+
+PYTHON2=$(shell pyversions -vd)
+PYTHON3=$(shell py3versions -vd)
%:
- dh $@ --with python2,python3
+ dh $@ --with python2,python3 --buildsystem=python_distutils
build-python%:
python$* setup.py build
Not sure if this is real issue or me being a noob but I get this error:
Traceback (most recent call last):
File "run.py", line 6, in
app = create_app(True)
File "/home/pi/pi-booth/app/init.py", line 12, in create_app
from .main import main as main_blueprint
File "/home/pi/pi-booth/app/main/init.py", line 5, in
import routes, events
File "/home/pi/pi-booth/app/main/events.py", line 6, in
import camera
File "/home/pi/pi-booth/app/main/camera.py", line 1, in
import RPIO
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/RPIO/init.py", line 116, in
from RPIO._RPIO import Interruptor
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/RPIO/_RPIO.py", line 64, in
class Interruptor:
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/RPIO/_RPIO.py", line 68, in Interruptor
_epoll = select.epoll()
AttributeError: 'module' object has no attribute 'epoll'
Error in atexit._run_exitfuncs:
Traceback (most recent call last):
File "/usr/lib/python2.7/atexit.py", line 24, in _run_exitfuncs
func(_targs, *_kargs)
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/RPIO/_RPIO.py", line 58, in exit_handler
RPIO.stop_waiting_for_interrupts()
AttributeError: 'NoneType' object has no attribute 'stop_waiting_for_interrupts'
Error in sys.exitfunc:
Traceback (most recent call last):
File "/usr/lib/python2.7/atexit.py", line 24, in _run_exitfuncs
func(_targs, *_kargs)
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/RPIO/_RPIO.py", line 58, in exit_handler
RPIO.stop_waiting_for_interrupts()
AttributeError: 'NoneType' object has no attribute 'stop_waiting_for_interrupts'
According to the comment at https://github.com/metachris/RPIO/blob/master/source/c_pwm/pwm.c#L445 add_channel_pulse(...)
is uncapable of setting one GPIO pin LOW and another HIGH at the very same time on the same DMA channel.
Currently the only the last action will be applied to all.
I would rather expect a return fatal(...)
so I don't experience mysterious behaviour and have to go through the source code to find a comment on why this basic functionality doesn't work.
Received the following exception
Exception in thread Thread-39:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 505, in run
self.__target(_self.__args, *_self.__kwargs)
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/RPIO/_RPIO.py", line 320, in wait_for_interrupts
self._handle_interrupt(fileno, val)
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/RPIO/_RPIO.py", line 241, in _handle_interrupt
val = int(val)
ValueError: invalid literal for int() with base 10: ''
Please advise if you need more information. The code has been running for several days and this error has occurred once. The code seems to be continuing to run correctly.
Setup is:
RPIO.add_interrupt_callback( 4, self.callBack, edge = 'rising', threaded_callback = True,debounce_timeout_ms = 50)
Interrupts on GPIO 4 are triggered by the interrupt pin from a MCP23008 which monitors 8 limit switches.
On an interrupt, the callback routine posts a message on a queue .
The operational process (simplified) is:
Clear the queue
RPIO.wait_for_interrupts( threaded = True )
Enable MS23008 interrupts
while True:
try :
msg = queue.get( block=True, timeout=2.0)
Process interrupt message
break
except Queue,Empty:
break
disable MS23008 interrupts
RPIO.stop_waiting_for_interrupts()
I need to change the subcycle_time_us of a channel after it's been initialized, but it seems to be impossible.
First, I tried PWM.clear_channel(chan) before PWM.init_channel(chan, subcycle_time_us=new_stu), but it gave an error that the channel was already initialized. Next, I tried a more draconian cleanup() call (I don't want to touch other channels, and this would mean initializing all of them which I really don't want to do, but even that didn't work.
It looks like the problem is the virtbase pointer in the channel structure. It's used throughout pwm.c to indicate whether the channel has been initialized. init_channel checks if it's set, and assumes it's initialized if it is set. But clear_channel doesn't clear it (and neither does shutdown (called by cleanup)). As there's no way to clear virtbase, there's no way to change the subcycle_time_us of a channel.
The following script should call 'ls' once per second - but as soon as the call to ls executes, the script dies.
from RPIO import PWM
import os
import time
def setup():
PWM.setup()
def main():
while True:
os.system("ls")
time.sleep(1.000)
setup()
main()
If I run the PWM script in the console, then everything works as expected, but if I run it from a script file, then the PWM dies after a few moments:
#!/usr/bin/env python2
from RPIO import PWM
def wdog(GPIO=18,CHAN=0,FREQ=20000):
PWM.setup()
PWM.init_channel(CHAN,FREQ) ## Freq = 199,000us
if(not PWM.is_channel_initialized(CHAN)):
PWM.clear_channel_gpio(CHAN,GPIO)
PWM.add_channel_pulse(CHAN,GPIO,0,1000) ## 50%
wdog(22,0)
I have a server that just sits quietly in a tmux window, watching pins and doing it's thing. But if I attach it and my window size changes, it dies. The reason is that source/c_pwm/pwm.c traps all signals, even those that are normally ignored:
// Catch all signals possible - it is vital we kill the DMA engine
// on process exit!
static void
setup_sighandlers(void)
{
int i;
for (i = 0; i < 64; i++) {
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = (void *) terminate;
sigaction(i, &sa, NULL);
}
}
I believe #19 and #15 are really this bug. But I put this here because the bug is more general than those issues.
When an GPIO interrupt occurs, it is often interesting to now the microsecond counter at time of interrupt. Would it be possible to add this to the callback parameters ? I suspect such a timestamp would be far more accurate than reading the microsecond counter in Python.
rpio-curses command issued on Raspbery Pi A+ ends with following error:
root@kroko:/automat# rpio-curses
Traceback (most recent call last):
File "/usr/local/bin/rpio-curses", line 5, in
pkg_resources.run_script('RPIO==0.10.0', 'rpio-curses')
File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 499, in run_script
self.require(requires)[0].run_script(script_name, ns)
File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 1235, in run_script
execfile(script_filename, namespace, namespace)
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/EGG-INFO/scripts/rpio-curses", line 93, in
"Maker: %s") % RPIO.sysinfo()
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/RPIO/init.py", line 183, in sysinfo
return (RPI_REVISION_HEX,) + MODEL_DATA[RPI_REVISION_HEX.lstrip("0")]
KeyError: '12'
In the example of "example4_pwm_lowlevel.py", it said we can add a new pulse to a subcycle. E.g.:
import RPIO.PWM as PWM
GPIO = 17
CHANNEL = 0
PWM.set_loglevel(PWM.LOG_LEVEL_DEBUG)
PWM.setup()
PWM.init_channel(CHANNEL)
PWM.print_channel(CHANNEL)
PWM.add_channel_pulse(CHANNEL, GPIO, 0, 50)
PWM.add_channel_pulse(CHANNEL, GPIO, 100, 50)
The above code will generate a pulse with two high levels, for each level, the width is 50*10us, the subcycle should looks like: --------__,
what if I want change the pulse to --? I don't think we can use PWM.add_channel_pulse(CHANNEL, GPIO, 50, 50), because I feel that will create: ------_, Am I right? how to change the pulse width smoothly?
Pressing CTRL+C quits the program if it is using RPIO.PWM, even though I have set try-except KeyboardException handler and have many other threads running as well.
$ pip install rpio
Collecting rpio
Downloading RPIO-0.10.0.tar.gz
Installing collected packages: rpio
Running setup.py install for rpio
Complete output from command /usr/local/opt/python/bin/python2.7 -c "import setuptools, tokenize;file='/private/var/folders/gx/dr6024r10jgdltk5gn18crtr0000gn/T/pip-build-8wpU6f/rpio/setup.py';exec(compile(getattr(tokenize, 'open', open)(file).read().replace('\r\n', '\n'), file, 'exec'))" install --record /var/folders/gx/dr6024r10jgdltk5gn18crtr0000gn/T/pip-IhNepU-record/install-record.txt --single-version-externally-managed --compile:
running install
running build
running build_py
creating build
creating build/lib.macosx-10.10-x86_64-2.7
creating build/lib.macosx-10.10-x86_64-2.7/RPIO
copying source/RPIO/init.py -> build/lib.macosx-10.10-x86_64-2.7/RPIO
copying source/RPIO/_RPIO.py -> build/lib.macosx-10.10-x86_64-2.7/RPIO
copying source/RPIO/Exceptions.py -> build/lib.macosx-10.10-x86_64-2.7/RPIO
creating build/lib.macosx-10.10-x86_64-2.7/RPIO/PWM
copying source/RPIO/PWM/init.py -> build/lib.macosx-10.10-x86_64-2.7/RPIO/PWM
running build_ext
building 'RPIO._GPIO' extension
creating build/temp.macosx-10.10-x86_64-2.7
creating build/temp.macosx-10.10-x86_64-2.7/source
creating build/temp.macosx-10.10-x86_64-2.7/source/c_gpio
clang -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -Qunused-arguments -Qunused-arguments -I/usr/local/include -I/usr/local/opt/sqlite/include -I/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/include/python2.7 -c source/c_gpio/py_gpio.c -o build/temp.macosx-10.10-x86_64-2.7/source/c_gpio/py_gpio.o
source/c_gpio/py_gpio.c:361:1: error: static declaration of 'setmode' follows non-static declaration
setmode(PyObject self, PyObject *args)
^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include/unistd.h:695:7: note: previous declaration is here
void *setmode(const char *) __DARWIN_ALIAS_STARTING(__MAC_10_6, __IPHONE_2_0, __DARWIN_ALIAS(setmode));
^
source/c_gpio/py_gpio.c:431:17: warning: incompatible pointer types initializing 'PyCFunction' (aka 'PyObject *()(PyObject *, PyObject *)') with an expression of type 'void *(const char *)' [-Wincompatible-pointer-types]
{"setmode", setmode, METH_VARARGS, "Set up numbering mode to use for channels.\nBOARD - Use Raspberry Pi board numbers\nBCM - Use Broadcom GPIO 00..nn numbers"},
^~~~~~~
1 warning and 1 error generated.
error: command 'clang' failed with exit status 1
----------------------------------------
Command "/usr/local/opt/python/bin/python2.7 -c "import setuptools, tokenize;__file__='/private/var/folders/gx/dr6024r10jgdltk5gn18crtr0000gn/T/pip-build-8wpU6f/rpio/setup.py';exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" install --record /var/folders/gx/dr6024r10jgdltk5gn18crtr0000gn/T/pip-IhNepU-record/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /private/var/folders/gx/dr6024r10jgdltk5gn18crtr0000gn/T/pip-build-8wpU6f/rpio
Hi - I am searching for an easy way to control servos (Hitec HS-805) with the RasPi.
I tried to use the one plain "PWM" provided by the RasPi with wiringPi's GPIO which worked out-of-the-box but not with satisfying results; the position of the servos is not reproducible and they vibrate slightly instead stopping until the PWM is switched off completely.
Then I searched the net and found some interesting work: "piblaster" and "servoblaster".
As piblaster seems more recent and claims to be an improved servoblaster, I tried it with ambivalent results: the positioning is acceptable but I got some weird DMA errors in the system log about filesystem corruption and problems accessing the SD card (/dev/mmcblk0p2), so I continued searching and found RPIO. Looked perfect in all aspects: easy install, in depth configurable for all servo needs, python and commandline interface, very accurate servo positioning - but after a while I get the same errors as with piblaster. First I thought I can force it with quickly moving the servo, but it also happens when doing just two cycles and waiting a few seconds.
I used your example - just with an other GPIO:
from RPIO import PWM
servo = PWM.Servo()
Using hardware: PWM
PW increments: 10us
servo.set_servo(4, 1000)
Initializing channel 0...
add_channel_pulse: channel=0, gpio=4, start=0, width=100
init_gpio 4
servo.set_servo(4, 1800)
clear_channel_gpio: channel=0, gpio=4
add_channel_pulse: channel=0, gpio=4, start=0, width=180
servo.stop_servo(4)
clear_channel_gpio: channel=0, gpio=4
This is moving my servo by 90 degrees.
I tried other servos, GPIOs, power supplies (both: servo and RasPi).
Do you also have seen anything like this yes? any ideas?
BTW: I am using Fedora 18 - no other tasks running, with
rpio --version = RPIO v0.10.1 (gpio-lib v0.10.1/0.4.2a).
rpio --sysinfo = 000d: Model B, Revision 2.0, RAM: 512 MB, Maker: Egoman
Christian
This happens when trying to build with musl libc on Alpine Linux:
ccache gcc -DNDEBUG -Os -fomit-frame-pointer -Os -fomit-frame-pointer -Os -fomit-frame-pointer -fPIC -I/usr/include/python2.7 -c source/c_gpio/c_gpio.c -o build/temp.linux-i686-2.7/source/c_gpio/c_gpio.o
source/c_gpio/c_gpio.c: In function 'setup':
source/c_gpio/c_gpio.c:82:35: error: 'caddr_t' undeclared (first use in this function)
gpio_map = (uint32_t *)mmap( (caddr_t)gpio_mem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, mem_fd, GPIO_BASE);
^
the caddr_t should be replaced with void *.
see http://stackoverflow.com/questions/6381526/what-is-the-significance-of-caddr-t-and-when-is-it-used
I am getting an error with add_interrupt_callback.
I am using BOARD pin numbering with P0 set to 11 (ie BCM 18)
I can set up and read inputs (and setup and write outputs) OK. And my previous code with RPi.GPIO worked OK (except that I want to control the threading)
But when I try to set an interrupt with:
RPIO.add_interrupt_callback(P0, bellpush, edge='rising', threaded_callback=False, debounce_timeout_ms=3000)
I get a 'not valid pin on Raspberry Pi' error, as follows:
Traceback (most recent call last):
File "alarmv3.py", line 106, in
IO.add_interrupt_callback(P0, bellpush, edge='rising', threaded_callback=False, debounce_timeout_ms=3000)
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/RPIO/init.py", line 217, in add_interrupt_callback
threaded_callback, debounce_timeout_ms)
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/RPIO/_RPIO.py", line 139, in add_interrupt_callback
if RPIO.gpio_function(int(gpio_id)) == RPIO.IN:
RPIO.Exceptions.InvalidChannelException: The channel sent is invalid on a Raspberry Pi (not a valid pin)
I tried using values for RPi pins and BCM pins instead of the variable P0, but all give the same error. Am I doing something wrong, or is there a bug?
RPIO seems not to be able to handle with loosing its FD like when daemonizing the process.
In the main() function, i try to call daemon_runner.do_action(), which results in
root@raspberrypi # python DoorcamExample.py start
root@raspberrypi #
started with pid 4374
Traceback (most recent call last):
File "DoorcamExample.py", line 224, in <module>
main()
File "DoorcamExample.py", line 201, in main
daemon_runner.do_action()
File "/usr/local/lib/python2.7/dist-packages/daemon/runner.py", line 189, in do_action
func(self)
File "/usr/local/lib/python2.7/dist-packages/daemon/runner.py", line 134, in _start
self.app.run()
File "DoorcamExample.py", line 164, in run
self.doorcam.startListening(channel=23, threaded=False, port=8099)
File "DoorcamExample.py", line 141, in startListening
RPIO.add_interrupt_callback(23, self.gpio_callback, pull_up_down=RPIO.PUD_DOWN, debounce_timeout_ms=1000)
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/RPIO/__init__.py", line 217, in add_interrupt_callback
threaded_callback, debounce_timeout_ms)
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/RPIO/_RPIO.py", line 215, in add_interrupt_callback
self._epoll.register(f.fileno(), select.EPOLLPRI | select.EPOLLERR)
IOError: [Errno 9] Bad file descriptor
INFO:DoorcamLog:Stop listening
while commenting daemon_runner.do_action() and uncommenting #app.run() works just as I hoped...
Is this a bug in RPIO, or am I missing something?
External modules:
RPIO
python-daemon's runner module
picamera (I guess not a part of the problem)
For the sake of resolving this issue, I also placed an open question on stackexchange:
http://raspberrypi.stackexchange.com/questions/14387/rpio-not-able-to-cope-with-daemonizing-the-process
DoorcamExample.py:
#!/usr/bin/python
import sys
import os
if os.geteuid() != 0:
# This works perfect on a Raspbian system because there's no rootpassword required
os.execvp("sudo", ["sudo"] + sys.argv)
print('to far!') #This should NEVER be reached, there is something wrong...
sys.exit(1)
import time
import datetime
import subprocess
import re
import glob
import logging
from daemon import runner
from lockfile import LockTimeout
import RPIO
import picamera
import atexit
class Doorcam:
global logger
logger = logging.getLogger("DoorcamLog")
def __init__(self):
logger.info('Doorcam started capturing')
self.pollLightFile='/var/tmp/picam-pollLight'
#self.p=[]
atexit.register(self.stopListening)
def boolval(self, test):
return [False, True][test.lower()[0] == 't']
def shot(self,filename, number=1, trigger='timed',resolution=(800,600)):
logger.info('Doorcam shot for %s'%trigger)
with picamera.PiCamera() as camera:
camera.resolution = resolution
camera.brightness = 56
if self.pollLight():
camera.exposure_mode = 'verylong'
else:
camera.exposure_mode = 'auto'
camera.start_preview()
timestamp= datetime.datetime.now().strftime('%Y%m%d-%H%M%S')
if number <= 1:
if self.pollLight():
time.sleep(2)
else:
time.sleep(0.5)
camera.exif_tags['IFD0.ImageDescription'] = str('Doorcam, %s shot %d of %d'%(trigger, number, number))
filename=filename%(timestamp+'-'+trigger)
camera.capture(filename)
else:
if self.pollLight():
time.sleep(1)
else:
time.sleep(0.8/number)
for x in range(1, number+1):
camera.exif_tags['IFD0.ImageDescription'] = str('Doorcam, %s shot %d of %d'%(trigger, x, number))
camera.capture(filename%(timestamp+'-'+trigger+'-'+str(x)+'of'+str(number)))
time.sleep(0.3)
filename=filename%(timestamp+'-*')
#timestampreadable= datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
return filename
def upload(self, filename,trigger='', notify=False):
names=sorted(glob.iglob(filename))
if type(notify) is bool:
if notify == True:
subprocess.Popen(['su', 'pi', 'notify.sh', '%s @ %s'%(trigger,datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))], stdin=None, stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT, close_fds=True)
subprocess.Popen(['su', 'pi', 'notify_photo.sh', names[0]], stdin=None, stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT, close_fds=True)
else:
subprocess.Popen(['su', 'pi', 'notify.sh', 'ERROR: %s with notify: %s (%s) @ %s'%(trigger, notify, type(notify), datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))], stdin=None, stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT, close_fds=True)
for name in names:
basename=os.path.basename(name)
logger.info('Doorcam started uploading %s as %s'%(name,basename))
subprocess.Popen(['photohandler.sh', name, '/doorcam/%s'%basename,], stdin=None, stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT, close_fds=True)
return names[0]
def pollLight(self):
try:
(mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime) = os.stat(self.pollLightFile)
except:
mtime = 0
#time.ctime(mtime)
if mtime < (time.time()-1800):
pollLine=['wget', 'http://www.isitdarkoutside.com/', '-q', '-O', '-']
out = subprocess.check_output(pollLine, stderr=subprocess.STDOUT)
out = re.search(b'id="answer">...', out)
out = out.group(0)
if out == 'id="answer">yes':
lastPollReturn = True
else:
lastPollReturn = False
file = open(self.pollLightFile, "w")
file.write(str(lastPollReturn))
file.close()
else:
file = open(self.pollLightFile)
lastPollReturn= (file.read().lower() == 'true')
file.close()
return lastPollReturn
def gpio_callback(self, gpio_id, val):
self.upload(self.shot(filename=self.filename, number=10, trigger='Doorbell'), notify=True, trigger='Doorbell')
def socket_callback(self, socket, val):
vals=val.split()
if len(vals) == 0 or len(vals) > 4:
number=1
notify=True
trigger='Socket'
triggernotify='Socket (value %s)'%val
elif len(vals) == 1:
number=int(vals[0])
notify=True
trigger='Socket'
triggernotify='Socket (value %s)'%val
elif len(vals) == 2:
number=int(vals[1])
notify=True
trigger=vals[0]
triggernotify=vals[0]
elif len(vals) == 3:
number=int(vals[1])
trigger=vals[0]
triggernotify=vals[0]
notify=self.boolval(vals[2])
elif len(vals) == 4:
number=int(vals[2])
trigger=vals[0]
triggernotify=vals[0], [1]
notify=self.boolval(vals[3])
socket.send(self.upload(self.shot(filename=self.filename, number=number, trigger=trigger), notify=notify,trigger=triggernotify))
RPIO.close_tcp_client(socket.fileno())
def startListening(self,channel,port=8080, threaded=True):
RPIO.add_interrupt_callback(23, self.gpio_callback, pull_up_down=RPIO.PUD_DOWN, debounce_timeout_ms=1000)
RPIO.add_tcp_callback(port, self.socket_callback)
RPIO.wait_for_interrupts(threaded=threaded)
def stopListening(self):
logger.info('Stop listening')
RPIO.stop_waiting_for_interrupts()
class Doorcamdaemon():
def __init__(self):
self.stdin_path = '/dev/null'
self.stdout_path = '/dev/tty'
self.stderr_path = '/dev/tty'
self.pidfile_path = '/run/lock/doorcam.pid'
self.pidfile_timeout = 5
def run(self):
self.doorcam=Doorcam()
#while True:
self.doorcam.filename='/var/tmp/%s.jpg'
#logger.info(self.doorcam.filename)
if self.shots > 0:
self.doorcam.upload(self.doorcam.shot(filename=self.doorcam.filename, number=self.shots, trigger=self.trigger), notify=self.notify, trigger=self.trigger)
self.doorcam.startListening(channel=23, threaded=False, port=8099)
#self.doorcam.timerShots(30)
#self.doorcam.stopListening()
# def start(self):
# try:
# self.run()
# except KeyboardInterrupt:
# print('You pressed Ctrl+C!')
# self.doorcam.stopListening()
def main():
global logger
trigger='doorbell'
shots=0
notify=False
if len(sys.argv) == 2 and not (sys.argv[1] == 'start' or sys.argv[1] == 'stop' or sys.argv[1] == 'restart'):
print( ("Usage: {0} start | stop | restart | trigger shots notify\nFor example:\n {0} commandline 2 True").format(sys.argv[0]) )
sys.exit(1)
logger = logging.getLogger("DoorcamLog")
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
handler = logging.FileHandler("/var/log/doorcam.log")
handler.setFormatter(formatter)
logger.addHandler(handler)
app = Doorcamdaemon()
daemon_runner = runner.DaemonRunner(app)
#This ensures that the logger file handle does not get closed during daemonization
daemon_runner.daemon_context.files_preserve=[handler.stream]
app.trigger=trigger
app.notify=notify
app.shots=shots
try:
daemon_runner.do_action()
#app.run()
except LockTimeout:
import errno
if len(sys.argv) == 4:
trigger=sys.argv[1]
shots=int(sys.argv[2])
notify = [False, True][sys.argv[3].lower()[0] == 't']
try:
from telnetlib import Telnet
tn = Telnet('localhost', 8099)
tn.write( ('{0} {1} {2}\r\n').format(trigger, shots, str(notify)).encode('latin-1'))
#print(tn.read_all())
sys.exit(0)
logger.info("couldn't aquire lock, tcpsocket request has been made...")
logger.debug(tn.read_all())
except:
sys.exit(errno.ECONNREFUSED)
sys.exit(errno.EINVAL)
except KeyboardInterrupt:
logger.info('Caught CTRL-C, quitting...')
if __name__ == "__main__":
main()
Hello
I tried to use your library to generate some PWM signals on a RaspberryPi V2 but I get always same error:
Traceback (most recent call last):
File "/usr/local/bin/rpio", line 5, in
pkg_resources.run_script('RPIO==0.10.1', 'rpio')
File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 499, in run_script
self.require(requires)[0].run_script(script_name, ns)
File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 1235, in run_script
execfile(script_filename, namespace, namespace)
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.1-py2.7-linux-armv7l.egg/EGG-INFO/scripts/rpio", line 353, in
main()
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.1-py2.7-linux-armv7l.egg/EGG-INFO/scripts/rpio", line 147, in main
import RPIO
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.1-py2.7-linux-armv7l.egg/RPIO/init.py", line 115, in
import RPIO._GPIO as _GPIO
SystemError: This module can only be run on a Raspberry Pi!
Any help on solving this would be welcome.
Thank you
-=Seba=-
It seems that you must call add_interrupt_callback() and then setup(). Calling in the reverse order has add_interrupt_callback) resetting the pin's parameters to some default value.
If the terminal height is 23 lines an error message is output that says what the problem is:
"Your terminal window is too small. rpio-curses
needs 24 lines and 70 columns (you have 23 lines, 80 columns)."
If the terminal height is 24 or 25 lines, the following is output:
Traceback (most recent call last):
File "/usr/local/bin/rpio-curses", line 5, in
pkg_resources.run_script('RPIO==0.10.0', 'rpio-curses')
File "/usr/local/lib/python2.7/dist-packages/distribute-0.6.49-py2.7.egg/pkg_resources.py", line 507, in run_script
self.require(requires)[0].run_script(script_name, ns)
File "/usr/local/lib/python2.7/dist-packages/distribute-0.6.49-py2.7.egg/pkg_resources.py", line 1272, in run_script
execfile(script_filename, namespace, namespace)
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/EGG-INFO/scripts/rpio-curses", line 495, in
main()
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/EGG-INFO/scripts/rpio-curses", line 461, in main
d.start()
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/EGG-INFO/scripts/rpio-curses", line 417, in start
self.draw()
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/EGG-INFO/scripts/rpio-curses", line 182, in draw
screen.addstr(pos_y, POS_GPIOLIST_X, option)
_curses.error: addstr() returned ERR
The output should offer a resolution OR the documentation needs to clearly specify a terminal window size to use
I did this on my RPi2
$ sudo apt-get install python-setuptools
$ sudo easy_install -U RPIO
and got this
pi@raspberrypi ~/RPIO $ sudo easy_install -U RPIO
Searching for RPIO
Reading http://pypi.python.org/simple/RPIO/
Best match: RPIO 0.10.0
Downloading https://pypi.python.org/packages/source/R/RPIO/RPIO-0.10.0.tar.gz#md5=cefc45422833dcafcd59b78dffc540f4
Processing RPIO-0.10.0.tar.gz
Running RPIO-0.10.0/setup.py -q bdist_egg --dist-dir /tmp/easy_install-iyUVZN/RPIO-0.10.0/egg-dist-tmp-mlGrcH
source/c_gpio/py_gpio.c:28:20: fatal error: Python.h: No such file or directory
compilation terminated.
error: Setup script exited with error: command 'gcc' failed with exit status 1
I tried this
$ git clone https://github.com/metachris/RPIO.git
$ cd RPIO
$ sudo python setup.py install
with a similar result.
can anyone tell me what I need to do please?
Hey Chris,
pip is throwing an error during the build with:
source/c_gpio/py_gpio.c:9:20: fatal error: Python.h: No such file or directory
Any ideas?
If you need the pip log file or anything, just shout.
Cheers,
Padraic
This is not an Issue, I just want to request an example of an Interrupt in a Class.
I do have a Interrupt trigger to a Callback function on a Class of a Movement Sensor
When I am importing the movement sensor Class in my code (since there are movement around) immediately start triggering the Callback function that gives an error because it does not have a "self" instance. (I am just importing the Class).
My question is there is a workaround? What is the best practice to code an Interrupt in a python Class?
Thanks in Advance,
Pablo.
Hi, So, let's try to explain my issue.
Context : I'm using RPIO in a WebIOPi setup which seems to work properly as all functions work.
The project I'm working on is 5 bicycles (non moving, on home trainers) odometer. I use reed sensors on wheels. At each turn the magnet pass by the sensor and close it. On the RPi side, i catch those with interrupts on GPIO pins.
And here is my issue : some interrupts callbacks aren't triggered. In debug mode, I can see that :
RPIO.add_interrupt_callback
in threaded mode as well as the RPIO.wait_for_interrupts
. And debouncetime setting seems to not change anything. It is like the callback isn't threaded as it should be...Anyone got an idea ?
Here is extracts of my code :
def velo_capt(gpio_id, value):
global data
data['velo%s' % gpio_id]['dist'] = data['velo%s' % gpio_id]['dist']+data['velo%s' % gpio_id]['circonf']
def setup():
RPIO.add_interrupt_callback(7, velo_capt, edge='rise', threaded_callback=True)
RPIO.add_interrupt_callback(8, velo_capt, edge='rise', threaded_callback=True)
RPIO.add_interrupt_callback(9, velo_capt, edge='rise', threaded_callback=True)
RPIO.add_interrupt_callback(10, velo_capt, edge='rise', threaded_callback=True)
RPIO.add_interrupt_callback(11, velo_capt, edge='rise', threaded_callback=True)
RPIO.wait_for_interrupts(threaded=True)
Thanx for your help !
Fred
I get the following error message with my program:
pi@TestPi ~ $ sudo python3 "bread test.py"
Traceback (most recent call last):
File "bread test.py", line 7, in
import RPIO as GPIO
File "/usr/local/lib/python3.2/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/RPIO/init.py", line 115, in
import RPIO._GPIO as _GPIO
ImportError: /usr/local/lib/python3.2/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/RPIO/_GPIO.so: undefined symbol: _Py_ZeroStruct
When I installed RPIO, it only put the libraries in the python2.7 folder, so I copied the 2.7 libs directly into the python3.2 folder.
The same program runs fine (ignoring "print" formatting with the parenthesis) in python 2.7, but gets the above error in python 3.2
Also, when I try to run "rpio-curses" I get the following error:
pi@TestPi ~ $ rpio-curses
Script not started as root. Running sudo...
Traceback (most recent call last):
File "/usr/local/bin/rpio-curses", line 5, in
pkg_resources.run_script('RPIO==0.10.0', 'rpio-curses')
File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 499, in run_script
self.require(requires)[0].run_script(script_name, ns)
File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 1235, in run_script
execfile(script_filename, namespace, namespace)
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/EGG-INFO/scripts/rpio-curses", line 93, in
"Maker: %s") % RPIO.sysinfo()
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/RPIO/init.py", line 183, in sysinfo
return (RPI_REVISION_HEX,) + MODEL_DATA[RPI_REVISION_HEX.lstrip("0")]
KeyError: '10'
Please help - I would love to be able to use rpio-curses and use the library with python 3.2.
Thanks!
James
I was unable to get a call back to work until I defined it with 3 arguments not 2 as noted in the documentation "def cb( me, pin, val) :" where "me" is a reference to the class so that class variables are referenced as me.xyz in the call back routine. Is this correct or am I doing something wrong?
Python 2.7 on Raspberry Pi wheezy updated.
My version of RPIO is "RPIO v0.10.0 (gpio-lib v0.10.0/0.4.2a)"
Hi,
I have a Raspberry Pi 2 and am getting the error below when trying to import the RPIO module. Should. Was getting this error when trying to import RPi.GPIO as well until recently, but that imports OK after some recent updates? Only just worked out that these are two different things - being a newbie and all that!
@raspberrypi ~ $ python
Python 2.7.3 (default, Mar 18 2014, 05:13:23)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
import RPIO
Traceback (most recent call last):
File "", line 1, in
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.1-py2.7-linux-armv7l.egg/RPIO/init.py", line 115, in
import RPIO._GPIO as _GPIO
SystemError: This module can only be run on a Raspberry Pi!
Traceback:
Traceback (most recent call last):
File "/usr/local/bin/rpio-curses", line 495, in <module>
main()
File "/usr/local/bin/rpio-curses", line 461, in main
d.start()
File "/usr/local/bin/rpio-curses", line 417, in start
self.draw()
File "/usr/local/bin/rpio-curses", line 176, in draw
screen.addstr(pos_y, POS_GPIOLIST_X+9, "%s " % (GPIO_FUNCTIONS[func]), curses.color_pair(3) if func == 4 else 0)
KeyError: 6
Running RPIO 0.10.0.
Any clues?
Hi there, when running my script, each time I launch I don't get my callback registered unless I change the "rising" or "falling" or "both" value when I register? I suppose perhaps you don't re-register the callback each time unless something has changed? I am cancelling my last script with Ctrl_C so i'm not running any cleanup code. Could that be why? Can't the library just forcibly override the last registered callback so my script can guarantee it's registered each time?
I get the following on the new Model B+:
pi@rpiplus ~ $ sudo rpio --version
RPIO v0.10.0 (gpio-lib v0.10.0/0.4.2a)
pi@rpiplus ~ $ sudo rpio --sysinfo
Traceback (most recent call last):
File "/usr/local/bin/rpio", line 5, in
pkg_resources.run_script('RPIO==0.10.0', 'rpio')
File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 499, in run_script
self.require(requires)[0].run_script(script_name, ns)
File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 1235, in run_script
execfile(script_filename, namespace, namespace)
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/EGG-INFO/scripts/rpio", line 345, in
main()
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/EGG-INFO/scripts/rpio", line 338, in main
RPIO.sysinfo()
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/RPIO/init.py", line 183, in sysinfo
return (RPI_REVISION_HEX,) + MODEL_DATA[RPI_REVISION_HEX.lstrip("0")]
KeyError: '10'
gbin@flypi ~/projects/RPIO> python setup.py install --user running install
running bdist_egg
running egg_info
writing top-level names to source/RPIO.egg-info/top_level.txt
writing source/RPIO.egg-info/PKG-INFO
writing dependency_links to source/RPIO.egg-info/dependency_links.txt
reading manifest file 'source/RPIO.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'source/RPIO.egg-info/SOURCES.txt'
installing library code to build/bdist.linux-armv6l/egg
running install_lib
running build_py
running build_ext
building 'RPIO._GPIO' extension
gcc -pthread -Wno-unused-result -Werror=declaration-after-statement -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -march=armv6 -mfloat-abi=hard -mfpu=vfp -O2 -pipe -fstack-protector --param=ssp-buffer-size=4 -fPIC -I/usr/include/python3.4m -c source/c_gpio/py_gpio.c -o build/temp.linux-armv6l-3.4/source/c_gpio/py_gpio.o
gcc -pthread -Wno-unused-result -Werror=declaration-after-statement -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -march=armv6 -mfloat-abi=hard -mfpu=vfp -O2 -pipe -fstack-protector --param=ssp-buffer-size=4 -fPIC -I/usr/include/python3.4m -c source/c_gpio/c_gpio.c -o build/temp.linux-armv6l-3.4/source/c_gpio/c_gpio.o
gcc -pthread -Wno-unused-result -Werror=declaration-after-statement -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -march=armv6 -mfloat-abi=hard -mfpu=vfp -O2 -pipe -fstack-protector --param=ssp-buffer-size=4 -fPIC -I/usr/include/python3.4m -c source/c_gpio/cpuinfo.c -o build/temp.linux-armv6l-3.4/source/c_gpio/cpuinfo.o
source/c_gpio/cpuinfo.c: In function ‘get_cpuinfo_revision’:
source/c_gpio/cpuinfo.c:64:5: error: ISO C90 forbids mixed declarations and code [-Werror=declaration-after-statement]
char* pos = strstr(revision_hex, "1000");
It compiles directly with the Makefile and make. I'll investigate if I have time.
When I open any 2 or more DMA channels to operate PWM, the signal signal width is doubled, thus a 1400us becomes a 2800us signal.
When PWM is used from the window icon it works but jams the screen (reboot time!). It's fine with non PWM I/O. Tried with python 2.7 and 3.2 - same result.
I'm calling python with sudo to get past /dev/mem access, I'm assuming this is correct.
If started from the LXTerminal window it is OK till you click on the Python Shell that it starts up, then jams the mouse again.
RPIO and Python are up to date as of today (Raspberian updated last week) - what am I doing wrong?
RPIO will be really good when I can get past these issues!
PS it seems to get mixed up if you try to use RPIO.BOARD.
When trying to create a channel pulse greater than 99999 in length a runtime error is returned. The error message also seems to contain errors (the channel number and the max_width). Below is an example that I generated in the python prompt:
import RPIO.PWM as pwm
pwm.setup()
Using hardware: PWM
PW increments: 10us
pwm.init_channel(0, 1000000)
Initializing channel 0...
pwm.add_channel_pulse(0, 18, 0, 99999)
add_channel_pulse: channel=0, gpio=18, start=0, width=99999
init_gpio 18
pwm.add_channel_pulse(0, 18, 0, 100000)
add_channel_pulse: channel=0, gpio=18, start=0, width=100000
Traceback (most recent call last):
File "", line 1, in
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/RPIO/PWM/init.py", line 115, in add_channel_pulse
return _PWM.add_channel_pulse(dma_channel, gpio, start, width)
RuntimeError: Error: cannot add pulse to channel 99999: width_start+width exceed max_width of 0
Is it currently possible to use the BOARD numbering scheme with interrupts? It doesn't currently seem to work.
I tried to set an interrupt on GPIO 2 (BOARD 3). When using RPIO.setmode(RPIO.BOARD)
and add an interrupt callback to pin 3, I get an InvalidChannelException
("not a valid pin").
With RPIO.BCM
and pin 2 it works though. Which is a little strange as pin 3 would be a valid GPIO pin with BCM numbering too.
Is this some bug? Do the interrupts not support the BOARD numbering?
When I open and close DMA channels repeatedly, Raspberry PI hangs.
This issue is observed rapidly when initializing 2 DMA channels, closing the channels and reopening them rapidly afterwards.
Seems to have a timing issue and concurrent access between closing and opening (accessing an illegal pointer?)
I have also observed a segfault when doing this with the inteactive python command line.
Please add support for model B+.
To start with, calling RPIO.sysinfo()
in Python, returns a key error, because the MODEL_DATA dictionary doesn't have an entry for model B+ (key '10').
With an active PWM channel modulating pins 23, 24 and 25, rpio-curses
crashes on startup with the following stacktrace:
Traceback (most recent call last):
File "/usr/local/bin/rpio-curses", line 5, in
pkg_resources.run_script('RPIO==0.10.0', 'rpio-curses')
File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 499, in run_script
self.require(requires)[0].run_script(script_name, ns)
File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 1235, in run_script
execfile(script_filename, namespace, namespace)
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/EGG-INFO/scripts/rpio-curses", line 495, in
main()
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/EGG-INFO/scripts/rpio-curses", line 461, in main
d.start()
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/EGG-INFO/scripts/rpio-curses", line 417, in start
self.draw()
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/EGG-INFO/scripts/rpio-curses", line 176, in draw
screen.addstr(pos_y, POS_GPIOLIST_X+9, "%s " % (GPIO_FUNCTIONS[func]), curses.color_pair(3) if func == 4 else 0)
KeyError: 6
Same for rpio -I
:
GPIO 2: INPUT (1)
GPIO 3: INPUT (1)
GPIO 4: INPUT (1)
GPIO 7: INPUT (0)
GPIO 8: INPUT (0)
GPIO 9: INPUT (0)
GPIO 10: INPUT (0)
GPIO 11: INPUT (0)
GPIO 14: ALT0 (1)
GPIO 15: ALT0 (1)
GPIO 17: INPUT (0)
GPIO 18: INPUT (0)
GPIO 22: INPUT (0)
GPIO 23: OUTPUT (0)
GPIO 24: OUTPUT (1)
GPIO 25: OUTPUT (1)
GPIO 27: INPUT (0)
Traceback (most recent call last):
File "/usr/local/bin/rpio", line 5, in
pkg_resources.run_script('RPIO==0.10.0', 'rpio')
File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 499, in run_script
self.require(requires)[0].run_script(script_name, ns)
File "/usr/lib/python2.7/dist-packages/pkg_resources.py", line 1235, in run_script
execfile(script_filename, namespace, namespace)
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/EGG-INFO/scripts/rpio", line 345, in
main()
File "/usr/local/lib/python2.7/dist-packages/RPIO-0.10.0-py2.7-linux-armv6l.egg/EGG-INFO/scripts/rpio", line 225, in main
RPIO._RPIO.GPIO_FUNCTIONS[f],
KeyError: 6
In March I did an apt-get update, apt-get upgrade, and apt-get dist-upgrade prior to installing database software. I had GPIO 28 on the P5 header programmed as a interrupt callback using RPIO and it stopped working. I noticed one message that said interrupt 50 was disabled in the kernel. I moved the wire to GPIO 11 on the P1 header, edited the program and it worked as before. I checked GPIO 29 on the P5 header and it did not work as an interrupt either. I don't know if the P5 pins work as standard IO points. I assume that the upgrades caused the problem, I2C was also disabled but I was able to turn it back on using raspi-config. Any ideas on how to make the P5 pins usable again?
Thanks
root@raspberrypi ~ #rpio-curses
Traceback (most recent call last):
File "/usr/local/bin/rpio-curses", line 93, in
"Maker: %s") % RPIO.sysinfo()
File "/usr/local/lib/python2.7/dist-packages/RPIO/init.py", line 183, in sysinfo
return (RPI_REVISION_HEX,) + MODEL_DATA[RPI_REVISION_HEX.lstrip("0")]
KeyError: '10'
Looks like the model data doesn't exist for the B+ in the MODEL_DATA dictionary.
MODEL_DATA = {
'2': ('B', '1.0', 256, '?'),
'3': ('B', '1.0', 256, '?'),
'4': ('B', '2.0', 256, 'Sony'),
'5': ('B', '2.0', 256, 'Qisda'),
'6': ('B', '2.0', 256, 'Egoman'),
'7': ('A', '2.0', 256, 'Egoman'),
'8': ('A', '2.0', 256, 'Sony'),
'9': ('A', '2.0', 256, 'Qisda'),
'd': ('B', '2.0', 512, 'Egoman'),
'e': ('B', '2.0', 512, 'Sony'),
'f': ('B', '2.0', 512, 'Qisda')
}
I'm running python 2.7 on the latest raspian on a Raspberry Pi B+.
https://github.com/metachris/RPIO/blob/master/source/c_pwm/pwm.c#L462 :
return fatal("Error: cannot add pulse to channel %d: width_start+width exceed max_width of %d\n", channels[channel].width_max);
This prints max_width
as channel and nothing as max width.
Hi. I am developing a pi based analog to digital device for the neuroscience lab where I work (Swartz Center for Computational Neuroscience). In addition to having multiple analog inputs (I use the TI ads1015 and go through I2C) it is to generate a TTL pulse for triggering purposes. I found this library and just dropped pwm.c and pwm.h into my project folder, commented out the main function and compiled it as a library so that my application (C based) can generate the desired signal. This took all of 5 minutes and it works beautifully with all the modularity I need. Thank you so much for such an excellent utility and a project that is so well set up! This is how all code should be.
-David Medine
When using RPIO in a script with Subprocess, closing a Subprocess will shutdown the main script, Without RPIO the script will continue as normal.
http://bpaste.net/show/LfCDZvxOafzkkGydj6xA/
Maybe it is the .kill() in subprocess ?
When changing pulses with add_channel_pulse() it can take a long time (up to half a second?) until the change is actually applied (see also raspberrypi/linux#476). I believe this is because the changed pulses will only be used for dma when the related cache lines get evicted from the cpu cache - this fits with the description in the issue I linked above, where some activity (for example io) can somewhat mitigate the issue. My workaround currently is to always use a very long subcycle time (and repeating the actually desired subcycle within that long subcycle), so that the whole cycle does not fit in cache. This does solve the problem, but a better solution would be to somehow avoid the cache altogether, though I have no idea if that is possible from userspace (in kernelspace dma_alloc_coherent might be used).
Have you experienced similar issues?
I want to make a LED blink with a period of 2 seconds, and I would like the hardware to handle this, just like I can turn it on and off with RPi.GPIO and let my Python script exit. (With RPi.GPIO pin configuration and LOW/HIGH state is retained after script exits)
Using RPIO.PWM I can sucesfully configure the desired PWM signal.
The issue arises when I let my script exit: The PWM signal disappears.
I asume it is related to some DMA cleanup. Does anyone have some idea as to how this can be fixed?
I'll hapilly work on it myself, but some input as to where to dive in would be great!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.