シュウジマブログ

Apple製品,技術系の話をするブログ

【Nucleo入門】Nucleo-F401でエンコーダ読み取り(STM32CubeIDE、macOS版)

記事概要

STM32 CubeIDEが公開されたことを記念して,STM32の基本的な使い方を確認します.

本記事ではSTM32で回転を読み取るためのセンサ,エンコーダを読み取るプログラムを作ります.

本ブログを書くにあたって下記リンク先を大いに参考にさせていただいています.

ruru-log.hatenablog.com

環境

  • STM32CubeIDE 1.0.0
  • macOS 10.14.5
  • NUCLEO-F401RE

STM32 CubeIDEについて(読まなくてもよい)

STM32 CubeIDEはSTM32用の統合開発環境です.

2019年4月にリリースされたものですが,実態はこれまでも存在し,広く使われていた「STM32CubeMX」,「SW4STM32」の2つのアプリケーションを統合したものです.

CubeMXはマイコンの設定を作成するためのアプリケーションです.

SW4STM32はプログラムを書いて実行するためのアプリケーションです.

これまではCubeMXで作った設定データをSW4STM32に取り込んで作る必要がありましたが,Cube IDEで統合されたため,とてもわかりやすくなりました.

まだネット上にはCubeIDEを使った記事は少ないため,CubeMXやSW4STM32を使った情報が多くあります.

調べる際には上記のワードも覚えておくとよいでしょう.

CubeMX,SW4STM32は今後アップデートされなくなるため,今から始める方はSTM32CubeIDEで練習するのがよいでしょう.

環境構築について

STM32 CubeIDEのインストール方法はこちらをご覧ください.

www.shujima.work

プロジェクトの作成

プロジェクト作成方法はUART通信のときと同じです.こちらの記事をご覧ください.

www.shujima.work

CubeMX

プロジェクト作成をするとこの画面にたどり着くと思いますので,そこで設定が必要になります.

既存のプロジェクトを活用する人は左メニューの「(プロジェクト名).ioc」(黒丸で囲ったところ)をダブルクリックするとこの画面が開くはずです.

f:id:masa_flyu:20190524024257j:plain

STM32ではマイコンの周辺機能(Peripheral)を様々なピンに割り当てることができます(緑のピンは割り当て済み).

この画面で,タイマーなどマイコンの機能をピンに割り当てることで,設定や初期化の内容がプログラムに反映されます.

今後機能を増やしていく際にはこちらの画面でピンを設定して,プログラムを記述という作業を繰り返していくことになります.

エンコーダのピン設定

エンコーダのために必要な入力

エンコーダは2つのパルス状波形(A相,B相)を発生させ,そのタイミングで,回転方向と回転量を知ることができます.

マイコンは2つのデジタル入力が1か0か,常に監視する必要があります.

そのようなプログラムを書いてもいいのですが,他にも様々な処理をさせたい時には,エンコーダの処理を自動で行ってくれる機能を活用すべきです.

STM32ではTimer機能の中にあるEncoder読み取り機能を活用出来ます.

STM32F401ではタイマー1〜5(TIM1〜TIM5)のいずれかで利用可能であり,それぞれに備えられたCH1,CH2端子にA相,B相の入力を接続します.

今回はまず,TIM3をエンコーダ入力に設定していきます.

ピンへの機能割り当て

では実際にピンを選んで設定していきます.今回は

  • PA6 → TIM3_CH1
  • PA7 → TIM3_CH2

を割り当てます.

PA6をクリックすると,割り当てられる機能一覧が出てきますので,「TIM3_CH1」を選択します.

f:id:masa_flyu:20190527222726j:plain

PA7をクリックすると,割り当てられる機能一覧が出てきますので,「TIM3_CH2」を選択します.

f:id:masa_flyu:20190527222737j:plain

PA6とPA7が黄色になっているはずです.

これは,ピンに機能が割り当てられたにも関わらず,必要な設定がなされていないことを表しています.

これらのピンを使えるようにするために,TIM3の設定をしていきます.

f:id:masa_flyu:20190527224702j:plain

ペリフェラルの設定ができるメニューを引っ張り出して設定を行います.

(最初から表示されていれば問題ありません)

f:id:masa_flyu:20190527224945j:plain

TIM3の設定を開いて,「Combined Channels」をEncoder Modeにします.

すると,先ほど黄色で表示されていたピンが緑色に色付けされるはずです.

もう少し詳しい設定をします.

f:id:masa_flyu:20190527232144j:plain

先ほどの設定の下側にさらに詳しい設定「Parameter Settings」があります.

