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のビルドに対応します。-\cos(2\theta)\end{array}\right)\]について考えます。モータ制御をするにあたって、次のような性質がある行列が分かると便利です。「α,β平面にある任意の点xを、”角度θを対称とする角度かつ、原点からの距離がxと同じ”点に映す。何言ってるかわからないので、下の図を見てください。はい、これを考えていきます。考えるにあたり、変換を次のように解釈すれば容易です。1回転行列をかけて補助線0度にする。20度を中心の鏡映変換を考えてあげる(ここではTとします。)3補助線をもとの角度θに戻す。この操作をすることで、\[Q(\theta)=R(\theta)TR(-\theta)\]という行列に変換できます。(結局Tで鏡映変換しているので、面倒くさくしてるだけじゃん!)と思われると思いますが、0度の鏡映変換は、β(y座標)を反転させるだけなので、極めて簡単な行列で表現できます。-1\end{pmatrix}\]これを使って以下のように計算できます。-\cos(2\theta)\end{pmatrix}\]\[=Q(\theta)\]つまり、θを対称とする鏡映変換は、このような2θの三角関数の行列で表現できる訳です。・コントローラ・ドライバなどとそれぞれ分かれているため、配線などが煩雑になってしまいます。私は(現実ではなく)インターネット上で知り合った方と一緒にモータ制御をやっているため、個人個人の環境で全然違う事が起こる現象、いわゆる「おま環」が発生するのを嫌い、作ってみました。マイコン基板を作ります。途中遊びでレース柄の基板も作ってみました。仕事じゃないのでオシャレな柄で作りたいなーって思って作っているのですが、流石にフットプリントが全く見えないデザインは、実装がしんどいので、今度は実装まで頼もうと思います...3相ドライバは中華製のものを購入しました。以下が実際に作成したものを、中華製の市販品に接続してる風景です。CADを作成して、アクリルは発注して作ってもらいました。本棚にも収まるので、制御則など、理論を触りたい人にとってはとても収まりが良いかと思います。2020年5月19日CubeIDEでBoostを使うC++には、constexprやTemplateといった、強力なコンパイル時処理の仕組みがあります。これを活用することで実行時には超高速で処理することができるようになったりしますが、いちいち自分で作っていくのも大変なので、今回はBoostライブラリを活用する方法を紹介致します。CubeIDEに加えて、arm-none-eabi-gccのインストールされている環境が必須です。(UTC)BoostVersion1.72.0https://www.boost.org/users/download/arm-none-eabi-gccVer8.2.01ダウンロード+コンパイルBoostの公式ページ(https://www.boost.org/users/download/)から、ダウンロードしてきて、展開します。(展開後に、Boost1_72_0というフォルダが作られていると思います。)次に、Boost1_72_0/user-config.jamというファイルを作り以下を記述します。–versionが正しくバージョンを返す事を確認してください。何も反応が無いようでしたら、環境変数でarm-none-eabi-gccのpathが通っていないと思います。arm-none-eabi-gccのインストール作業を見直してください。内にコマンドプロンプトを立ち上げます。私の場合は、次のようになっています。E:\Boost\boost_1_72_0>ここで、次のようにコマンドを入力すると、コンパイルが行われます。installバージョン等は適宜読み替えてください。いうフォルダが生成されます。ここにライブラリの本体が入っています。本当はCubeIDEにライブラリのリンクを設定するべきですが、今回は簡単のために、全部プロジェクトファイル内にコピーして進めていきます。使いたいプロジェクト(今回は「STM32H743ZI_BOOST」としました。)内に、Boostというフォルダを作成します。プロジェクト名(右クリック)>New>Folderなどから簡単に作れると思います。次にプロジェクト設定を操作します。pathsからインクルードパスを設定できます。ここに、../Boostを追加します。画像は既に追加済みです。最後に、Boostの本体をコピーしてきます。先程作った、プロジェクト内のBoostフォルダをエクスプローラで開いて、\ArmM\include\boost-1_72\boostを\STM32CubeIDE\workspace_1.0.0\STM32H743ZI_BOOST\Boost内にコピーします。Boostの中にboostがあり、紛らわしい状況ですが注意してください。以上で、Boostの導入は終了です、お疲れさまでした。BOOST_VERSION;}のようなソースを、コンパイルしてみると良いと思います。コンパイルに成功したら、導入が成功しています。Boostは主にアプリケーション向けのライブラリとして幅広く使われておりますが、組み込みでも活躍できると思います。別ページに書こうと思いますが、Sprintfの置き換えとして、Boost::spirit::karmaを使うことで、3倍?程度早くなることは確認しています。代償としてコンパイル時間がboostされますが...今後コンパイル時間を短縮する工夫を書いていければと思います。標準で入っているJ-Link関連の物のバージョンが古いため、STM32H7でのデバッグでは少し調子が悪そうに動きます。そのため、今回は無理やりバージョンアップする方法を紹介します。downloadsから、自分の環境にあったものをダウンロード。インストーラの形式で配布されているので、指示に従ってインストール。(x86)\SEGGER\JLink_V652」にインストールしましたので、ご自身の環境に合わせて読んでください。「C:\ST\STM32CubeIDE_1.0.0\STM32CubeIDE\plugins\com.st.stm32cube.ide.mcu.externaltools.jlink.win32_1.0.0.201904160814\tools\bin」にあります。「C:\ST\STM32CubeIDE_1.0.0\STM32CubeIDE\plugins\com.st.stm32cube.ide.mcu.externaltools.jlink.win32_1.0.0.201904160814\tools\bin」内にコピーします。「C:\ST\STM32CubeIDE_1.0.0\STM32CubeIDE\plugins」内部を「JLink」などで検索すると目的のディレクトリが見つかります。(念の為バックアップ取っておいたほうがいいと思います。SoftwareがCubeIDE内で利用できるようになります。CubeIDE環境で、UTF-8に対応する「ええっ!?このIDEはUTF-8に対応していないの???」いや、対応はしているんです。私達が文字を認識できないだけでして...早速環境の設定をしていきます。以下、執筆時の環境です。開発したいプロジェクトのプロパティを開きます。Mac:Command+I)を押してください。適当に画像のようにチェックを入れればOKです。私はWindowsのほか、Macでも開発をするので、Other:Linuxに設定してあります。Macの方はここで終わりです。内容が無い記事でごめんなさい。以下Windowsの方。2フォントを変更するCubeIDEの標準のフォントは、一部日本語に対応していません。Fontsを開きます。Fontを、フォント名をConsolasからお好きなものに変更します。読みやすいと思います。Takaoフォントは、https://launchpad.net/takao-fontsからTakaoFonts_xxxxx.xx.zipをダウンロードして、インストールするだけで、Windows環境でも利用できるようになります。これでコメントアウトが文字化けして困る事もなくなりました。以上です、お疲れ様でした。・J-Linkを繋げたいとか、諸々の都合でJTAGで接続することがあるかと思います。毎回接続ピンが行方不明になって調べているので、メモとして残しておきます。みんな細かいことよりさっさと接続関係が欲しいのは理解していますから。このとき、基板上のST-LinkV2/1にあるCN2のジャンパはすべてオープンにしてあります。1JTAGのピンについてJ-Linkのデータシート・UM08001によると以下のようになっています。20-pinのピン配置は、(デバッガのオプション的なピンを除いて)どのデバッガでもほとんど変わりはなく、STLinkV2/V3等でも僅かな違いがあるものの、利用できます。次のようにつなぎます。signal参考にしたデータシートはJ-Linkのデータシートのほか、F405データシートであるDocID022152が参考になります。2Nucleoボードとのピンの関係これらより、3V3,GND,PB4,PA15,PA13,PA14,PB3,NRSTを接続すれば動作することがわかりました。Nucleoボードの場合、ピンアサインがめちゃくちゃなので、自分でマイコンピンとの対応を考える必要があります。UM1724P.35には以下のような図があります。これを見て比較するのが楽かと思います。以上の作業を得て、一番最初の接続関係が導けます。