ロータリーエンコーダをArduinoでエミュレートする
📕

ロータリーエンコーダをArduinoでエミュレートする

Tags
Arduino
switch
Published
February 6, 2022

ロータリーエンコーダとは

回転を検出できるスイッチです。
notion image
物理ユーザーインターフェイス面で使いやすいスイッチです。回転動作でページ切り替えなどに使ったりします。

スイッチの動作について

AとBはスイッチになっています。ロータリーエンコーダを回すと2つのスイッチがONになったりOFFになったりします。この2つのスイッチの状態(ON/OFF)を使い、前回の状態と今回の状態を比較することで回転方向を検出します。
notion image
Arduinoで使う場合は以下のライブラリが手軽でいいです。
Encoder
PaulStoffregenUpdated Aug 30, 2024
#include <Encoder.h> // Change these two numbers to the pins connected to your encoder. // Best Performance: both pins have interrupt capability // Good Performance: only the first pin has interrupt capability // Low Performance: neither pin has interrupt capability Encoder myEnc(5, 6); // avoid using pins with LEDs attached void setup() { Serial.begin(9600); Serial.println("Basic Encoder Test:"); } long oldPosition = -999; void loop() { long newPosition = myEnc.read(); if (newPosition != oldPosition) { oldPosition = newPosition; Serial.println(newPosition); } }

AとBの4つの状態

notion image
時計回りの場合は 0010110100というように変化していきます。
反時計回りの場合はその逆ですね。
ABの状態を2進数から10進数に変換すると0123という状態になります。
notion image

ロータリーエンコーダをエミュレートする

00 10 11 01の4つの状態を順番に切り替えていくとエミュレートできそうですね。
ビット演算を使うとこんな感じでエミュレートできそうです。
#define pinA 3 #define pinB 4 #define SERIALCHECK void setup(){ pinMode(pinA,OUTPUT); pinMode(pinB,OUTPUT); Serial.begin(115200); } void loop(){ for (uint8_t i = 0; i < 4; i++) { digitalWrite(pinA,(bool)(i >> 1)); digitalWrite(pinB,(bool)(i & 1)); delay(100); #ifdef SERIALCHECK Serial.print("i:"); Serial.print(i); Serial.print(" state:"); Serial.print((bool)(i >> 1)); Serial.println((bool)(i & 1)); #endif } }

シリアルモニタ出力

i:0 state:00 i:1 state:01 i:2 state:10 i:3 state:11

参考になりそうな記事

次の成長をしたい人向け。もっと低いレイヤが気になる人へ。

手実装でロータリーエンコーダ読み取った人

Arduinoでロータリーエンコーダー
「ロータリエンコーダーなんて懐かしいブツのためにライブラリ使うこともないわなー」 ...と考えていたこともありました。さがすより作った方が速いわw ...なんて。 いえ、結局自分で作ったんですけどね...ちゃんと動くまで2時間ぐらいかかりました。 あちこちで書かれているので簡単にまとめると、ロータリーエンコーダは位相の90度ずれた2つのスイッチからの信号を元にして、どっち向きにどのぐらい回転したかを検出するデバイスです。まぁ回転とは限らないのですが、ほとんど回転物で使われます。 2つのスイッチからの信号を2ビットのデータとみなした場合、正回転だと値 0▶1▶3▶2 と変化します。逆回転だと 2▶3▶1▶0 ですね。0123あるいは3210と変化してくれればまだ簡単なのですが、これは一種のグレイコードというもので状態の変化(この場合は回転)で一度に1ビットずつしか変わらないようにしているものです。1ビットしか変わらないので、チャタリングが起こっても値がどったんばったんすることがないというスグレモノ。 なので、今回はこれを読んだ値>順番値に変換します int readEncoder() { const byte gray[] = {0, 1, 3, 2}; return gray[(digitalRead(EncoderA) << 1) | digitalRead(EncoderB)]; } これでめでたく0,1,2,3の値が返ってきます。 あとは、両方のピンに対して割り込みを指定し void attachEncoder() { attachInterrupt(digitalPinToInterrupt(EncoderA), encoder, CHANGE); attachInterrupt(digitalPinToInterrupt(EncoderB), encoder, CHANGE); } 割り込みを受け付けるルーチンではこんな感じに増分と繰り上がりを処理します。 void encoder() { detachEncoder(); delay(10); prevGray = currentGray; currentGray = readEncoder(); if (currentGray
Arduinoでロータリーエンコーダー

2進数って何?という人

オシロスコープで確認できるミクロな問題(チャタリングなどについても触れられています)

エミュレートしたいシーン

3Dプリンタのモード切り替えスイッチにロータリーエンコーダが使われています。
壊れた場合にでもどうぞ。
notion image