arm-box: Raspberry Pi + python でボタン判定を行う
ポイント
pull-upを忘れない
長押しの判定も作ってみた
tickのwrapに対応
ちょっとchatteringの対応が不十分っぽいのか \ うまくボタンがとれていない時がある。
処理の流れは適当に作ったけど、もうちょっとしっかり考えた方がよかったかな...
処理の流れ
event
前回からの経過時間算出 (tick - tick^-1)
on: 前回押下あり? -> chattering以外なら、timeout再開
on: chattering時間内 -> 無視
on: 前回押下を記録・timeout起動
off: 前回押下なし -> 無視
off: chattering時間内 -> 無視
off: それ以外 -> pres確定
off: pres時: 前回押下の記録削除
timeout: 前回押下なし -> 無視
timeout: それ以外 -> hold確定
プログラム:
def tick_delta(prev, curr): # {{{1
# type: (int, int) -> int
if prev > curr:
curr += 2 ** 32
ret = curr - prev
return ret
class buttons:
def regist_simple(self, chs, func): # {{{1
# type: (List[int], Callable[[int], bool]) -> None
def callback_hold(ch): # {{{2
if self.tick < 0:
return # already released
self.tick = -1
if ch not in self.cbs_hold:
return
self.cbs_hold[ch](ch)
def callback_press(pin, lv, tick): # {{{2
d = tick_delta(self.tick, tick)
ch = self.pins.index(pin)
if lv == self.lv_release:
if self.tick < 0:
# not pressed, just ignore...
# or hold callback alerady called by timer.
return
if d < self.usec_chatter:
return # just ignore the new button for chattering
self.timer_cancel()
self.tick = -1
func(ch)
return
if self.tick > 0:
if d < self.usec_chatter:
return # ignore chattering.
elif self.timer is not None:
self.timer_cancel()
if self.timer is None:
self.timer = Timer(self.sec_hold, callback_hold, args=[ch])
self.timer.start()
self.tick = tick # 1st holded button!
# }}}
# active = edge to low.
for ch in chs:
if ch >= len(self.pins):
continue
pin = self.pins[ch]
self.io.set_mode(pin, pigpio.INPUT)
self.io.set_pull_up_down(pin, pigpio.PUD_UP)
self.io.callback(pin, pigpio.EITHER_EDGE, callback_press)
print("registerd function for GPIO {} as {}ch".format(pin, ch))
コメント
Comments powered by Disqus