2020年6月6日モータ制御のためのTIM/ADC設定(STM32・コード記述編)前回はCubeMXでの設定をしました。モータ制御のためのTIM/ADC設定(STM32・CubeMX編)今回はこちらの設定をCubeMXで吐いたコードを編集します。1CubeIDEプロジェクトの作成こちらの手順にしたがい、CubeIDEで開発できる環境を整えてください。C++を利用して記述するため、C++に対応できるようにMakefileを編集してください。Makefile+CubeMX+CubeIDEでSTM32開発MakefileをC++に対応させる編集箇所が多いので、抜けていたり、環境がイタズラしたりと、うまく行かないことがあると思います。そのようなときのために、編集済み・確認済みのgitを用意しておきましたので、こちらを利用してください。main()を適当に編集します。*/}MX_TIM1_Init();でCubeMXで指定したタイマの設定がされます。MX_ADC1_Init();でCubeMXで指定したADCの設定がされます。これらは内部でレジスタを設定しています。してジャンプしていくと、いずれはレジスタを叩いている場所に飛べるはずです。TIM_CHANNEL_1)でTIM1のCH1のPWMを出力します。9990;ではレジスタを直叩きします。それぞれの意味は以下の通りです。(170MHzのクロックを、10KHzまで分周します)TIM1のカウンターを10000に設定。(10000でリセットがかかる)CH1の閾値を7500に設定。CH2の閾値を5000に設定。CH3の閾値を2500に設定。CH4の閾値を9990に設定。7500);などがありますが、全部同値です。マクロ仲介してわかりにくくなってるだけなので、直叩きしています。HALの構造体を再度宣言して、HAL_TIM_PWM_ConfigChannel()関数を叩く手法もありますが、こちらは処理時間的に勿体ないので使いません。mySqrtの宣言・定義は前回のcppに対応する記事を見てください。2stm32g4xx_it.cを記述こちらにADCの終了割り込み時の動作を記述します。別に他の所に関数を書いてもいいのですが、今回はお試しなのでここに全部書いちゃいます。ADC1_2_IRQHandler(void)内に書いていきます。“usart.h”が必要になります。*/}ADCの動作が終了したタイミングで、こちらが呼ばれて、USARTでADCの入力値を返します。JDR3;こちらがADCの値が格納されているレジスタです。レジスタを叩くときには、最適化を防止するためvolatileをつけることが肝心です。マイコンに書き込んでみると次のようになります。UARTの出力を見てみると、次のようになります。これらから、目的のタイミングで動作していることがわかりました。以上で全説明は終了です。今回作成したものは以下から取得できます。2020年6月6日モータ制御のためのTIM/ADC設定(STM32・CubeMX編)1概要モータ制御をするためには、PWMを出力するだけではなく、ADCで適切なタイミングで状態を読み取る必要があります。(適当な電圧出力だけでも回りはしますが、”それはモータ制御なのか?...”と問われると違うと思います。)一例として、以下の画像のようなタイミングで動作させることが、今回の目標です。DutyのPWMと、100%タイミングで、ADC用のトリガ信号を出力します。このトリガ信号を利用して、ADCを動かしてみます。“なぜこのタイミングでADCを動作させるか”というと実際の(3シャント方式電流検出の)モータドライバの回路は以下のようになっています。モータから流れる電流が、橙の丸で囲ったシャント抵抗に流れる電流を測定するには、ローサイド側のMOSFETが下がっている時しか(流れないので)検出できないのです。そのため、確実にFETがOFFになるタイマ100%時にADCを動作させます。以下が今回執筆時環境です。次のようにPWMを設定します。CH4と設定していきます。Compare(OC4REF)と設定していきます。今回は設定しませんでしたが、Prescalerに値を設定するとカウントを分周します。≒カウント動作が遅くなります。本来はここに10000などの値を設定しますが肝心な箇所なので、こんなコーダーに任せるよりも自分でソース内に記述したほうがいいよね???の精神で、今回は後で触ります。mode1を選ぶことによって、は山のようなカウンタの動作をします。Counter参照)TRGOの設定は、TRGO2にCH4のカウンタ値との比較の出力を出します。このTRGO2を利用して、今回はADCを動かしていきます。ChannelのPulseには、数値を入れることで、TIMのカウントと比較して、カウントよりもPulseの値が大きいときは出力をONにします。mode2にすることで負論理になります。Periodと同様、ソース内で変更します。覚えておいてください。Settingすべてにチェックをいれます。使わなくても特に損しないのでチェックを入れておきます。以上がPWM設定です。次にADCの設定に移ります。次のように設定します。Single-endedと設定していきます。図中では、IN2,IN12にもSingle-endedで使っていますが、モータの電流測定は上記3種の予定で、実際には以下のものを観測することを想定しております。IC温度出力なので、今回は駆動用の電流検出のみに目をむけて、ADC1のIN1,7,6のみ説明致します。6とりあえず設定項目が非常に多いので、大切な事だけ書きました。Injected_ConversionModeは割り込み要求用のADC設定です。Timer1のTRGO2から、立ち上がりエッジで割り込みがかかり、Ch1,Ch7,Ch6の順に変換します。この3チャンネルだけはこのようにタイマに連動した割り込みの設定が必要ですが、他のチャンネルはRegular_ConversionModeなどに入れて、適当に使えばよいです。Settingsチェックをいれます。以上が、ADCの設定の説明でした。あとは自分が使いたいものを増やしたりして、コードを生成すれば良いです。2020年5月20日MakefileをC++に対応させる前回、Makefileでのビルドを使ってLチカをしました。Makefile+CubeMX+CubeIDEでSTM32開発しかし、MakefileがC++でのビルドに対応していないので、cppファイルがあると読み込めません。変更してC++に対応させましたので、ここに残しておきます。makefileを以下のように編集します。$(BUILD_DIR)/*.d)前回との差分はこちらをご覧ください。次のテンプレートクラスを追加しています。val;}};これはニュートン法で平方根の値を求めるようなクラスです。=0.2236秒周期に収束するようなLチカをするようにしています。}以下にプロジェクトのリポジトリを残します。詰まったときに参考にしてください。CubeMXでコード生成3CubeIDEでデバッグとCubeIDEのみで全て完結します。一方で、この手法だと次のような欠点があります。・CubeIDEのバージョンアップやOS間、IDE間の移動に弱いCubeIDEは、基本的に同一のバージョンで利用することで安定したビルド環境が構築されますが、Makefileで管理すれば、CubeIDEだけでなく、VSCodeや他のIDEでもビルド環境が整います。面倒ですが、コマンドベースでの管理も可能です。・CubeIDE内のCubeMXが非常に酷なGUI狭い環境での操作を強要されます。(FullHDだと、ピン配置を見ながらタイマの設定なんてできたもんじゃないです。)CubeIDE内のMXではなく、CubeMXを単体で起動することで、ある程度開放されます。・プロジェクトファイルの管理がGUIベースインクルードパスなどの設定がEclipseベースGUIのため、ソースで管理しにくいです。xmlなので、ゴリ押し設定をできなくはないですが、そこまでしてやる意味あるの?と言われてしまうと疑問です。これらを解決するために、次のような手法を取ることで、より簡単に開発することができます。Debugを利用して開発をすすめる以下に概要図を載せます。それでは実際に作ってみましょう。今回はSTM32G431RBTの載った、NUCLEO-G431RBを使ってLチカをするプロジェクトを実際に作ってみます。今回は特にバージョンに縛られませんが、以下の環境にて確認致しました。Projectを作成CubeMXを利用してMakefileのプロジェクトを作成します。Projectから、マイコンを選ぶ。Mode?」の文字が出るので、迷わずYes。これはマイコンボードの標準の配置に(LEDなどすでにピンが確定しているもの)勝手に配置してくれます。このページを見ている皆様には釈迦に説法かもしれませんが、このページでピン配置や内部機能を設定することができます。今回はLチカができれば良いので、何も触らない。Managerタブに移り、ProjectNameを入力。今回は「G431RBMakeProj」とした。Toolchain/IDEに「Makefile」を入力。peripheralにチェックを入れる。これを入れることで、main.cにすべてのイニシャライズコードが記述されず、ソースが分離されるので管理しやすくなる。Projectのコードが作られる。Projectを作成します。ProjectこちらもNUCLEO-G431RBを選んでNextを押す。今回はProjectNameを「G431RB_Proj」としました。TypeにEmptyが選択されていることに注意。Finishを押すことでプロジェクトが生成されます。ここでプロジェクト内のすべてを消しておいてください。プロジェクトへ中身をコピーします。重複しているものは上書き保存です。CubeIDEに戻ります。このままだと、CubeIDEを再起動するまでコピーしたものが見えないので、プロジェクトをリフレッシュします。Settingsから次のように変更します。automaticallyのチェックを外す。directoryを次のようにする。(Buildを消す)これでプロジェクトの設定が終了しました。本当はこの段階ですべての工程が終了して、正しくビルド・デバッグが動作するはずですが、CubeMXのいつものガバで正しくビルドができないと思います。以下の工程は、そのうち必要なくなるかと思います。4Makefileを修正するMakefileの中のCPUを次のように直します。-mcpu=cortex-m45Lチカするmain関数にLチカコードを記述します。*/}手順は以上です。以下から本日作成したソースを取得できます。トラブルの際にご活用ください。LEDBlink_with_C以下に続きを書きました。Makefileを編集してcppのビルドに対応します。