ロータリエンコーダの位相信号をソフトウェアでカウントする
20091012
coskx
1.はじめに
H8/3048には位相カウンタが1つしかなく,2つのロータリエンコーダをハードウェアで読みたい場 合は,h8/3069のような2chの位相カウンタを持つCPUに乗り換えることになる。しかし,分解能の少ないロータリエンコーダなら,2相の信号を 2bitの入力で受けて,ソフトウェアでカウントすることができる。この方法によれば4つのロータリエンコーダを読みだすこともできる。
2.ゆっくりカウント値が変化するロータリエンコーダ
例えば100パルス/回転くらいのロータリエンコーダが1RPSで回転したとすると,100パルス/secくらいの信号となり,位相変化はその4倍の400パルス/秒程度になる。このような場合には1msecの割り込みで2つのビットを読んでいれば,カウントできる。
3.ゆっくりカウント値が変化するロータリエンコーダのソフトウェアでの読みとり
正方向に回転した時には次のように2つの信号が変化する。
時間→ | ||||||||
A相 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 0 |
B相 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 |
逆方向に回転した時には次のように2つの信号が変化する。
時間→ | ||||||||
A相 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 |
B相 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 0 |
この関係を直前のAB信号と,現在のAB信号を基に,カウンタ値を増やすべきか減らすべきかを考えて表にすると次のようになる。
例えば,前回割り込み時にAB信号が01で現在のAB信号が00ならカウンタ値を1増やすことを示している。
ただし,赤の字のところはあり得ない,または検査周期が長すぎて,データを取り損ねていて+2または-2にすべきところである。
今回割り込み時のAB信号 | |||||
00 |
01 |
10 |
11 |
||
前回 割り 込み 時の AB 信号 |
00 |
0 |
-1 |
1 |
0 |
01 |
1 |
0 |
0 |
-1 | |
10 |
-1 |
0 |
0 |
1 | |
11 |
0 |
1 |
-1 |
0 |
前回割り込み時のAB信号をBit3,Bit2,今回割り込み時のAB信号をBit1,Bit0として番号を作ると次のようになる。
AB信号の2進表示 |
0000 | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 | 1000 | 1001 | 1010 | 1011 | 1100 | 1101 | 1101 | 1111 |
AB信号の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 |
あり得ないかまたは検査周期が長すぎてデータを取り損ねていている組み合わせは,エラーとなるので,エラーを示すテーブルも作っておく。
0は正常,1はエラーを表す。
今回割り込み時のAB信号 | |||||
00 |
01 |
10 |
11 |
||
前回 割り 込み 時の AB 信号 |
00 |
0 |
0 |
0 |
1 |
01 |
0 |
0 |
1 |
0 | |
10 |
0 |
1 |
0 |
0 | |
11 |
1 |
0 |
0 |
0 |
前回割り込み時のAB信号をBit3,Bit2,今回割り込み時のAB信号をBit1,Bit0として番号を作ると次のようになる。
AB信号の2進表示 |
0000 | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 | 1000 | 1001 | 1010 | 1011 | 1100 | 1101 | 1101 | 1111 |
AB信号の10進表示 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
カウント増減値 |
0 |
0 |
0 |
1 |
0 |
0 |
1 |
0 |
0 |
1 |
0 |
0 |
1 |
0 |
0 |
0 |
4. 1つのロータリエンコーダ読み取りプログラムコード
例えば,割り込み関数中でポートBの第0第1ビットにロータリエンコーダからのA相B相の信号が得られるとすると,
次の参考プログラムのようにすれば,ロータリエンコーダの現在位置が,変数counterに保存される。
あとで,errorcountの値が0から増えていなければ,正しく動作していると考えることができる。
参考プログラムの一部 |
volatile int counter=0;
/*ロータリエンコーダを数えるカウンタ,初期値は0*/ |
5. 2つのロータリエンコーダ読み取りプログラムコード
2つのロータリエンコーダを使用している時でも同様にプログラミングできる。
例えば,エンコーダ1がポートBの第0第1ビットに,エンコーダ2はポートBの第2第3ビットに得られたとしよう。
次の参考プログラムのようにすれば,2つのロータリエンコーダの現在位置が,それぞれ変数counter1,counter2に保存される。
あとで,errorcount0,errorcount1の値が0から増えていなければ,正しく動作していると考えることができる。
参考プログラムの一部 |
volatile int counter1=0;
/*ロータリエンコーダ1を数えるカウンタ,初期値は0*/ |