STM32 タイマーエンコーダモード:ロータリーエンコーダの読み取り徹底解説
ロータリーエンコーダは、回転運動をデジタル信号に変換する入力デバイスであり、ロボット工学、産業オートメーション、ヒューマン・マシン・インターフェース(HMI)など、幅広いアプリケーションで使用されています。STM32 マイクロコントローラは、内蔵されたタイマーモジュールを利用して、ロータリーエンコーダの出力を効率的に読み取ることができるエンコーダモードを備えています。本記事では、STM32 のエンコーダモードの詳細な解説と、ロータリーエンコーダの読み取りに関する実践的な知識を提供します。
1. ロータリーエンコーダの基礎
ロータリーエンコーダは、回転するシャフトに取り付けられたコードディスクと、そのディスクのコードパターンを読み取るためのセンサーで構成されます。一般的に使用されるロータリーエンコーダには、インクリメンタルエンコーダとアブソリュートエンコーダの2種類があります。
1.1. インクリメンタルエンコーダ
インクリメンタルエンコーダは、シャフトの回転に応じてパルス信号を生成します。これらのパルス信号は、通常、位相が90度ずれた2つのチャネル(AチャネルとBチャネル)で構成されます。この位相差を利用することで、回転方向を判別することができます。
- 動作原理: インクリメンタルエンコーダのコードディスクには、放射状に配置されたスリットまたはパターンが刻まれています。ディスクが回転すると、センサーがこれらのスリットを検出し、AチャネルとBチャネルにパルス信号を生成します。回転方向によって、AチャネルとBチャネルのパルスの位相関係が変化します。例えば、時計回りの回転の場合、AチャネルがBチャネルより先に立ち上がり、反時計回りの回転の場合、BチャネルがAチャネルより先に立ち上がります。
- 利点:
- シンプルで低コスト
- 高速回転に対応可能
- 絶対位置を記憶する必要がないため、電源を切っても問題ない
- 欠点:
- 電源投入時やノイズの影響で、位置がずれる可能性がある(累積誤差が発生する)
- 絶対位置の情報がないため、初期位置を確立する必要がある
- アプリケーション:
- ロボットの関節角度制御
- 産業オートメーションにおける位置決め
- マウスやジョイスティックなどのHMIデバイス
1.2. アブソリュートエンコーダ
アブソリュートエンコーダは、シャフトの絶対的な角度位置を直接デジタルコードで出力します。このコードは、グレイコードまたはバイナリコードなどの形式で表現されます。
- 動作原理: アブソリュートエンコーダのコードディスクには、シャフトの角度位置に対応するユニークなコードパターンが刻まれています。複数のセンサーがこれらのコードパターンを同時に読み取り、角度位置を表すデジタルコードを生成します。
- 利点:
- 絶対位置を直接読み取ることができる
- 電源投入時やノイズの影響を受けても、位置がずれることがない
- 累積誤差が発生しない
- 欠点:
- インクリメンタルエンコーダよりも複雑で高コスト
- エンコーダの分解能が高いほど、コードディスクのトラック数が増加する
- アプリケーション:
- 高精度な位置決めが必要なロボットアーム
- 産業機械のサーボ制御
- 医療機器
本記事では、より一般的なインクリメンタルエンコーダを対象とし、STM32のエンコーダモードを使ってその出力を読み取る方法に焦点を当てます。
2. STM32 タイマーエンコーダモードの概要
STM32 のタイマーモジュールは、エンコーダモードを備えており、外部のインクリメンタルエンコーダの出力を効率的に読み取ることができます。エンコーダモードを使用すると、タイマーが自動的にエンコーダの A チャネルと B チャネルの信号を監視し、カウンタを増減させることができます。これにより、CPUの負荷を軽減し、エンコーダの回転を正確に追跡することができます。
2.1. エンコーダモードの動作原理
エンコーダモードでは、タイマーの2つの入力チャネル(通常は TI1 と TI2)がエンコーダの A チャネルと B チャネルに接続されます。タイマーは、これらの入力信号のエッジを検出して、内部カウンタを増減させます。回転方向は、A チャネルと B チャネルの位相関係に基づいて決定されます。
- カウンタの増減: タイマーは、設定されたモード(通常は Mode 3)に応じて、A チャネルと B チャネルの両方の立ち上がりエッジと立ち下がりエッジを検出し、それに応じてカウンタを増減させます。これにより、エンコーダの分解能を4倍にすることができます。
- フィルタリング: タイマーには、入力信号のノイズを除去するためのデジタルフィルタリング機能が組み込まれています。これにより、誤ったカウントを防ぎ、エンコーダの読み取り精度を向上させることができます。
- 割り込み: タイマーは、オーバーフロー、アンダーフロー、キャプチャなどのイベントが発生した場合に割り込みを生成することができます。これらの割り込みを利用することで、ソフトウェアでエンコーダの位置を監視し、必要な処理を実行することができます。
2.2. エンコーダモードの設定
STM32 のエンコーダモードを設定するには、以下の手順を実行します。
- タイマーの有効化: 使用するタイマーをクロックイネーブルにします。
- GPIOの設定: エンコーダの A チャネルと B チャネルに接続する GPIO ピンを、タイマーの代替機能(Alternate Function: AF)として設定します。
- タイマーのエンコーダモードの設定: タイマーの Control Register 1 (TIMx_CR1) と Slave Mode Control Register (TIMx_SMCR) を設定して、エンコーダモードを有効にします。
- フィルタリングの設定: 必要に応じて、タイマーの Capture/Compare Mode Register 1 (TIMx_CCMR1) を設定して、デジタルフィルタリングを有効にします。
- 割り込みの設定: 必要に応じて、タイマーの Interrupt Enable Register (TIMx_DIER) を設定して、割り込みを有効にします。
- カウンタの初期化: タイマーの Counter Register (TIMx_CNT) を初期化します。
3. STM32CubeIDE を使用したエンコーダモードの実装
STM32CubeIDE は、STMicroelectronics が提供する統合開発環境 (IDE) であり、STM32 マイクロコントローラの開発を容易にするための強力なツールセットを提供します。STM32CubeIDE を使用すると、グラフィカルなインターフェースを通じて、タイマーエンコーダモードを簡単に設定し、必要なコードを自動生成することができます。
3.1. プロジェクトの作成
- STM32CubeIDE を起動し、「File」>「New」>「STM32 Project」を選択します。
- ターゲットとなる STM32 マイクロコントローラを選択します。
- プロジェクト名を入力し、「Next」をクリックします。
- 「Initialize all peripherals with their default mode?」のチェックを外し、「Finish」をクリックします。
3.2. タイマーと GPIO の設定
- 「Device Configuration Tool」を開き、「Connectivity」セクションで、使用するタイマー(例:TIM1)を有効にします。
- 「Mode」を「Encoder Mode」に設定します。
- エンコーダの A チャネルと B チャネルに接続する GPIO ピンを選択し、対応するタイマーチャネル(例:TIM1_CH1、TIM1_CH2)に割り当てます。
- 「Parameter Settings」タブで、エンコーダモードのパラメータを設定します。
- Encoder Mode: エンコーダモードの種類(通常は「Encoder Mode TI1 and TI2」を選択)
- Polarity: A チャネルと B チャネルの極性(通常は「Rising Edge」を選択)
- Filter: 入力信号のフィルタリング(必要に応じて設定)
- Prescaler: タイマークロックの分周比(通常は「No prescaler」を選択)
- Counter Mode: カウンタの動作モード(通常は「Up」を選択)
- Auto-reload Register Value: カウンタの最大値(エンコーダの分解能に合わせて設定)
- 必要に応じて、「NVIC Settings」タブで、タイマー割り込みを有効にします。
3.3. コードの生成と編集
- 「Project」>「Generate Code」を選択して、初期化コードを生成します。
- 生成されたコードを編集して、エンコーダの読み取り処理を実装します。
3.4. コード例
以下は、STM32CubeIDE で生成されたコードを基に、エンコーダの読み取り処理を実装した例です。
“`c
/ Includes /
include “main.h”
/ Private variables /
TIM_HandleTypeDef htim1;
/ Private function prototypes /
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM1_Init(void);
int main(void)
{
/ MCU Configuration——————————————————–/
/ Reset of all peripherals, Initializes the Flash interface and the Systick. /
HAL_Init();
/ Configure the system clock /
SystemClock_Config();
/ Initialize all configured peripherals /
MX_GPIO_Init();
MX_TIM1_Init();
/ Start the encoder interface /
HAL_TIM_Encoder_Start(&htim1, TIM_CHANNEL_ALL);
while (1)
{
/ Read the encoder value /
int32_t encoderValue = __HAL_TIM_GET_COUNTER(&htim1);
/* Do something with the encoder value */
// 例: シリアルポートに出力
printf("Encoder Value: %ld\r\n", encoderValue);
HAL_Delay(100); // 100ms 待機
}
}
/ TIM1 init function /
static void MX_TIM1_Init(void)
{
/ USER CODE BEGIN TIM1_Init 0 /
/ USER CODE END TIM1_Init 0 /
TIM_Encoder_InitTypeDef sConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim1.Instance = TIM1;
htim1.Init.Prescaler = 0;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 65535; // または適切な最大値
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
sConfig.EncoderMode = TIM_ENCODERMODE_TI12;
sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
sConfig.IC1Filter = 0; // または適切なフィルタ値
sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
sConfig.IC2Filter = 0; // または適切なフィルタ値
if (HAL_TIM_Encoder_Init(&htim1, &sConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
/ USER CODE BEGIN TIM1_Init 2 /
/ USER CODE END TIM1_Init 2 /
}
/ GPIO init function /
static void MX_GPIO_Init(void)
{
/ GPIO Ports Clock Enable /
__HAL_RCC_GPIOA_CLK_ENABLE();
}
“`
コードの説明:
MX_TIM1_Init(): タイマー1をエンコーダモードで初期化します。EncoderMode,IC1Polarity,IC2Polarity,IC1Filter,IC2Filterなどのパラメータを適切に設定する必要があります。Periodはカウンタの最大値を設定します。 エンコーダの分解能と必要な範囲に合わせて適切な値を設定してください (例: 360°の角度を表現する場合は、360以上の値)。HAL_TIM_Encoder_Start(&htim1, TIM_CHANNEL_ALL): タイマー1のエンコーダモードを開始します。TIM_CHANNEL_ALLは、両方のチャネル(AとB)を同時に開始することを意味します。__HAL_TIM_GET_COUNTER(&htim1): タイマー1のカウンタレジスタから現在のエンコーダ値を読み取ります。printf("Encoder Value: %ld\r\n", encoderValue): エンコーダの値をシリアルポートに出力します。 この部分は、実際のアプリケーションに合わせて調整する必要があります。
3.5. デバッグとテスト
- コードをコンパイルして、STM32 マイクロコントローラに書き込みます。
- ロータリーエンコーダを STM32 ボードに接続します。
- デバッグツールを使用して、エンコーダの値を監視します。
- エンコーダを回転させ、値が正しく変化することを確認します。
4. エンコーダの読み取り精度の向上
エンコーダの読み取り精度は、アプリケーションの性能に大きく影響します。以下の方法を使用することで、エンコーダの読み取り精度を向上させることができます。
- デジタルフィルタリング: エンコーダの入力信号にノイズが含まれている場合、デジタルフィルタリングを有効にすることで、誤ったカウントを防ぐことができます。STM32 のタイマーモジュールには、プログラマブルなデジタルフィルタリング機能が組み込まれており、入力信号のノイズを除去することができます。
- ヒステリシス: エンコーダの入力信号にチャタリングが発生している場合、ヒステリシスを適用することで、誤ったカウントを防ぐことができます。ヒステリシスは、信号が変化するためにある閾値を超える必要があることを意味します。
- 割り込み処理: エンコーダの回転速度が速い場合、割り込み処理を使用することで、エンコーダのカウントを正確に追跡することができます。タイマー割り込みを使用すると、エンコーダのカウンタがオーバーフローまたはアンダーフローした場合に割り込みが発生し、ソフトウェアでエンコーダの位置を更新することができます。
- エンコーダの分解能: エンコーダの分解能が高いほど、より細かい角度位置を検出することができます。アプリケーションの要件に応じて、適切な分解能のエンコーダを選択してください。
- 配線とシールド: エンコーダと STM32 ボード間の配線は、できるだけ短くし、シールドされたケーブルを使用することで、ノイズの影響を軽減することができます。
5. 応用例
STM32 のエンコーダモードは、様々なアプリケーションで使用することができます。以下に、いくつかの応用例を示します。
- ロボットの関節角度制御: エンコーダは、ロボットの関節の角度位置を正確に測定するために使用されます。STM32 のエンコーダモードを使用することで、ロボットの関節角度をリアルタイムで制御することができます。
- 産業オートメーションにおける位置決め: エンコーダは、産業オートメーションにおける部品の位置決めや搬送に使用されます。STM32 のエンコーダモードを使用することで、部品の位置を正確に制御することができます。
- CNC マシンの制御: エンコーダは、CNC マシンの軸の移動量を正確に測定するために使用されます。STM32 のエンコーダモードを使用することで、CNC マシンの軸を正確に制御することができます。
- 医療機器: エンコーダは、医療機器における位置決めや速度制御に使用されます。STM32 のエンコーダモードを使用することで、医療機器の動作を正確に制御することができます。
6. トラブルシューティング
エンコーダの読み取りで問題が発生した場合、以下の点を確認してください。
- 配線: エンコーダと STM32 ボード間の配線が正しいことを確認してください。A チャネルと B チャネルが逆になっていないか、GND と VCC が正しく接続されているかを確認してください。
- エンコーダの設定: エンコーダモードの設定が正しいことを確認してください。Polarity、Filter、Prescaler などのパラメータが、エンコーダの仕様とアプリケーションの要件に合っているかを確認してください。
- クロックの設定: タイマーのクロックが正しく設定されていることを確認してください。クロックが遅すぎると、エンコーダのカウントを正確に追跡することができません。
- ノイズ: エンコーダの入力信号にノイズが含まれていないか確認してください。ノイズが多い場合は、デジタルフィルタリングを有効にするか、配線を改善してください。
- エンコーダの故障: エンコーダ自体が故障していないか確認してください。別のエンコーダを試してみるか、オシロスコープでエンコーダの出力信号を監視してください。
7. まとめ
本記事では、STM32 マイクロコントローラのタイマーエンコーダモードを使用して、ロータリーエンコーダの出力を効率的に読み取る方法について詳細に解説しました。エンコーダモードの動作原理、設定方法、STM32CubeIDE を使用した実装例、読み取り精度の向上方法、応用例、トラブルシューティングなど、実践的な知識を提供しました。
STM32 のエンコーダモードは、ロボット工学、産業オートメーション、HMI など、幅広いアプリケーションで使用することができます。本記事で得られた知識を活用して、エンコーダベースのシステムを開発し、アプリケーションの性能を向上させてください。
さらに学習を進めたい場合は、STM32 のリファレンスマニュアルやアプリケーションノートを参照することをお勧めします。また、STMicroelectronics のウェブサイトでは、様々なサンプルコードやチュートリアルが提供されています。
この情報が、STM32 でロータリーエンコーダを扱う際の助けとなることを願っています。