本文を読み飛ばす

arm-box: Raspberry Pi + python でボタン判定を行う

ポイント

  • pull-upを忘れない

  • 長押しの判定も作ってみた

  • tickのwrapに対応

ちょっとchatteringの対応が不十分っぽいのか \ うまくボタンがとれていない時がある。

処理の流れは適当に作ったけど、もうちょっとしっかり考えた方がよかったかな...

処理の流れ

  1. event

  2. 前回からの経過時間算出 (tick - tick^-1)

  3. on: 前回押下あり? -> chattering以外なら、timeout再開

  4. on: chattering時間内 -> 無視

  5. on: 前回押下を記録・timeout起動

  6. off: 前回押下なし -> 無視

  7. off: chattering時間内 -> 無視

  8. off: それ以外 -> pres確定

  9. off: pres時: 前回押下の記録削除

  10. timeout: 前回押下なし -> 無視

  11. 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
宣伝: