-
Notifications
You must be signed in to change notification settings - Fork 89
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Interrupts #15
Comments
Unless it has changed, EventIO from this project uses a blocking poll loop to check for pin status changes. One better way to do this is with epoll because it lets the kernel take care of notifying your program when a file descriptor - any of them, but it can be tied to a gpio - changes. In the Bone's case this is done in memory/hardware so it never actually touches a file. Bonescript uses epoll, you can do it manually with the epoll library in C, directly from Python (http://scotdoyle.com/python-epoll-howto.html) or, personally I enjoy using Tornado (http://www.tornadoweb.org/) because it comes with the default Bone distribution, you can still use regular PyBBIO in the IOLoop, and it is very cpu efficient. The same single process Tornado IOLoop is able to handle real-time WebSocket clients, regular web traffic, inbound and outbound TCP sockets, scheduled events, and, of course, edge-triggered IO. |
I think I understand that. I saw something else about the gpio driver being able to create Are you just using PyBBIO |
Give it a shot! Install python-tornado through opkg, then configure a GPIO in your shell: Then run a test program like this: import logging, tornado.ioloop, tornado.options
class MyInterrupter (object):
def __init__ (self, loop, gpio_val_path):
self.fd = open (gpio_val_path, "r")
loop.add_handler (self.fd.fileno (), self.int_handler, loop._EPOLLET)
self.interrupt_count = 0
def int_handler (self, fd, events):
# instead of just counting you could read a data line or something else here with bbio
self.interrupt_count += 1
def log_count (self):
# don't print on every count, the overhead could cause us to miss some interrupts if we are blocking on write
logging.info ("interrupt_count is %d" % self.interrupt_count)
tornado.options.parse_command_line ()
loop = tornado.ioloop.IOLoop.instance ()
interrupter = MyInterrupter (loop, "/sys/class/gpio/gpio86/value")
printer = tornado.ioloop.PeriodicCallback (interrupter.log_count, 1000)
printer.start ()
loop.start () |
Nice! I've never worked with Tornado, but this looks really elegant. So it's essentially just abstracted away the epoll API a bit and added some really nice stuff for callback loops, non-blocking IO loops, etc? I'll give it a shot. That should work great for my app. Quick question, and I'll dig through if you don't know off the top of your head, but is there something in PyBBIO's API that will let me write |
If this is on a custom Cape you can store pinmux settings in an EEPROM chip, add some code to the Bone board file in the kernel and rebuild the whole system and etc, etc.. eventually it can configure IO automatically. Otherwise (for dev) I either do it before starting the IOLoop in code or by running a shell script at boot with systemd. I think Bonescript has some utilities for these settings too, but I haven't looked at it much. I would like to reiterate for others that PyBBIO is still very useful with Tornado due to Alexander's memory mapped IO approach. Have fun! |
So, I ended up implementing this directly with epoll (still super-interested in Tornado, just didn't delve into it yet). I haven't had the time to extract the bits and pieces out, but I have a pretty good idea of how to turn it into |
Hey guys, sorry for the delay responding. Hardware interrupts have been on the list for PyBBIO, but I hadn't thought too much about it yet. The EventIO library was a quick first pass at an event loop of sorts, more or less as a proof of concept of what an event-driven API for PyBBIO could look like. I've actually been meaning to rewrite it using Tornado, and having built-in epoll bindings is yet another reason it would be a good fit; thanks for pointing that out bduhan. alanctkc, it would be much appreciated if you wanted to contribute some interrupt code! Do you think it could be integrated into the core API and used without having to change the structure of a PyBBIO program; that is have a Tornado event loop running in a separate thread or process which only handles interrupts, and have the main loop execute normally? |
Cool. I've got a busy weekend, so I'll probably get to it Monday-ish. I think I could incorporate it into the core PyBBIO API pretty easily, with no dependencies. My plan is to add a basic thread, in daemon mode, in the run() method. I'd then just use epoll directly instead of using Tornado at all. If you ever wanted to incorporate Tornado later, it would be trivial to change it, but that way it keeps it simple and only uses core Python for now. The I'll let you know how that goes! |
Err, maybe I'll leave the thread out of the |
Yeah, the idea is to have the API fully support three methods of using PyBBIO: using the Arduino-style setup()->loop() scheme, just importing bbio and calling the bbio_init() and bbio_cleanup() methods explicitly, and importing it into the Python interactive interpreter in which case bbio_init() and bbio_cleanup() are called automatically. The run() function is only used in the first case. I agree leaving Tornado out of the core API is a good idea, I just misread what you said before. |
Interrupt code pulled from Alan, see issue #16. |
The BeagleBone reference manual mentions the possibility of using a hardware interrupt to detect pin changes immediately when they happen. The documentation is sparse, and all I could find was this statement:
Bonescript uses an
attachInterrupt
method, similar to the Arduino to pull it off, although in my experience with it, it seemed spotty.Have you considered moving away from the EventIO model and using interrupts? I'm not sure how to pull it off in Python (signals, maybe?), but it would be extremely helpful for pin changes that last only a few milliseconds.
I'm still not 100% sure I understand how the interrupts work, so maybe they're only doing something similar to your EventIO model anyway, but here's the method I'm talking about in Bonescript:
https://github.com/jadonk/bonescript/blob/master/node_modules/bonescript/index.js#L272
The text was updated successfully, but these errors were encountered: