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