I am attempting to monitor a GPIO pin, and per the Linux docs I should be able to do this by monitoring the /sys/class/gpio/gpio##/value
file with select
:
"value" ... reads as either 0 (low) or 1 (high). If the GPIO
is configured as an output, this value may be written;
any nonzero value is treated as high.
If the pin can be configured as interrupt-generating interrupt
and if it has been configured to generate interrupts (see the
description of "edge"), you can poll(2) on that file and
poll(2) will return whenever the interrupt was triggered. If
you use poll(2), set the events POLLPRI and POLLERR. If you
use select(2), set the file descriptor in exceptfds. After
poll(2) returns, either lseek(2) to the beginning of the sysfs
file and read the new value or close the file and re-open it
I am attempting to do this in Ruby, and per the IO.Select documentation it calls select(2)
.
So, with this knowledge I threw together the following test program:
fd = File.open("/sys/class/gpio/gpio17/value", "r")
loop do
rs,ws,es = IO.select(nil, nil, [fd], 5)
if es
r = es[0]
puts r.read(1)
else
puts "timeout"
end
end
However, it does not detect any pin changes. When I launch this app it will immediately fall into the if
block and display the pin's current value, and then every 5 seconds just prints timeout
.
Have I read the docs wrong? Shouldn't select
be able to monitor this?
Before select
will correctly trigger on a GPIO pin you'll need to setup the pin's edge trigger. From the GPIO docs:
"edge" ... reads as either "none", "rising", "falling", or
"both". Write these strings to select the signal edge(s)
that will make poll(2) on the "value" file return.
This file exists only if the pin can be configured as an
interrupt generating input pin.
In Ruby simply:
File.open("/sys/class/gpio/gpio17/edge", "w") { |f| f.write("both") }
The complete example from above would look like:
fd = File.open("/sys/class/gpio/gpio17/value", "r")
File.open("/sys/class/gpio/gpio17/edge", "w") { |f| f.write("both") }
loop do
rs,ws,es = IO.select(nil, nil, [fd], 5)
if es
r = es[0]
puts r.read(1)
else
puts "timeout"
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With