【倒立振子part7】エンコーダの値を読み取る

前回ブラシレスDCモータを回転させた。
今回はとりあえず内蔵基板のエンコーダの値を読み取ってみる。

ロータリーエンコーダ

ロータリーエンコーダとは回転軸の角度及び角速度を測定する電子部品である。
エンコーダの種類はインクリメンタル式、アブソリュート式など構造の違いはあるが基本的には回転をパルス情報で取得する方法である。
今回使用するエンコーダはインクリメンタル式であるためインクリメンタル式エンコーダについて考える。
エンコーダの分解能とは軸を1回転させた場合に出力されるパルス数を表す。

A相とB相があるときはどちらの相のパルスの立ち上がりが早いかで回転方向の判断ができる。
2相あるエンコーダを使用するときに出てくる言葉として「逓倍」がある。
1パルス毎に回数を数えることでどれくらい回転したかを判断するのは分解能基準にしたものであり、これを「1逓倍」と呼ぶ。
「2逓倍」とはカウントのルールを変えてパルスでカウントするのではなく、立ち上がりと立ち下がりをそれぞれカウントして分解能の2倍カウントすることができる方法である。
「4逓倍」とはA相に加えてB相も2逓倍でカウントすることで分解能の4倍でカウントする方法である。

逓倍を使うことのメリットとデメリットについては
メリット:より精密に測定ができる
デメリット:電気的ノイズ(チャタリング等)に弱く誤作動してしまう可能性がある
があげられる。

波形を読み取る

ロータリエンコーダの波形を読み取る方法として下記のサイトを参考にさせていただいた。
www.shujima.work
回転パルスの立ち上がりと立下りの前後のA相とB相の比較をして正か負を判断する方法は理解しやすく、簡単なプログラムだったので参考にさせていただいた。
はじめて使ったプログラムとして条件演算子についてメモしておく。
条件演算子?:はif-else文のような条件分岐ができる演算子である。
式1 ? 式2 : 式3
という文では
・式1が真であれば → 式2を実行
・式1が偽であれば → 式3を実行
となる。

また不具合として割り込み関数中にシリアル通信をする際

Guru Meditation Error: Core  1 panic'ed (Interrupt wdt timeout on CPU1). 

等のエラーが発生してしまい割り込み中にエンコーダの状態を取得できなかった。
原因についてはあまりよく分からなかったが多分下記にもある通り割り込み中にデータが失われている可能性がある。そのためカウント等はloop()の中で行うとする。
(シリアル通信速度がAtom Matrixでは115200bps固定なので合わないのかも)
www.musashinodenpa.com

プログラム

#include "M5Atom.h"
 
#define ENC_A 22
#define ENC_B 19

volatile int  enc_count = 0; 
 
void setup() {
  Serial.begin(115200);
  
  pinMode(ENC_A, INPUT);
  pinMode(ENC_B, INPUT);
 
  attachInterrupt(ENC_A, ENC_READ_A, CHANGE);
  attachInterrupt(ENC_B, ENC_READ_B, CHANGE);

}
 
 
void loop() {
  Serial.println(enc_count);
}

void ENC_READ_A(){
  enc_count += digitalRead(ENC_A) == digitalRead(ENC_B) ? -1 : 1;
}

void ENC_READ_B(){
  enc_count += digitalRead(ENC_A) == digitalRead(ENC_B) ? 1 : -1;
}

測定結果

測定結果的に割り込み関数attachInterruptの条件をCHANGEにしているため4逓倍するカウントできるため1周で400パルス出力される。分解能は0.9度であり倒立振子を制御するには問題なさそうなのでこのまま進めていく。

次回

今回のプログラムを元に角度と角速度を導出するプログラムを作っていく。