[英]Blocking read on GPIO from Python: How to block using epoll() and select.EPOLLET
我正在嘗試在嵌入式系統(ARM內核)上從Python訪問GPIO,該嵌入式系統運行的是使用Buildroot(內核4.1.15)構建的linux。
我希望我的代碼阻塞以等待GPIO2上的引腳更改(即,我不想通過重復調用“ read”來輪詢該引腳)。 我正在嘗試在邊緣觸發模式下使用“ epoll”來做到這一點:
有關epoll的信息,請參見Python文檔 。 select.EPOLLET標志用於獲取epoll的邊沿觸發。 另請參閱Linux文檔以了解epoll 。
為簡單起見,我已經使用sysfs從控制台設置了GPIO引腳:
# cat /sys/class/gpio/gpio2/direction
in
# cat /sys/class/gpio/gpio2/edge
rising
這是我的Python代碼:
#!/usr/bin/env python
# coding=utf8
from time import sleep
import select
import sys
if __name__ == '__main__':
try:
pinIn = open("/sys/class/gpio/gpio2/value", "r")
except IOError:
print("Error setting up GPIO pin")
sys.exit()
myPoll = select.epoll()
myPoll.register(pinIn.fileno(), select.EPOLLPRI | select.EPOLLET)
while(1):
events = myPoll.poll(4)
print("EPoll result: %s" % (str(events),))
for fd, event_type in events:
print("FD: %d; Events: %d" % (fd, event_type))
if event_type & select.EPOLLIN:
print("-EPOLLIN!")
if event_type & select.EPOLLPRI:
print("-EPOLLPRI!")
if event_type & select.EPOLLERR:
print("-EPOLLERR!")
value = pinIn.read(1)
pinIn.seek(0)
print("--> %s" % (str(value),))
sleep(1)
為了進行測試,我以每個周期大約2秒的時間從信號發生器向輸入引腳饋送方波,這樣我就可以看到引腳何時發生變化。
當我在嵌入式系統上運行它時,我得到了:
# python3 /usr/sbin/test-gpio-python.py
EPoll result: [(3, 10)]
FD: 3; Events: 10
-EPOLLPRI!
-EPOLLERR!
--> 0
代碼在1秒鍾的睡眠中進入睡眠狀態,然后在下一次迭代中,poll()立即返回並且不會阻塞。 由於我的輸入每2秒僅在一個上升沿上運行,因此應該阻塞。
為什么“ poll()”不被阻止?
====編輯:====
最初,當我嘗試使用“ select.EPOLLET”時,代碼導致了一個奇怪的錯誤:
OverflowError: can't convert negative value to unsigned int
但是,我發現我不小心使用了myPoll = select.poll()而不是epoll() 。 代碼現已修復。
我決定通過查看/ proc / interrupts來檢查中斷信息。
在這里,GPIO引腳的邊沿設置為“上升”后僅幾秒鍾:
# cat /proc/interrupts
...
33: 421 gpio-mxc 2 Edge gpiolib
...
嗯,已經發生了421次中斷!
兩秒鍾后:
# cat /proc/interrupts
...
33: 852 gpio-mxc 2 Edge gpiolib
...
那可以解釋。 中斷的堆積速度約為每秒400個,絕對比我在Python中處理它們的速度快。
在示波器上進行的進一步研究表明,信號發生器的輸出僅為1.6 V,看起來噪聲正在觸發設備上的輸入電路。
當我切換到正確的信號發生器輸出並在GPIO引腳上獲得干凈的信號時,我開始獲得預期的中斷數,並且python代碼正常工作(即poll()在輸入的上升沿之間正確地阻塞了)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.