ロボットに使用されるエンコーダについて説明します。
ロボットにおけるエンコーダとは、物体の移動量をデジタルに変換して出力するセンサのことです。回転量を検出するロータリーエンコーダと、直線変位を検出するリニアエンコーダがあります。
用途としてロボットアームの角度取得や自己位置推定があります。
ロボットアームの駆動モータにロータリーエンコーダを取り付け、ロボットアームの制御に必要な角度を取得します。取得した角度をもとに、目標位置までの誤差を求めて目標位置までロボットアームを動かします。
ロボットの車輪の駆動モータにロータリーエンコーダを取り付けて回転量を取得します。取得した回転量をもとに、ロボットの位置を推定します。タイヤ等が地面と滑る場合正確な位置推定ができなくなるので、エンコーダ以外のセンサで補正する場合があります。
移動量の検出方法にはつぎのような種類があります。
スリットのついた円盤を発光素子と受光素子で挟み、発光素子から発せられた光を受光素子で検知する方式です。円盤が回転すると光が通過と遮断を繰り返すため、その変化を受光素子で検知し、デジタル信号に変化します。
磁気方式や静電方式と比べて、磁気の影響を受けにくく高速に動作しますが、ほこりや油分などで光がさえぎられるなどすると、精度が悪化します。
エンコード用の回転円板の物理的な限界がエンコーダの限界になります。電気信号の処理部分によって実現可能な分解能と精度が決まります。
回転量をカウントする方式には、相対的な移動をカウントするインクリメンタル方式と、絶対的な位置を取得するアブソリュート方式があります。
インクリメンタル方式は信号のON/OFFをカウントします。値の増減から計算開始時点からの位置が計算できます。インクリメンタル方式は相の数によって1相式、2相式、3相式に分かれます。
1相 | 相対的な移動量は取得できるが、回転方向は取得できない。 |
2相 | 相対的な移動量と回転方向が取得できる。 |
3相 | 相対的な移動量と回転方向が取得でき、1周させれば位置補正ができる。 |
相対的な移動量のみ取得できる方式です。1相のパルスの増加のみを検出するため、回転方向は取得できません。
相対的な移動量と回転方向が取得できる方式です。2相の位相が1/4ずれていて1相目(A相)と2相目(B相)の出力の順序で回転方向を識別できます。
一般的にインクリメンタルエンコーダは2相式のことを指します。
相対的な移動量と回転方向が取得でき、1周させれば位置補正ができる方式です。
アブソリュート方式は絶対的な位置を検出可能です。アブソリュート方式のスリットパターンにはグレイコードが使用されています。
磁気パターンを埋め込んだドラムや回転ディスクを回転させ、磁気センサで磁界の変化を読み取ることで検知する方式です。ほこりや油分の汚染に強く、小型、軽量、高分解能ですが、磁気が強い環境では精度が悪化します。
磁気変化を電気信号に変換するため、物理的な制約が少ないです。
1相(A相)式と2相(AB相)式が一般的です。
電気的な接点を移動させて、電気的な変化を回転量に変換する方式です。
安価ですが、チャタリングが起きやすいです。
送信機と回転子と受信機で構成されています。送信機と受信機は固定されています。回転子は正弦波パターンが埋め込まれています。回転子が回転することで、静電容量が変化しその変化を読み取ります。
ほこり、汚れ、油の影響を受けないため、光学式よりも信頼性が高くなります。
エンコーダのパルス出力の形式には以下のような種類があります。
信号として電圧をそのまま出力する形式です。もっとも簡単な形式ですので、エンコーダの出力をデバイスの入力に接続するだけでよいです。電流を制限するために出力抵抗を挟む必要がある場合があります。
トランジスタのオンオフが出力となっている形式です。出力は電圧ではなくトランジスタのコレクタですので、使用者側で電流を流す必要があるので、プルアップ回路などを挟みます。
NPNトランジスタとPNPトランジスタを用いて出力する方式です。Low側PNPトランジスタは出力信号をGNDへ落とすのに機能し、High側NPNトランジスタはプルアップを行います。
プッシュプル出力では、抵抗を介したオープンコレクタ出力よりも速い、高速な信号切り替えが可能です。 電力を消費する抵抗がなければ、電力消費はより低くなり、プッシュプル出力は電力を節約したいシステムに対して適しています。
出力信号にラインドライバを用い差動信号を出力する形式です。
差動ラインレシーバなどを用いて出力を受け取ります。この方式は、RS-422規格といって、差動信号なのでノイズに強いといった利点があります。また、長距離の伝送が可能で、規格では1.2kmまで可能です。ただ信号数が2倍に増えるので、その取扱いが面倒です。
実際にロータリーエンコーダの回転角度を取得するプログラムを作成します。今回はインクリメンタル形2相のものを4逓倍で使用します。
A相とB相の出力の変化を読み取り、前回との状態の違いから角度の変化量を計算します。状態の違いから変化量を計算する方法はいろいろと考えられますが、今回は変換表を用います。
A, Bピンの入力を並べたものを状態として、前回の状態と現在の状態のすべての組み合わせを書いたものが以下の表です。さらに現在と今回の状態を並べたものも加えて書くと、0~15までの数値になることが分かります。
×は無効入力(存在し得ない)。
前回の状態 | 00 | 00 | 00 | 00 | 01 | 01 | 01 | 01 | 10 | 10 | 10 | 10 | 11 | 11 | 11 | 11 |
現在の状態 | 00 | 01 | 10 | 11 | 00 | 01 | 10 | 11 | 00 | 01 | 10 | 11 | 00 | 01 | 10 | 11 |
合計(現在) | 前回<<2) | 0 | 1 | 10 | 11 | 100 | 101 | 110 | 111 | 1000 | 1001 | 1010 | 1011 | 1100 | 1101 | 1110 |
10進数 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
状態 | 変化なし | 減少 | 増加 | × | 増加 | 変化なし | × | 減少 | 減少 | × | 変化なし | 増加 | × | 増加 | 減少 | 変化なし |
パルス増加量 | 0 | -1 | 1 | 0 | 1 | 0 | 0 | -1 | -1 | 0 | 0 | 1 | 0 | 1 | -1 | 0 |
これで、エンコーダからの入力を受け取るピンの変化があったとき、変換表を参照すればエンコーダの回転量を取得できるようになります。
実際にArduinoを用いて実装してみましょう。
Arduino UNOを用いて、接続は2, 3番ピンをエンコーダのA, Bに接続してください。Arduinoのピン変化割り込みが許可されているピンは限定されているので注意が必要です。(https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/)
// 1回転当たりのパルス量(エンコーダによる) static const int ppr = 50; // エンコーダに接続するピン static const int pinA = 2; static const int pinB = 3; // エンコーダからの入力を変化量に変換するテーブル static const int encode_table[] = {0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0}; // エンコーダの変化量 int count = 0; void setup() { Serial.begin(9600); pinMode(pinA,INPUT); pinMode(pinB,INPUT); // pinA, pinBのピン変化割り込みを設定 // Uno: pin2(int.0) pin3(int.1) attachInterrupt(0, encode, CHANGE); attachInterrupt(1, encode, CHANGE); } void loop() { // エンコーダの回転角度[deg] = パルスカウント[pulse] * 360[deg/rev] / ppr[pulse/rev] / 4(逓倍) float angle = float(count) * 360.0 / float(ppr) / 4.0; Serial.println(angle); delay(100); } void encode() { //前回の状態を保存する変数 static int last_state = 0; //ピン入力の読み取り int sig1 = digitalRead(pinA); int sig2 = digitalRead(pinB); // 現在の状態(pinAとpinBを並べたもの) int8_t state = sig1 | (sig2 << 1); // 合計 int8_t sum = state | last_state<<2; // 前回と今回の状態が異なっていた場合に変換表を参照しcountを計算 if (last_state != state) { count += encode_table[sum]; //前回の状態として保存 last_state = state; } }
今回はArduinoですべて書きましたが、エンコーダ用のライブラリはQEI(Quadrature Encoder Interface:直交エンコーダインタフェース)といった名前のライブラリが豊富にあります。
多くの企業がエンコーダを生産・販売しています。ここでは、ロボットに組み込みやすく、価格が3,000円から20,000円のものを紹介します。
メーカー | オムロン |
分解能[ppr] | 100~500 |
回転が滑らかで抵抗が少ないです。よく使用されています。
詳細:https://www.fa.omron.co.jp/products/family/486/itemlist/
メーカー | IWATSU |
分解能[ppr] | 20~100 |
ある程度の抵抗があるので、触れた程度では回転しません。また、Z相はありません。
詳細:https://www.iti.iwatsu.co.jp/ja/products/compo/rotary_encoder_ec202_index.html
メーカー | マイクロテック・ラボラトリー |
分解能[ppr] | 32~10000越えまで |
超高性能なものもありますが、高価です。主な用途は厳密な測定用などですが、ロボコン向けに製品提供を行っています。
メーカー | maxon |
分解能[ppr] | 32~5000 |
maxonモータに搭載されているエンコーダです。モータ出力軸に接続されているため、減速前の回転数を読み取ることになります。