I looked at the example code for doing I/O using the GPIO pins, but — I need to be able to count impulses (between 0.01 and 250Hz), which isn't really doable with GPIO polling on a multitasking OS.
Are the GPIO pins capable of generating interrupts?
I looked at the example code for doing I/O using the GPIO pins, but — I need to be able to count impulses (between 0.01 and 250Hz), which isn't really doable with GPIO polling on a multitasking OS.
Are the GPIO pins capable of generating interrupts?
Yes they can generate interrupts, and just yesterday some example code was posted. Note, I do not know whether 250 Hz pulses (4 msec interval) will always be reliable, depending on what other operations the R-Pi is doing (SD card I/O, USB and Ethernet, etc.) although you may be able to change interrupt priority if needed.
Thanks for the link!
I thought about it some more, and then remembered that this is Linux, where you deal with interrupts in kernel space, possibly creating an interface to user-space.
I think for the moment it is actually simpler for me to use a MSP430-based Launchpad board to do the counting and interface it via SPI to the Raspberry.
Thanks for the link!
I thought about it some more, and then remembered that this is Linux, where you deal with interrupts in kernel space, possibly creating an interface to user-space.
I think for the moment it is actually simpler for me to use a MSP430-based Launchpad board to do the counting and interface it via SPI to the Raspberry.
I was doing some experiments last night with a 555 timer set for around 1500 Hz connected to a GPIO on the pi, and a modification of the irq demo program linked from this page:
http://www.raspberrypi.org/phpBB3/viewtopic.php?f=44&t=7509
I used gettimeofday to time the interval between interrupts, and was getting numbers quite close (within 1% probably) of the frequency based on what I was reading from the frequency counter on my multimeter also attached to that input. CPU utilization was around 6-7%.
--bob
That's a very interesting experiment. The question then is: Why are you getting a 1% difference?
Is the crystal on the RPI inaccurate? Are you missing interrupts? Is the multimeter inaccurate?
If you are just measuring the interval to be about 700 microseconds, and then doing 1/interval and getting 1500+/- 15 each time, you're not missing interrupts. If you count interrupts for a long enough period, maybe 1 day of wallclock or ntp-synced time, then you should be able to calibrate the crystal of the raspberry pi.
The inter-interrupt times wandered around a central value (that wander is what I was estimating as 1%). This was a very sloppy experiment so I don't have any stored data to look back on. My assumption is that there's variation in the latency between the low-level GPIO interrupt and the time at which the userland code is able to take action, since the linux scheduler is involved (and there's a context switch required etc).
Hi,
Sorry to "break in" to this discussion but I've been trying to get the "gpio-irq-demo" program to work with no success, and it appears that you've got it (or some version of it) working just fine :-).
i fetched the code from here: http://dev.mrkva.eu/rpi/gpio-irq-demo.c
The poll() call always just times out - the program doesn't detect the rising or falling signal edge. Its probably something silly or obvious, but I've spent a few hours and no luck - can you help?
I'm running on the latest apt-get updated Raspbian Wheezy kernel on a Rev 2 Pi which i understand includes the kernel patch for interrupt support (right?). I'm using GPIO pin 17 (aka WiringPi pin 0) and have verified that i can read it using the "gpio" utility. e.g.
$ gpio mode 0 in
$ gpio read 0 # returns the correct 0 or 1 if pin is at ground or Vcc
# now pull the pin to ground
$ gpio edge 0 rising
$ ./gpio-irq-demo 17 # program is using the BCM pin numbers...
value is 0
timeout
timeout
# but when i pull the pin up to Vcc, i don't get the "interrupt, value is: " message
Any idea what is wrong?
thanks for your help!
Don
Hm, not offhand. However I did do the pin configuration directly using the /sys/class/gpio interface, not through wiring. Something like
echo 17 > /sys/class/gpio/export
echo rising > /sys/class/gpio/gpio17/edge
I forget if I had to set the pin direction as well, but I suspect it defaults to in.
hmmm. i was getting "permission denied" (even with sudo) trying to use the "echo" commands with /sys/class/gpio so opted for the gpio route. I think I saw some discussions somewhere about how to work around this, but can you let me know what you did?
It would also be really appreciated if you could send me your interrupt code - I'm new to this site, not sure how that is done...
thx
Don
You do need to run the commands as root ("sudo bash" will get you a root shell). My code is sitting on my pi which is powered off on my workbench - will put a copy up when I have it online next.
Eueka! "sudo bash" did the trick - thanks. Next step is to use threads so my main program can continue to run. I will have to handle multiple inputs - I need to count pulses coming in on several GPIO pins. I think i saw some example code (wfi.c) that does this, but I couldn't get it to work - probably for the same reason that I couldn't get gpio-irq-demo.c to work. Good news is that the frequency i need to handle is really low - not more than a few pulses per second.
If you have any example code that you think might help, let me know...
My application, by the way, is an aquarium control system - I will be building sensors that will allow me to count CO2 bubbles (for a CO2 injector) and water drips (for a Nitrate filter), read Ph and ORP sensors, and control some valves to maintain specific levels.
Thanks again for your assistance.
Don
This sounds like a classic event driven application (you have events coming in triggered by interrupts from your bubble/drip sensors, and presumably from one or more timers that drive periodic checks and maintenance that will turn valves on and off).
If I was writing this software for myself I'd probably not write it in C but rather use something like perl and the timer / event libraries that are available for it. I'm sure there are such event libraries for any of the scripting languages. The advantage of doing it with one of these languages is that the volume of code will be much smaller and the logic will be easier to represent. With the rates you are talking about performance will not be a problem at all.
--bob
Hi Bob,
you are almost certainly correct, but being an old C programmer with minimal Perl expertise, I'm just more comfortable with that language. Something about an old dog and new tricks?
Meanwhile, I've made good progress in C - i am able to read a temperature sensor (varistor) via an adc on the I2C bus, handle a pulse counter using edge-triggered interrupts and poll(), read an ORP probe via the Pi's serial port, and turn off/on some relays. Next step is to start using threads to take the pulse counter out of the main program loop, put the whole thing together, and actually hook it up to the tank...
regards
Don