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

![SS 192.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565043/a41cd967-f549-8677-1efa-2e99bf69518d.png) ロータリーエンコーダを簡単に使いたいよう

## やること
Arduinoでロータリーエンコーダを使います。
2,3ピンはI2Cで使用したいので、今回は9,10ピンを使った割り込み処理を試します。
ロータリーエンコーダの信号読み取りはライブラリの [Encoder Library](https://www.pjrc.com/teensy/td_libs_Encoder.html) を利用します。

## ロータリーエンコーダーとは？
回転量を信号に置き換える電子部品です。時計回り、反時計回りも検出できます。
ボリュームと違って360度以上、何回転でもグルグルと回せるのが良いところです。
絶対値を出力するアブソリュート型と相対的な回転量をパルスで出力するインクリメンタル型があります。
今回使う[EC10E](https://akizukidenshi.com/catalog/g/gP-15228/)はインクリメンタル型です。


## 準備物・実施環境
- Arduino系のもの（今回はMICRO。UNO R4の場合の注意は最後の方に）
- ロータリーエンコーダ　秋月で1個50円の[EC10E](https://akizukidenshi.com/catalog/g/gP-15228/)
- ライブラリ　Encoder,TimerOne, MsTimer2


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565043/be6f879f-55bc-9746-8e2c-5a505ce2705d.png" width = 300>
ロータリーエンコーダーEC10Eは、写真のように銀色の面をオモテ、足を下にした時、
左の足 C : GND
中の足 B : Output signal B 
右の足 A : Output signal A 
となります。ちなみにEC10Eはマウスホイール用のパーツらしいです。


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565043/f9be17e6-c3ed-99fb-0e04-5be0832320ab.png" width = 300>
EC10Eの真ん中の六角穴は2mm径となります。ミニ四駆用のシャフトがピッタリ入るので、写真のギアと組み合わせればクリクリできるようになります。


## 接続
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565043/09161eca-e549-20f4-f8b3-68da83e6a2e6.png" width = 400>
A はArduino 9番ピンに接続し、さらにそこから10kΩの抵抗を5Vに接続します。
B はArduino 10番ピンに接続し、同上。
GNDはArduino GNDに接続します。
(図では赤いラインがVINへの接続になっていますが、正しくは5Vです。)

この接続方法は簡易的なものです。
よりよい結果を出すためのフィルタ回路例も公式にあります↓
https://tech.alpsalpine.com/prod/j/html/encoder/incremental/ec10e/ec10e_common.html


## プログラム

#### Arduino系のスケッチその１：MsTimer2 を使う場合　

```c++:Arduino

#include <MsTimer2.h> //タイマーライブラリの読み込み
#include <Encoder.h> //ロータリーエンコーダライブラリの読み込み
 
Encoder myEnc(9, 10); //ロータリーエンコーダ信号に使うピンを9,10に設定
volatile long oldPosition  = -999; //割り込み処理で使う変数はvolatileにすると安心
volatile long newPosition  = 0;

void RotEnc() { //割り込み処理の関数
                //ライブラリで得たロータリーエンコーダの数値をキープするだけ
  newPosition = myEnc.read();
}

void setup() {
  Serial.begin(115200);
  //割り込み処理の設定
  MsTimer2::set(1, RotEnc); //1ms(ミリ秒)で設定
  MsTimer2::start();
}
 
void loop() {
  //ロータリーエンコーダの数値が変化した時だけシリアルに出力
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
    Serial.println(newPosition);
  }
}
```
割り込み速度が1msなので手で回す分には十分使える分解能です。
でも他の処理に影響が出るかも？


#### Arduino系のスケッチその２：TimerOne を使う場合

```c++:Arduino

#include <TimerOne.h> //高性能なタイマーライブラリの読み込み
#include <Encoder.h>
 
Encoder myEnc(9, 10);
volatile long oldPosition  = -999;
volatile long newPosition  = 0;

void RotEnc() {
  newPosition = myEnc.read();
}

void setup() {
  Serial.begin(115200);
  Timer1.initialize(25); //25μs(マイクロ秒)で設定
  Timer1.attachInterrupt(RotEnc);
}
 
void loop() {
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
    Serial.println(newPosition);
  }
}
```
25μs(40kHz)で値を取得します。これぐらいあるとロータリーエンコーダ的には安心ですが、割り込み回数が多くなるのでやっぱり他の処理に影響が出るかも？？


## 実行

スケッチをArduinoに書き込んだらそのままシリアルモニタを開きます。
うまくいけばロータリーエンコーダをクリクリと回した分だけ、シリアルモニタに数値が表示されます。回転方向により、数値が増えたり減ったりします。


## ところで何がしたかったのか
廉価な倒立振子を試作しようとしていて、ロータリーエンコーダーが必要になりました。
ミニ四駆用のギアは歯の大きさがタミヤの工作シリーズのギアボックスのものと噛み合うので、3Dプリンタなどと組み合わせれば下記のようにホイールの回転量を調べることができます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565043/caaae5f9-7dbb-a4bb-185c-5b7c2d24da5b.png" width = 300>
EC10Eはクリックが重いので、金属の板を一旦外し、クリック用の突起を万力で挟んでたいらにしてから使っています。

## これちゃんと動くのか
[Encoder Library](https://www.pjrc.com/teensy/td_libs_Encoder.html)の解説文にある「Low Performance Polling Mode」としての使用になります。
プログラムのところにも書きましたが、割り込み回数を増やすことで精度をアップしようとしているので、他の処理との関係がうまく行くかちょっと心配です。
手元ではI2Cやシリアル書き込みと同居できているようですが、処理を書き足していくうちに不具合が生じるようになるかもしれません。

## Arduino UNO R4の場合

Arduino UNO R4では内部処理が変わってしまったようで、2023年10月時点では前述のライブラリが動かないようです。下記のライブラリであれば動くようですのでお試しください。
https://reference.arduino.cc/reference/en/libraries/rotaryencoder/


## 参考URL
下記のサイト/記事を参考にさせていただきました。

- [Arduinoでロータリーエンコーダーの動作確認](http://funcs.org/1789)
- [Encoder Library](https://www.pjrc.com/teensy/td_libs_Encoder.html)
- [Arduinoでロータリーエンコーダを使いたい話](https://qiita.com/trancingyou/items/4c0504604bab3efcd6f1)
- [Arduinoのタイマー割り込みライブラリの調査](https://qiita.com/hnw/items/67988f0c21c29df8ee15)
- [Arduinoのタイマー調査](https://qiita.com/wdice02136/items/3d5fa55c55a60d16725b)
- [miso-engine : Arduinoのタイマーライブラリ](https://miso-engine.hatenablog.com/entry/2015/07/20/221014)
- [Fグループ電子工作講座 : エンコーダの取付方法再検討](http://project12513.blog-fps.com/%E5%91%A8%E8%BE%BA%E5%9B%9E%E8%B7%AF%E8%A8%AD%E8%A8%88/%E3%82%A8%E3%83%B3%E3%82%B3%E3%83%BC%E3%83%80%E3%81%AE%E5%8F%96%E4%BB%98%E6%96%B9%E6%B3%95%E5%86%8D%E6%A4%9C%E8%A8%8E)