マイコンテンプレートを使ったプロトタイプ開発の第3回は、シールド基板Joystick機能のテンプレート追加です。
4方向入力とプッシュ操作ができるジョイスティック(出典:Adafruit)
要旨
STM32Fx用テンプレート を題材にしましたが、他テンプレート でも同様です。説明が長くなったので、先に本投稿の開発手順と要旨を示します。
シンプルテンプレートをRenameし、「機能追加用テンプレートを作成」
API作成ツール、サンプルソフトやレファンレンスなどを利用し、「追加機能を理解」
「追加機能ファイルを作成」し、追加処理をプログラミング
ユーザ関数起動「Launcher()で追加処理を起動し、デバッグ」
要旨:マイコンテンプレートをプロトタイプ開発に利用すると、既に基本動作する枠組みやライブラリが準備済みなので、機能追加の開発効率が上がり、追加処理が1ファイルに閉じ込められるため、ソフトウェア資産として流用性も高まる。
シールド基板構成
機能追加に使うシールド基板は、SDカードに液晶表示画像が保存されており、カードから画像を読込み、それを液晶に出力する、これにMCUのSPIインタフェースを使う構成です。Joystickは、液晶表示の選択肢を入力するためのHMI(Human Machine Interface)に使います。
TFT液晶出力、SDカードのデータ入出力、Joystickでの5SW入力、これら3機能ハードウェアを追加するシールド基板(Source:Adafruit)
回路図からも解るようにJoystickは、シールド基板のSDカードやTFT液晶とは完全に別物です。1個のJoystickで「上下左右」と「プッシュ」の5入力を1本のADC入力だけで処理できますので、効率的で低価格なHMI実現手段の1つと言えます。
本投稿は、このJoystickのADC入力を弊社STM32Fxシンプルテンプレートへ追加し、ADC_Joystickプロジェクトを作り動作確認します。
関連投稿:テンプレート活用プロトタイピングの開発方針:第1回 とソフトウェア概要:第2回
テンプレート変更準備
今回は、初めてですので、少し丁寧に説明を加えます。
最初に、ワークスペースへシンプルテンプレートを取込み、これに「変更を加える前」にプロジェクト名をADC_JoystickへRenameします。
Template Project Rename
Renameを選択すると、プロジェクト名の入力ダイアログが現れますのでADC_Joystickと入力します。
さらに、「手動」でcfg/ico/pdf/txtの4ファイル名をADC_Joystick. cfg/ico/pdf/txtに変更します。
最後に、ADC_JoystickをClean ProjectとBuild Projectすると、正常にコンパイルされ、シンプルテンプレートからADC_JoystickへRenameが成功したことが確認できます。
Tips:リネームプロジェクト名は、「追加周辺回路_装置」としました。プロジェクト名を見れば、時間が経過した後でも、内容が解りやすいメリットがあります。
関連投稿:Eclipse IDEプロジェクトのImportやRename方法
また、レファレンスプロジェクトとしてTFTシールドサンプルソフトもワークスペースへ取込みます。方法は、
File>Import>Existing Projects into Workspaceで
Repository>STM32Cube FW F0 V1.9.0>Project>STM32F072RB-Nucleo>Demonstrations>STM32F072RB-Nucleoを選択しImportしてください。
以上で、2プロジェクトがワークスペースへ入り、ADC_Joystickに変更を加える準備ができました。
ADC_JoystickプロジェクトとTFTシールドサンプルソフト(STM32F072RB-Nucleo)がワークスペースへ入る
STM32CubeMXでADC追加
Joystickで利用するADCを、STM32CubeMX(以下CubeMX)でADC_Joystickプロジェクトへ追加します。
CubeMXを起動し前章で手動変更したADC_Joystick.icoをLoadすると、シンプルテンプレートのCubeMX設定がロードされます。これに周辺回路ADCを追加します。
ADCのIN8に☑を入れると、PB0ピン、PB.00を使うことが解ります。このPB.00がArduinoコネクタA3に接続されており、Joystickのアナログ値がADCへ入力されます。
STM32CubeMX Setting
通常は、ここでADCを利用するサンプルソフトなどを参照し、詳細設定を調べます。しかし今回は、もっと直接役立つレファレンスプロジェクトのADC関連ソースを読みます。
※レファンレンスソースは一部しか抜粋しませんので、解りにくいと思いますが、文章が分かれば十分です。
TFT_ShieldDetect Logic
ADC関連は、最初にmain.cのL120でシールド基板の実装有無を確認し、実装(SHIELED DETECTED)ならばTFTを初期化(BSP_LCD_Init())し、SDカードから画像読込み(SDCard_Config())を実行します。
L116のコメントから、PB.00電圧レベルで基板有無を確認していることが解ります。そこで、ShieledDetect()を読むと、アナログ入力として使う予定のPB.00を、ここでGPIO入力+プルダウンへ初期設定した後、電圧レベルを読込み、0以外で基板実装と判断しています。
PB.00をアナログ入力に設定しているのは、TFT_DisplayImages()の中、L304のBSP_JOY_Init()です。
つまり、最初にPB.00をGPIO入力+プルダウンに設定し、入力が0以外で基板実装と判断し、次に同じPB.00をADCのIN8に再設定(stm32f0xx_nucleo.cのL841)します。アナログ入力では基板有無の判定ができないのです。
プルダウンが設定できるGPIO入力なら基板無し(電圧レベル=0)の判定が可能です。また、ADC設定は、CubeMXのデフォルト設定で良いことも解ります。
Tips:「同じピン機能をADCからGPIOに切替えて実装有無を判断するテクニック」は、今回だけでなく他でも使えるので覚えておくと役立ちます。
以上、レファンレンスからADCの使い方が解りました。CubeMXへADC追加後のConfigurationタブを示します。CubeMX ProjectをセーブしGenerate Code、Generate Reportを実行し、初期化コードを生成して下さい。
STM32CubeMX Configuration
シールド基板実装判定GPIOとADCの切り替え
ADC_Joystickのmain.cには、PB.00のADC初期化コードMX_ADC_Init()がCubeMXにより自動追加されます。では、どこで基板実装有無を確認するかというと、L232のUserInit()で行います。
テンプレートに準備済みのUserInit()
UserInit()は、無限ループ実行直前に、何らかの独自設定をユーザが行うための関数です。テンプレートには初めからこの関数が準備されています。
Shield Detection Logic in UserInit
UserInit()のL128で基板実装判定のため、PB.00を再度GPIOに設定し直します。そして、判定結果をUSB経由のCOMポートへ出力します。テンプレートには、COMポート出力機能がありますので、簡単に判定結果が出力できます。
基板実装を確認したら、L146でPB.00を再再度ADCに設定します。
つまり、PB.00はCubeMXでADCとして初期設定しますが、UserInit()で基板実装判定のためGPIOに再設定し、実装済みならもう1度ADC初期設定をします。ADC初期設定コードは、CubeMX自動生成コードですので、将来ADC設定に変更が生じたとしてもCubeMXを変えれば良いだけで、ソースはそのまま使えます。
後は、ADCの値を読んで、stick位置を判断し、その結果も基板実装結果と同様、COMポートへ出力すればJoystick関連の追加処理は完成です。
STM32F0とSTM32F1のBSP
BSPはBoard Support Packageのことで、評価ボード用のライブラリです。
STM32F0用は、Drivers>BSP>stm32f0xx_nucleo.c/hです。STM32F1用は、stm32f1xx_nucleo.c/hです。
関連投稿:BSP解説は、コチラの投稿 のSTM32Fxファームウエア構成やHAL Examplesの章を参照。
Joystickのstick位置判断関数BSP_JOY_GetState()もこのBSPで提供されますが、面白いことに、F0用とF1用のBSP_JOY_GetState()の閾値が異なります。どちらも同一条件で動作するので異なる必要はありません。また、if~else if~else文で分岐するのも、処理時間が長くなります。
Difference Between F0 BSP_JOY_GetState() and F1
そこで、F0用のより広い判断閾値を使い、if文とgoto文で分岐する方法を用いました。
Stick Position Judgement
ADC_Joystickプロジェクト動作確認
Joystickのみ機能追加する場合に備え、stick位置のCOMポート出力、STM32F0xとF1xで共用のための#ifdef~#endifなどの関連処理を新規追加のJoystick.cファイルに集め、ADC_Joystickプロジェクトへ加えました。
ADC_Joystick File Configuration
シールド基板を実装すると評価ボード上の青SWが操作できませんので、ユーザ関数を起動するLauncher()のSwScan()はコメントアウトし、代わりに40ms周期起動にstick位置の取得判断関数:JoystickSacn()を入れました。
完成したADC_Joystickプロジェクト動作中のCOMポート出力例を示します。
ADC_Joystick COM Output Example
まとめ
STM32Fxシンプルテンプレートを使って、シールド基板のJoystick機能のみを追加しました。
長文説明になりましたが、実際に行った処理は、下記のようにとても簡単で単純です。
テンプレートプロジェクトをRenameし、ADC_Joystickプロジェクト作成
STM32CubeMXで、作成プロジェクトへADC機能を追加
レファレンスプロジェクトのADC関連部分を読み、使い方と設定理解
機能追加/削除を容易にするため、Joystick.cファイルを新規追加し、ADC関連処理記述
Launcher()で起動し、必要に応じて処理結果をCOMポートへ出力し、追加処理の動作確認
テンプレートには、COMポート出力やUserInit()などの基本的な処理と枠組み、BSPなど開発に必要となるライブラリが既に準備済みなので、「追加する処理にのみ集中して開発できる」ことがお判り頂けたと思います。
Joystickファイルを新規追加すると、機能の追加/削除、他プロジェクトへの応用も簡単です。ユーザが手動で変更する箇所は、ユーザ関数を起動するLauncher()やUserInit()、COMポートへの出力メッセージ程度で、初期化コードなどはAPI作成ツールSTM32CubeMXが自動的に生成します。