このうち下記を変更します.

  • Counter Period : 0 → 65535
  • Encoder Mode : Encoder Mode TI1 → Encoder Mode TI1 and TI2
Counter Period

Counter Periodはカウンタの範囲を決定するためのもので,これを超えたときにプログラムへの割込みを設定することができます.

0〜65535まで設定できます.

初期設定の0ではカウントできないため必ず変更する必要があります(なぜ初期設定が0???).

Encoder Mode

Encoder Modeは エンコーダのどの入力が変化したときにカウントを変えるかを決定します.

初期設定ではA相だけでしか変化しない状態なので,A相,B相で変化させることで,より細かく値が変化します.これにより100[Pulse/rev]のエンコーダを用いて,400[Count/rev]を利用できます.

これにて設定は終了です.

f:id:masa_flyu:20190524025222j:plain

左の「Project Explorer」メニューから「main.c」を開きます.

作成完了

f:id:masa_flyu:20190524025237j:plain

これがmainプログラムです.

すでに自動生成された設定などが記述されています.

エンコーダ読み取りプログラム

プログラムを書く上での注意

f:id:masa_flyu:20190524030604j:plain

mainプログラムを下にスクロールすると,main()関数が見えてきます.

main関数の中もいろいろと記述済みですが,こちらを追記していきます.

その際に注意しなければならないのが「自分で書いたプログラムが勝手に削除される場合がある」ことです.

main.cはマイコンの設定に応じて自動で書き換えられますが,その際,「指定の場所」以外に書かれたプログラムは削除されていしまいます.

f:id:masa_flyu:20190524031522j:plain

必ず,

/*USER CODE BEGIN xxx */

/*USER CODE END xxx */

間に記述するようにしてください.

またこのコメントを消さないでください.

インクルード文

今回はC言語の標準入出力関数などをインクルードして

  • sprintf()
  • strlen()

を使用したいので,

  • stdio.h
  • string.h

をインクルードします.

以下のように,「USER CODE BEGIN Includes」の下に2行追加します.

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "string.h"

/* USER CODE END Includes */

main関数

main関数には「USER CODE BEGIN〜END 2」の中に3行と「USERCODE BEGIN〜END WHILE」の中に4行追記します.

「HAL_TIM_Encoder_Start()」関数を使うことで,エンコーダのカウントをスタートできます. また,「TIM3->CNT」を参照することで今のカウントを随時読むことができます. 「HAL_UART_Transmit()」でUARTを経由してMacに値を送信しています.

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM3_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
  HAL_TIM_Encoder_Start(&htim3,TIM_CHANNEL_ALL);
  int cnt;
  char scnt[100];
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    cnt = TIM3 -> CNT;
    sprintf(scnt, "%d\r\n", cnt);
    HAL_UART_Transmit( &huart2, scnt, strlen(scnt) + 1, 0xFFFF);
    HAL_Delay( 100 );
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

エンコーダの接続

ハードウェアを接続します.今回接続するエンコーダはAliexpressで購入したこちらのエンコーダです(Aliexpressはすぐリンク切れするのでリンク貼りません,Aliexpressで「rotary encoder 600」とかで検索すれば出ます).

f:id:masa_flyu:20190528211053j:plain

エンコーダにもいくつか種類があって,今回購入したものはオープンコレクタタイプでした.

通常のエンコーダであれば電源と出力を直接つなぐだけで良いですが...

f:id:masa_flyu:20190528213450p:plain

オープンコレクタタイプでは外部にプルアップ抵抗を接続する必要があります.

その代わり,エンコーダの電源電圧とI/Oの電源電圧を変えることができます(同じ電源でももちろんOK).

プルアップ抵抗は10kΩとかその辺の適当に大きな抵抗をA相⇔3.3V,B相⇔3.3Vに接続しておけば大丈夫です.

f:id:masa_flyu:20190528213509p:plain

今回は下記のような感じで接続しました.

f:id:masa_flyu:20190528220021p:plain

D11,D12という名前はArduino準拠にしたもので,STMの呼称ではありません.Arduino互換端子のすぐ隣にあるピンは同じ機能ですので,どちらを使っても構いません.

f:id:masa_flyu:20190528221542p:plain

書き込み

UARTの時と手順は同じです.

macでUARTを見る

UARTの時と手順は同じです.

今回のプログラムを実行すると,エンコーダのカウント値が延々と出力されます.

f:id:masa_flyu:20190528221129j:plain

参考文献

STM32 HALドライバー公式ドキュメント

STM32F3 HALでエンコーダ入力 - 北の国から

当ブログをご利用いただく際には免責事項をお読みください。