2025年2月24日月曜日

ロータリーエンコーダのよみとり(エッジ変化の読み取り)

前回までロータリーエンコーダのON,OFFの状態
を見ていたが、今回はOFF→ON(立ち上がり)ON→OFF(立ち下り)
の変化を見てみることにする。
→状態変化をイベントとして受け取ることにより、circuitpythonが
(バタつきなく)正しく読み取っていることを期待するとともに、
よくわからない待ち時間の考慮をなくす。

その前にロータリーエンコーダの仕組みを復習。
ロータリーエンコーダは、それを回すと、
...OFF→ON→ON→OFF→OFF→ON..と状態を4つで
1周期を繰り返すスイッチが2個あり、
それぞれのスイッチは他方より4分の1周期ずれているもの。

前回はスイッチを回したときのスイッチの状態に着目して、
一方のスイッチの状態ともう片方の直前の状態をを比較したときに、
同じであれば順方向、逆であれば逆方向となる都合の良い動きに着目し、
それらを排他的論理和を取ることにより方向を調べていた。

今回はスイッチを回したときのスイッチの変化に着目して、
同時に両方のスイッチは変化しない(スイッチの変化は1個づつ)、
自身の今回の変化(立ち上がり、立ち下り)の方向と
相手側の前回の変化の方向を比較し、
自身がSW1なら過去のSW2の方向変化が同じであれば順方向、違えば逆方向
自身がSW2なら過去のSW1の方向変化が同じであれば逆方向、違えば順方向
となる都合の良い動きに着目する。
前回は起動直後の状態をとれたので、最初からデータを信用できたが、
今回はプログラム起動直前の状態変化は取れないため、
最初の2カウント分の読み取りは破棄する。

ま、このページのものを参考にして
https://learn.adafruit.com/key-pad-matrix-scanning-in-circuitpython/keys-one-key-per-pin

自分用に書き換えたのが以下のプログラム
# SPDX-FileCopyrightText: 2022 Dan Halbert for Adafruit Industries
#
# SPDX-License-Identifier: MIT

import board
import keypad

KEY_PINS = (
    board.GP0,
    board.GP1,
    board.GP2,
    board.GP3,
    board.GP4,
    board.GP28,
    board.GP27,
    board.GP26,
    board.GP5,
    board.GP6,
    board.GP16, #RE1S1
    board.GP17, #RE1S2
    board.GP18, #RE2S1
    board.GP19, #RE2S2
)

keys = keypad.Keys(KEY_PINS, value_when_pressed=False, pull=True)
waitcount=2
isRE1Sw1Raise=False
isRE1Sw2Raise=False
while True:
    event = keys.events.get()
    if event:
        # A key transition occurred.
        #print(event)

        if event.pressed:
            # Turn the key blue when pressed
            if event.key_number == 10 :
                isRE1Sw1Raise=False
                if waitcount > 0:
                    waitcount -=1
                    continue
                if isRE1Sw1Raise == isRE1Sw2Raise : print("UP")
                else : print("DOWN")
            elif event.key_number == 11 :
                isRE1Sw2Raise=False
                if waitcount > 0:
                    waitcount -=1
                    continue
                if isRE1Sw1Raise != isRE1Sw2Raise : print("UP")
                else : print("DOWN")

        # This could just be `else:`,
        # since event.pressed and event.released are opposites.
        if event.released:
            if event.key_number == 10 :
                isRE1Sw1Raise=True
                if waitcount > 0:
                    waitcount -=1
                    continue
                if isRE1Sw1Raise == isRE1Sw2Raise : print("UP")
                else : print("DOWN")
            elif event.key_number == 11 :
                isRE1Sw2Raise=True
                if waitcount > 0:
                    waitcount -=1
                    continue
                if isRE1Sw1Raise != isRE1Sw2Raise : print("UP")
                else : print("DOWN")


結果、クリックなしのロータリーエンコーダでゆっくり目に回すといい感じに読み取るが、
速く回すと、逆方向の検知がされてしまう。

クリックありの方で、コメントのprintを有効にして、その他のprintを無効にした結果、以下のようにまったく使い物にならず。

















期待していたのは、11と10が交互に出るものなんだけどそうなっていない。
10が多いということは、11を拾えていないのか10がバタついているのか、その両方なのかよくわからない。

IncrementalEncoderでクリックありのものはdivisorを4にクリックなしのものはdivisorを2で使うのがよいのかなぁ。


0 件のコメント: