5

/sys/class/gpio/gpio##/valueGPIOピンを監視しようとしています.Linuxのドキュメントに従って、次のファイルを監視することでこれを実行できるはずです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

私はRubyでこれをやろうとしています.IO.Selectのドキュメントに従ってselect(2).

したがって、この知識を使用して、次のテストプログラムをまとめました。

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

ただし、ピンの変化は検出されません。このアプリを起動すると、すぐにifブロックに入り、ピンの現在の値が表示され、5 秒ごとにtimeout.

ドキュメントを間違って読んだことがありますか?selectこれを監視することはできませんか?

4

1 に答える 1

5

GPIOselectピンで正しくトリガーするには、ピンのエッジ トリガーを設定する必要があります。GPIOドキュメントから:

"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.

Rubyでは単純に:

File.open("/sys/class/gpio/gpio17/edge", "w") { |f| f.write("both") }

上記の完全な例は次のようになります。

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
于 2013-01-12T19:16:57.093 に答える