はじめに
今回は「STM32マイコンとTouchGFX GUI チャレンジ」という開発コンテストに応募すべく、この夏にでも活躍しそうな熱中症予防表示器を作ってみました。
数年前にSTM32マイコンは、ほんの少しだけ趣味として学習したことはあるのですが、Arduinoのようにお手軽には扱えなかったため、当時の私には難易度が高く、プロトタイプ製作までに至ることはなかったのですが、今回、軽い気持ちで応募した開発ボードプレゼントキャンペーンに当選、「何かを作る義務が発生してしまった!」ということで、一念発起して応募作品作りに取り組んでみました。
開発テーマを選定する
電子工作を趣味として楽しんでいる程度の私には、難しいことはできないので、以前に取り扱ったことのある温湿度センサーで何かできないかと考えた結果、今年の夏も暑い日が続くとのことで、熱中症の予防をテーマとして、「熱中症予防表示器」の製作を選定しました。
熱中症予防に利用できる指標として、以前に聞いたことがある、暑さ指数:WBGT(Wet Bulb Globe Temperature)を活用することにしました。評価ボードは画面も大きく視認性が良いためWBGT値によて画面全体の色が変化するようにすることで、警告状況が一目でわかるようにしました。
WBGTについて詳しく知りたい場合は、環境省の熱中症予防情報サイトや日本生気象学会の「日常生活における熱中症予防指針」Ver.4 が参考になります。
応募作品の製作準備をする
ハードウェアの準備をする
今回の開発で私が使用したデバイスは、当選したSTM32開発ボードを含めて以下となります。
・STM32U5G9J-DK2:ST MICRO
・環境センサユニット ver.2(ENV II):M5Stack
・GROVE – 4ピン – ジャンパオスケーブル:SEEED
STM32U5G9J-DK2と温湿度センサーユニットとの通信方式はI2Cとなり、ハードウェア的には、I2Cのクロック信号とデータ信号の2本と5V電源、GNDの合計4本を結線するのみの簡単なものとなります。
ソフトウェア開発環境の準備をする
今回のコンテストでは、STM32マイコンとTouchGFXを使用して製作することが条件となっているため、STmicroが提供している2つツールを使用してプログラムの開発を行いますので、STMicroの公式サイトからダウンロードしてPCにインストールします。
・TouchGFX
・STM32CubeIDE
プログラム開発
今回の開発で行うことは2つです。
1.TouchGFXを使用してLCD画面のデザイン設計する。
2.STM32CubeIDEを使用してC++でメインプログラムを作成する。プログラムでは次の処理をしています。
① I2Cでセンサーから温湿度データを読み取る。
② 温湿度データからWBGT値を求める。なお、WBGT値は配列に格納しておく。
③ WBGT値に従い画面の色を変化させる。
touchGFXで画面をデザインする
1.文字や温度の数値、湿度の数値、WBGT値をtextAreaを使用して画面に配置します。文字については、表示したい文字を”translation”に記載するだけですが、測定数値の表示については、Wildcardを使用します。
2.温度や湿度の下に時系列グラフを描画するためには、dynamicGraphを使用して画面に配置しました。多くのパラメータ設定があるので画面表示がどうなるのかを試しながらパラメータ値を決定しました。
3.画面レイアウトが完成すれば、右下の”</>”マークの Generate Code をクリックしてコードを生成します。
4.画面左下の”Files”をクリックし、表示されたフォルダーの一階層上に戻り、”STM32CubeIDE”フォルダに入り、”.project”ファイルをクリックして、CubeIDEを起動してプログラムの作成に取り掛かります。
参考として、私の開発環境だけなのかもしれませんが、画面の作りこみで手間取った点がありましたので紹介します。
当初、測定値の数字がうまく表示できず”?”マークが表示されてしまいました。ネットの情報も確認しながら試行錯誤してみたところ、
Texts – Typograhies にある文字設定の”Wildcard Ranges”にASCII文字にあたる”0x20-0x7E”を記載して数字の表示を許可することが必要だったことがわかりました。
STM32CubeIDEでプログラムコードを記述する
STM32マイコンのハードウェア端子設定
まず初めにセンサーとI2Cで通信するために、I2Cを使用できるようにSTM32マイコンの端子設定をします。
今回は評価ボードの裏面に配置視されているCNコネクタの”SCL/D15”と”SDA/D14”の端子を使用しました。この端子の場合は、初期状態でI2Cになっていたように思いますが、設定されていない場合は、CubeIDEの”Project Explorer”から”STM32U5G9J-DK2.ioc”ファイルをクリックしてpinoutの設定を行います。
画面のように、Connectivityの”I2C1″を選択後、MODEで”I2C”を選択します。Configurationは初期値のままで特に問題はありませんでした。
なお、ユーザーマニュアルを見るとTable 11に記載のある通り、I2C1のクロックとして”SCL/D15”がMCUの”PG14”に、I2C1のデータとして”SDA/D14”がMCUの”PG13”に接続されていることがわかります。
温度・湿度をセンサーから読み取るプログラムの作成
先人の方々によるお知恵を拝借しながら、I2C通信に関してはHALライブラリを使用することで簡単に行えました。
プログラムを記述するファイルは、今回の場合、先ほどTouchGFXで作成した画面のPropertiesの一番上に記載する名称を”Screen1”にしているため、Project Explorerでは、Applocation-User-guiの中にある”Screen1View.cpp”のファイルとなります。
あるいは、windows のエクスプローラーで見た時のファイルの保存場所は、C:TouchGFXで作成したProjectフォルダー名\TouchGFX\gui\src\screen1_screenの中にあります。
プログラムの動作フローとしては、
・10秒ごとに下記の3つを繰り返し、
①センサーから温度と湿度のデータを読み出す
②WBGT値を条件として画面全体の色を変化させる
③温度と湿度の測定値を表示する
・60秒ごとにグラフにプロットする動きとなっています。
void Screen1View::sht30() { uint8_t sh30_data[6] = {0}; uint8_t sht30_measure_cmd[2] = {0x24, 00}; // 測定コマンドの送信 HAL_I2C_Master_Transmit(&hi2c1, SHT30_I2C_ADDR << 1, sht30_measure_cmd, 2, 1000); // 測定完了待機 高精度の場合15msec以上を設定 HAL_Delay(20); // 測定値の読み出し HAL_I2C_Master_Receive(&hi2c1, SHT30_I2C_ADDR << 1, sh30_data, 6, 1000); // 湿度を算出する env_rh = 100.0 * (sh30_data[3] << 8 | sh30_data[4]) / 65535.0; // 温度を算出する env_t = -45.0 + 175.0 * (sh30_data[0] << 8 | sh30_data[1]) / 65535.0; /* 少数以下は切り上げとする */ int index_tmp = ceil(env_t) -21; int index_hum = ceil(env_rh) / 5 - 3; /* WBGT表示値を配列から読み取る */ int WBGT = WBGT_t[index_tmp][index_hum]; /* WBGT値を条件として画面の色を決定する */ if(WBGT<=20){ box5.setColor(touchgfx::Color::getColorFromRGB(0, 0, 255)); // RGB値で指定 blue boxWithBorder2.setColor(touchgfx::Color::getColorFromRGB(0, 0, 255)); } else if(WBGT<=24){ box5.setColor(touchgfx::Color::getColorFromRGB(0, 255, 0)); // RGB値で指定 green boxWithBorder2.setColor(touchgfx::Color::getColorFromRGB(0, 255, 0)); } else if(WBGT<=27){ box5.setColor(touchgfx::Color::getColorFromRGB(255, 255, 0)); // RGB値で指定 yellow boxWithBorder2.setColor(touchgfx::Color::getColorFromRGB(255, 255, 0)); } else if(WBGT<=30){ box5.setColor(touchgfx::Color::getColorFromRGB(255, 128, 0)); // RGB値で指定 orange boxWithBorder2.setColor(touchgfx::Color::getColorFromRGB(255, 128, 0)); } else{ box5.setColor(touchgfx::Color::getColorFromRGB(255, 0, 0)); // RGB値で指定 red boxWithBorder2.setColor(touchgfx::Color::getColorFromRGB(255, 0, 0)); } boxWithBorder2.invalidate(); /* 測定値を表示する */ touchgfx::Unicode::snprintfFloat(textArea1Buffer, TEXTAREA1_SIZE, "%.1f", env_t); textArea1.invalidate(); touchgfx::Unicode::snprintfFloat(textArea2Buffer, TEXTAREA2_SIZE, "%.1f", env_rh); textArea2.invalidate(); touchgfx::Unicode::snprintf(textArea3Buffer, TEXTAREA3_SIZE, "%d", WBGT); textArea3.invalidate(); Counter += 1; if (Counter >= 6) // // 60秒(3600フレーム)ごとにプロットする { // Insert data point dynamicGraph1.addDataPoint(env_t); dynamicGraph1.invalidate(); dynamicGraph2.addDataPoint(env_rh); dynamicGraph2.invalidate(); Counter = 0 ; } }
WBGTを配列で定義しておく
温度と湿度からWBGT値を決定するには、WBGT簡易推定図を参照して配列定義を行い使用しています。
推定図の左下の温度21℃と湿度20%の組み合わせをWBGT_t[0][0]=14として20行17列の2次元配列を作成しました。
具体的なプログラムの記述としては、次のように定義しています。
const int WBGT_t[20][17] = {{14,14,15,15,16,16,17,17,18,18,19,19,19,20,20,21,21}, {15,15,16,16,17,17,18,18,19,19,20,20,20,21,21,22,22}, {15,16,16,17,18,18,19,19,20,20,20,21,21,22,22,23,23}, {16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,24,24}, {17,17,18,19,19,20,20,21,21,22,22,23,23,24,24,25,25}, {18,18,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26}, {18,19,20,20,21,22,22,23,23,24,24,25,25,26,26,27,27}, {19,20,21,21,22,22,23,24,24,25,25,26,26,27,27,28,28}, {20,21,21,22,23,23,24,24,25,26,26,27,27,28,28,29,29}, {21,21,22,23,23,24,25,25,26,26,27,28,28,29,29,30,30}, {21,22,23,24,24,25,26,26,27,27,28,29,29,30,30,31,31}, {22,23,24,24,25,26,26,27,28,28,29,29,30,31,31,32,32}, {23,24,25,25,26,27,27,28,29,29,30,30,31,31,32,33,33}, {24,25,25,26,27,28,28,29,30,30,31,31,32,32,33,34,34}, {24,25,26,27,28,28,29,30,30,31,32,32,33,33,34,34,35}, {25,26,27,28,29,29,30,31,31,32,33,33,34,34,35,35,36}, {26,27,28,29,29,30,31,32,32,33,34,34,35,35,36,36,37}, {27,28,29,29,30,31,32,33,33,34,35,35,36,36,37,37,38}, {27,28,29,30,31,32,33,33,34,35,35,36,37,37,38,38,39}, {28,29,30,31,32,33,34,34,35,36,36,37,38,38,39,39,40}};
完成形の動作を確認する
それでは、派手な動きはないので面白みの無い動画かもしれませんが、コンテスト参加作品の動画をご覧ください。
おわりに
TouchGFXを使用することで、今回のような単純な画面であれば、ごく短時間で設計できますし、使いこなせば、画面デザインや画面にタッチした時の様々な動作について複雑な視覚的効果を実現できる有用な開発ソフトウェアだと感じました。
今回の作品製作に取り組んだ感想として、TouchGFXとCubeIDEを連携させての開発は、比較的お手軽に開発が始められるArduinoのようにデバイスライブラリーやインターネット情報が充実しているとは言い難いですが、STM32マイコンも趣味の電子工作でもじっくりと取り組めば興味深く面白いものだと思いました。
コメント