コンテンツ

H8 MCUボードにイロイロつないでみる/1 - マザーボード?にMCUボードを乗せる
H8 MCUボードにイロイロつないでみる/2 - I/Oポートを増やす+温度センサーを付ける
H8 MCUボードにイロイロつないでみる/3 - ロータリーエンコーダをつけてみる
H8 MCUボードにイロイロつないでみる/4 - 赤外線リモコン受信素子をつけてみる
H8 MCUボードにイロイロつないでみる/5 - 周波数カウンタにしてみる
H8 MCUボードにイロイロつないでみる/6 - ・・・

H8 MCUボードにイロイロつないでみる/3

ありきたりですが、次にロータリーエンコーダをつないでみました。
ロータリーエンコーダ(以下、エンコーダと訳)の動作原理は、ネット上にたくさんあるので、そちらを参照して頂くとして・・・
ではなく、ちょっとだけ書いておきます。

ロータリーエンコーダーの仕組み

まず、エンコーダは、軸の回転した量をパルスで出力するもの*1なので、単純に考えれば、以下のとおり、軸を回した時にパルスを出力すれば良いわけです。

波形1

軸を回せば回しただけのパルスがでますので、それを数えれば回転量が分かるというわけです。
しかし、この場合、回転量が増加する一方向だけの動作しかできません。
軸を右に回しても、左に回しても、それを知る術がないのです。

そこで、その問題を解決する為に、エンコーダは、下図のようにA相・B相という2種類のパルスを出すようになっています。

波形2

どうして、これで左右、どちらへ回転しているのが分かるのか?

とりあえず、回転量はパルスを数えるとして、B相信号の立ち上がり部分に注目してみます。
すると、

(1)右へ向かう場合、B相が立ち上がる時は「必ずA相はHレベルである」
(2)左へ向かう場合、B相が立ち上がる時は「必ずA相はLレベルである」

という事になります。
これで、軸がどちらの方向に回されたのか?を知る事ができます。
実際は、立下りエッジも見たりとか、時と場合によってイロイロな方法や検出回路があるのですが、簡単な考え方としては以上です。

ロータリーエンコーダーをつないでみる

例によって、部品箱を覗くと、以下のように2個のエンコーダがみつかりました。

エンコーダの画像

ひとつは、COPALの光学式のもの*2、もうひとつは何かの基板から外した接点式のもの*3です。
配線の途中にあるのは、以下のような(ありきたりの)I/F回路を組んだ基板です。
親基板に乗せても良かったのですが、I/F回路が違うのと、どうせ使い回すだろう…ということで、こういう形になってしまいました。

エンコーダ回路図

H8 3048Fなどは、位相カウンタ内臓ですので、その入力である、TCLKAとTCLKBにA相・B相の信号線をつなげばOKです。
他に、光学式は電源がいるのとプルアップやHC14*4などの為に電源をつなぎます。

※ちなみに、接点式の信号端子は、秋葉原などで出回っているモノのように「COM-A-B」ではなく「A-COM-B」でした。
 素性の知れないモノは要チェックです。

ところで、最初、接点式のものは手抜きして回路図A部分のプルアップ部分だけを配線して動かしてみたのです。
結果、カウントアップ/ダウンは行えました。
それで、「んー、チャタリングは意外と少ないのねぇ」と気を抜いてしまったのでした。
が、やはり甘い考えでしたね。はい。
カウンタのオーバーフロー/アンダーフローの処理で割り込みを使うようにソフトを書いたのですが、割り込みが発生すると、カウンタ値がとんでもない値に飛んでいってしまうのでした。
光学式では起こらないので、やはりチャタリングで割り込みが多数入っているんだろう、という結果になったわけです。
そこで、またもや手抜きで回路図B部分の積分回路まで組んで、あとはH8の入力回路に頼ろうと・・・
見事に裏切られましたね。結果変わらずです*5
あ~あ、やっぱりな。…と、部品箱からHC14を取り出して増設となりました。

エンコーダ増築部分

結果は、さすがシュミットトリガ!でした。
手抜きはしないよーに!

ソフトウェア

そもそも、内臓カウンタで機能を提供しているので、処理を書くという程のものではありません。

