こんにちは、しゅうです。
前回はモータの制御のための下準備を行いました。
今回は、回路を組んだり、プログラムを出力してモータを回転させてみます!
ちょっと長めに書いております。
回路
モータドライバ・モータ・NUCLEOボードの接続関係を図示してみます。
今回使うモータドライバ、DRV8835にはMODEピンがあります。そのMODEは2つあり、IN/INとPHASE/ENABLEの2種類のモータ制御方法が提供されています。今回使うモジュールのデータシートを参照しましょう。こちらは必要事項を簡単にまとめているので、より詳しい情報はDRV8835のメーカーTexas Instrumentから出ているデータシートを見てみましょう。
このMODEピンへの入力がHIGHの時はIN/IN、LOWの時はPHASE/ENABLEモードに切り替わります。この2つはモータ制御モードで、それぞれ下記の表に示すような特徴があります。

DRV8835のデータシートより抜粋
IN/INモードにある、Coastというのはモータが空転になる状態です。これにより慣性を用いた減速をすることができます。今回のマイクロマウスおいては、空転状態にする必要は特にないので、基本的にPHASE/ENABLEモードでモータ制御を行います。すなわちMODEピンにはHigh(論理値でいう1)を入れることになります。なので、3V3や5Vに接続すれば問題ありませんが、将来的にIN/INモードで制御する可能性があるかもしれないので、MODE用のGPIOピンを設定します。
次はモータの回転方向と速度を決めます。先程のTable4によれば、ENABLEに0を送るとPHASEの値に関係なくモータの動作がブレーキになることがわかります。すなわち、PHASEで回転方向を指定し、ENABLEで回転速度を指定します。
今回使うモジュールにおいては、AIN1がPHASE、AIN2がENABLEに割り振られています。モータをとりあえず正回転させるならば、AIN1に0を、AIN2にPWMを入力します。
残りはVCC、VMには3V3を接続しておいて、GNDも接続しておきます(データシートより、VCCは2~7V、VMは0~11Vが接続できます)。ブレットボードを用いた実際の接続例は次の画像のようになります。NUCLEOボード側のピン配置については次の章でお話しします。
全体を写すと、何がどこにつながっているかわかりづらくなってしまうので、概略を以下の図で示します。
プログラムの出力
いつも通り雛形を作ります。NUCLEOボードを選択してそれにUART通信の設定をした状態からスタートします(こちらの記事を参照してください)。まず初めにタイマーの設定をします。
左側の、TimersからTIM1を選択しましょう。続けて、Clock SourceはInternal Clock(内部クロック)を選択し、Channel1はPWM Generation CH1を選択します。下記画像に示してます。また、この時のピン配置は自動的にPA8に割り振られています。
タイマーについてはこちらの記事を参考にして、下記画像の部分を設定します。Parameter Settingsのタブを選択して表示してください。場合によっては違うタブが表示されるので矢印キーなどで適宜変更してください。
PrescalerとCounter Periodを設定します。
PrescalerはClock Sourceに対する分周、Counter Periodは何カウントしたら1周するかをそれぞれ設定します。
ここで、PWM周波数は次の式のように計算されます。
PWM Frequency[Hz] = Clock Source[Hz]/(Prescaler*Counter Period)
例えば、PWM周波数を1kHzにする場合は、Clock Sourceが32MHz、Prescalerを32、Counter Periodを1000に設定します。以下計算式です。
1[kHz] = 32[MHz]/(32*1000)
Clock Sourceの値はSTM32CubeIDEのClock Configurationタブに移って下記画像の赤丸で囲んでいるところで見ることができます。今回は32MHzに設定していますが、64MHzなど他の周期にも設定可能です。
そして、STM32の仕様上0からカウントが始まりますので、Prescalerは32-1、Counter Periodは1000-1に設定します。下記画像は実際の設定を行った後の画像になります。
以上でPWM用のピン設定ができたので、あとは回転方向を決めるためのピンにPB1を、MODE用にPA9を割り振ります。この2つはどのピンでも問題ないのでひとまずはNUCLEOボード上で接続しやすい場所を選んでいます。下記画像は最終的なピン配置の結果になります。ピンのところを右クリックすると、ラベル名を変更することができるので、今回はそれぞれにAIN1, AIN2, MODEのラベルをつけました。増えてくると分からなくなりやすいので…!
また、今回新たに設定したピン配置を下記表にもまとめております。
STM32F103RB | DRV8835 |
---|---|
PA9 | MODE |
PB1 | AIN1 |
PA8 | AIN2 |
プログラムの追加
今回は新たに3つの関数を使い、PWM出力を実現します。
- __HAL_TIM_SET_COMPARE
- 第1引数で使用するタイマー、第2引数で使用するチャンネル、第3引数でデューティ比を求めるための値を指定
- 第3引数の最大値はSTM32CubeIDEの方で設定したCounter Periodになります
- 注意:頭のアンダースコアは2つ
- HAL_TIM_PWM_Start
- 第1引数で使用するタイマー、第2引数で使用するチャンネルを指定
- PWM出力を開始
- HAL_TIM_PWM_Stop
- 第1引数で使用するタイマー、第2引数で使用するチャンネルを指定
- PWM出力を停止
そして、HAL_GPIO_WritePin関数を使ってPB1(回転方向の指定)とPA9(MODE用)に1を出力させます。
以上を踏まえて、main.cに追加したコードを下記に示します。
/* USER CODE BEGIN 2 */ HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, 1); // Mode selection /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, 1); // Rotation direction __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 500); // Sets the duty ratio, maximum value = Counter Period HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); // Start PWM output HAL_Delay(1000); // Rotate for 1 second HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1); // Stop PWM output /* USER CODE END WHILE */
あとはビルドして、エラーがないか確認し、NUCLEOボードとPCを繋げて書き込みましょう!
書き込みするとすぐモータが回るので注意してください!
実行!
無事モータが回りました!以下のGIFでは、リセットボタンを使って、モータの回転を止めたり開始したりをしています。
まとめ
以上、モータの回転までできました。
__HAL_TIM_SET_COMPARE関数を使うとき、先にデューティ比を決めておくとプログラムが書きやすく実現したい制御もわかりやすくなるかもしれませんね。すなわち、__HAL_TIM_SET_COMPARE関数の第3引数を決めうちの値ではなく、デューティ比から計算するように定義することです。
また、PWMの周波数が1kHzで良いのかも考えておく必要がありそうです。
次回はエンコーダの値を記録して、表示させていきます。
そういえば、STM32CubeIDEのUIがちょっと変わりましたね?どうやら表示の設定があるそうですが、今回たまたまこの様に開かれました。詳しい設定方法が分かり次第、どこかで記しておきます!