Arduinoで複数のロータリーエンコーダを使う

記事内に広告が含まれています。

こんな感じのロータリーエンコーダを使います。

↑前回の記事【ロータリーエンコーダの回転数を読み取る方法】

上の方法ではピン変化割り込みを使うので複数のロータリーエンコーダの値を読み取ることができない。 (Arduino Unoの場合、2,3番ピンのみでしかattachInterrupt()が使えない )

スポンサーリンク

タイマー割り込みでロータリーエンコーダの値を読み取る

どうしても複数のロータリーエンコーダを使いたい場合、タイマ割り込みを用いてピン変化を監視すれば無理やり読み取ることはできます。3つのエンコーダから値を読み取ってみます。

3エンコーダ配線図

下のスケッチでは8~13番ピンを読み取りに使っています。

#define PIN_1A 8
#define PIN_1B 9
#define PIN_2A 10
#define PIN_2B 11
#define PIN_3A 12
#define PIN_3B 13
const int8_t ENCODER_TABLE[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
//エンコーダ1
volatile bool StatePin1A = 1;
volatile bool StatePin1B = 1;
volatile uint8_t State1 = 0;
volatile long Count1 = 0;
//エンコーダ2
volatile bool StatePin2A = 1;
volatile bool StatePin2B = 1;
volatile uint8_t State2 = 0;
volatile long Count2 = 0;
//エンコーダ3
volatile bool StatePin3A = 1;
volatile bool StatePin3B = 1;
volatile uint8_t State3 = 0;
volatile long Count3 = 0;
ISR(TIMER2_COMPA_vect){
  //エンコーダ1読み取り
  StatePin1A = PINB & 0b00000001;//8番ピン
  StatePin1B = PINB & 0b00000010;//9番ピン
  State1 = (State1<<1) + StatePin1A;
  State1 = (State1<<1) + StatePin1B;
  State1 = State1 & 0b00001111;
  Count1 += ENCODER_TABLE[State1];
  //エンコーダ2読み取り
  StatePin2A = PINB & 0b00000100;//10番ピン
  StatePin2B = PINB & 0b00001000;//11番ピン
  State2 = (State2<<1) + StatePin2A;
  State2 = (State2<<1) + StatePin2B;
  State2 = State2 & 0b00001111;
  Count2 += ENCODER_TABLE[State2];
  //エンコーダ3読み取り
  StatePin3A = PINB & 0b00010000;//12番ピン
  StatePin3B = PINB & 0b00100000;//13番ピン
  State3 = (State3<<1) + StatePin3A;
  State3 = (State3<<1) + StatePin3B;
  State3 = State3 & 0b00001111;
  Count3 += ENCODER_TABLE[State3];
}
void setup() {
  pinMode(PIN_1A, INPUT_PULLUP);
  pinMode(PIN_1B, INPUT_PULLUP);
  pinMode(PIN_2A, INPUT_PULLUP);
  pinMode(PIN_2B, INPUT_PULLUP);
  pinMode(PIN_3A, INPUT_PULLUP);
  pinMode(PIN_3B, INPUT_PULLUP);
  TCCR2A = 0b00000010;//タイマ2比較一致
  TCCR2B = 0b00000010;
  OCR2A  = 200;//0.1msごとに割り込み
  TIMSK2 = 0b00000010;
  Serial.begin(9600);
}

void loop() {
  Serial.print(Count1);
  Serial.print(" ");
  Serial.print(Count2);
  Serial.print(" ");
  Serial.println(Count3);
}

処理速度を上げるため、digitalRead()の代わりにPINB & 0b00000001と表記しています。ほかのピンを使いたい場合は以下で解説しています。

手で回した範囲では読み飛ばしはありませんでしたが、高速で回す場合はOCR2A とTCCR2Bで割り込み周期を調整しましょう。

処理速度が足りない場合

処理速度が足りない場合は性能の良いボードに変えましょう。↓のArduino Dueだと全ピンでピン変化割り込みが使えるので、複数のロータリーエンコーダを使うにはその方が良いかもしれません。

あとは最近だとesp32がおすすめです。Arduino IDEが使えて、とても高性能です。

コメント