short tmr2ovf;

/************************************************************************/
/*                                                                      */
/* ロータリーエンコーダ用に2相カウンタを初期化                         */
/*                                                                      */
/************************************************************************/
void init_ctr2(void)
{
    tmr2ovf = 0;                    /* オーバーフローカウンタ           */

    ITU.TMDR.BIT.MDF   = 1;         /* 位相計数モード設定               */
    ITU.TMDR.BIT.FDIR  = 0;         /* Overflow/Underflowでflag set     */
    ITU2.TIER.BIT.OVIE = 1;         /* OVF での割り込み許可             */
    ITU2.TCNT          = 0;         /* カウンタ初期値                   */
    ITU.TSTR.BIT.STR2  = 1;         /* カウンタのスタート               */
}


/************************************************************************/
/*                                                                      */
/* ロータリーエンコーダのカウンタ値を取得                               */
/*                                                                      */
/************************************************************************/
long get_ctr2(void)
{
#if  1
  #define ENC_TYPE_COPAL (1)
#endif
long ctr;

    ctr  = ITU2.TCNT;                 	/* カウンタの値を取得           */
    ctr += tmr2ovf * 0x10000;          	/* オーバーフロー分を加える     */
    #ifdef ENC_TYPE_COPAL
        return ctr;                    	/* 戻り値として返す(光学式)     */
    #else
        return ctr / 4;                	/* 戻り値として返す(接点式)     */
    #endif
}

初期化処理とカウンタ値取得処理です。
初期化処理は、コメントのとおりでマニュアルの写しみたいなものです。
カウンタ値取得処理は、16ビットカウンタ値を32ビットカウンタ値に拡張する処理が入っています。
必要なのかは微妙*6ですが、-2147483648~0~+2147483647まで使えます*7
変数 tmr2ovf は、ハードカウンタのオーバーフロー/アンダーフローの数を保持している変数です。


/************************************************************************/
/*  vector 34 OVI2                                                      */
/************************************************************************/
__interrupt(vect=34) void INT_OVI2(void)
{
extern short tmr2ovf;

    /* TSRのOVFをクリア(読み込んでから書き込む) */
    if(ITU2.TSR.BIT.OVF) ITU2.TSR.BIT.OVF = 0;
    /* OverFlowかUnderFlowか判断して、その処理を行う */
    if(ITU2.TCNT & 0x8000) --tmr2ovf;
    else ++tmr2ovf;
}

オーバーフロー/アンダーフロー時に起きる割り込み処理です。
割り込み要因フラグをクリアしてから、オーバーフローなのかアンダーフローなのかの判断をしてオーバーフローカウンタを増減しています。
オーバーフロー/アンダーフローの判断は、割り込みが入った時のハードカウンタ値を取得して、MSBが立っていれば、0→0xffffへのアンダーフロー、MSBが立っていなければ、0xffff→0へのオーバーフローとしています。
普通は、割り込み処理に飛んでくるまでに、0x8000もカウントしない筈なので…。
あ、長時間の割り込み禁止ならば、ありえますね。
どんなシステムか知りませんが。

補足

ちなみに、接点式のものは、以下の図の通り、クリック間で四つのエッジが出力されます。
H8 3048Fの位相カウンタは4逓倍で全てのエッジをカウントするので、1クリックで4カウントされます。

接点式クリック位置



H8 MCUボードにイロイロつないでみる/4

*1 ロータリーエンコーダについて書いていますが、回転量や移動量をパルスで出力する測定器は結構あります。
*2 10年位前にジャンクで購入したもの。新品だと結構なお値段がするのではないでしょうか・・・
*3 小さな字でALPSと刻印がありました。
*4 あまった入力はオープンではなく、GNDなどへ接続しておきます。
*5 チャタリングなのか、波形がなまったせいなのかは不明です。
*6 0.1mm/パルスの磁気スケールで10m長のモノを計れば、100000パルスですから、16ビットカウンタでは計れません。
*7 回しきるまでエンコーダーの方が先に壊れたりなんかして・・・
最終更新のRSS
Last-modified: 2010-07-27 (火) 17:39:14 4984日前
HTML convert time: 0.011 sec.