2016年3月17日木曜日

STM32F1のエンコーダインターフェースモード

STM32F1のTIMxについてるエンコーダインターフェースボードを試してみた。

テストに使用したエンコーダはこれ
http://akizukidenshi.com/catalog/g/gP-00292/
1回転24パルスの機械接点タイプのエンコーダだ。

ソースコード
void TIM3_Init(void) {
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    TIM_SetAutoreload(TIM3, 24 * 2 - 1);
    TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI1, TIM_ICPolarity_Falling, TIM_ICPolarity_Falling);
    TIM_Cmd(TIM3, ENABLE);
}

最初はRCCでクロックの供給を行う。次にGPIOを初期化する。今回はマイコンでプルアップを行い、エンコーダはGNDに落とした。TIM3のCH1、CH2はGPIOA6、7に接続されているので、GPIOAの6と7をIPUとして初期化する。次にTIM_SetAutoreloadでカウンタの上限を指定する。またTIM_EncoderInterfaceConfigで動作モードを指定する。最後にTIM_Cmdで動作を開始させる。

TIM_EICの引数にはカウントモード(TIM_EncoderMode_TIhoge)と極性(TIM_ICPolarity_hoge)を渡す。
カウンタモードはTI1ならCH1のエッジでカウント、TI2ならCH2のエッジでカウント、TI12ならCH1とCH2それぞれのエッジでカウントを行う。
極性はRisingで立ち上がり、Fallingで立ち下がりエッジを使うことになると思うが、カウンタは立ち上がり、立ち下がりエッジの両方でカウントを行うため、実質的にはあまり違いはないと思う。ただ今回はプルアップで最初のエッジが立ち下がりのため、Fallingを指定した。

それとTIM_SAで指定した24*2-1という数字だが、これはエンコーダのパルス数(1回転24パルス)に立ち上がりと立ち下がりエッジで2回分、それから0始まりのために-1となる。カウントモードでTI12を指定した場合は24*4-1とする。この設定でわかるように、エンコーダは1回転24パルス出力でも、マイコンからはその2倍(あるいは4倍)として認識することができる。1回転24パルスのエンコーダでも実際には96パルスという比較的高分解能として使えるわけだ(ただしヒューマンインターフェースの場合は1クリックの途中で値が変わるのは非常に気持ち悪いが)。

エンコーダでカウントアップしていき上限に達した場合は0にリセットされ、カウントダウンで0を下回った場合はTIM_SAで指定したカウント値に飛ぶ。そのためカウント値の監視がカウンタのリセットに間に合わない場合にはもっと大きな数値を指定するとか工夫する必要があると思う。音量の調整などに使用するために範囲を0-50とかにすると、音量を下げて0になった次の瞬間に50に飛んで最大音量となるため、この辺りはうまく処理する必要があると思う。


機械式のロータリーエンコーダはチャタリングが酷く、以前にソフトウェアで読んだ時も素早く回すととても使いものにならないような結果になった。今回も同じような結果を予想していたが、CRフィルタも何も使用せず、しかもマイコンの外部部品はエンコーダのみでプルアップ抵抗もマイコン内蔵という悪条件ながら、ほとんど読み込みエラーが発生しなかった。操作ダイヤルなど、相対的な動作で構わない用途にはほぼ問題なく使用できると思われる。モーターの絶対位置を計測したい等の用途では何らかの対策が必要だと思うが、モーターの回転数を測るような、0.5パルスずれた程度ではあまり問題にならない用途では十分だと思われる。


ところで、STM32F1リファレンスマニュアルには「エンコーダインタフェースモードは、単に方向選択を含む外部クロックとして動作します」と書いてある。ということはCH1のパルスでカウントし、CH2でインクリメントとデクリメントを切り替えられるのか?と思って試してみたが、そういう動作はできないようだ。少なくともエンコーダインターフェースボードではノイズとして処理されてしまうらしい。
もしもこのような動作が可能であればステッピングモータドライバに対するパルス出力(回転方向の1bitとステップ数のパルス)のような信号を受け取ることができると思ったんだけど、それはできないみたい。

0 件のコメント:

コメントを投稿