はじめに
STMicroelectronicsのIoTディスカバリボードのコレクションに新たに加わったB-U585I-IOT02Aは、STM32U585AII6Q MCUを搭載しているのが特徴です。STM32 MCUの超低消費電力カテゴリに分類されるSTM32U5シリーズは、同クラスの製品よりも強化されたパフォーマンスとセキュリティ機能を誇っています。これらの機能を利用して、このディスカバリ ボードには、多機能で安全かつ効率的なIoTアプリケーションをいくつでも開発するために使用できるコンポーネントが豊富に含まれています。またWiFiとBLEの通信モジュール、外部メモリ、および各種環境センサを搭載しています。
また、B-U585I-IOT02Aはカメラモジュール拡張コネクタを搭載しており、外部カメラモジュールの接続が可能です。特に、B-CAMS-OMVに同梱されているカメラモジュールMB1379は、ディスカバリボードと完全互換で、人気の高いOV5640 5-Mpixel CMOSイメージセンサをベースにしています。次のチュートリアルでは、白紙のプロジェクトから開始して、このモジュールとやり取りする方法を示します。
注:ただし、このコネクタのシルクスクリーン(図1)には、誤ってMB1183カメラモジュールを使用するように記載されています。これはいくつかの理由で間違っています。
-
MB1183モジュールは、単体ではお求めいただけません。本モジュールを搭載したST EVALボードを購入することでのみ入手可能です(AN5020の表4参照)。EVALボードはディスカバリボードやNUCLEOボードよりもかなり高価なため、このモジュールを入手するのはコスト的に厳しいかもしれません。
-
MB1183モジュールではカメラモジュールコネクタの1、2ピンに1.8Vを供給する必要がありますが、これらのピンはB-U585I-IOT02Aのテストポイントに接続されています(つまり、フローティングのままです)。そのため、このディスカバリボードでMB1183モジュールを使用することは可能ですが、まず適切な電圧を供給するために1.8Vの電圧レギュレータを追加する必要があります。図2に小型のSOT-23-3デバイスを用いた例を示します(AP2138N-1.8TRG1DICT-NDレギュレータを示しています)。
-
MB1183モジュールは、STのサポートが不十分なS5K5CAGAというCMOSイメージセンサを採用しています。ドライバは、OV5640センサ用のドライバと同様に、STM32U5 MCUパッケージおよびGitHubから入手可能です。しかし、S5K5CAGAドライバは古く、OV5640ドライバが提供する機能の多くがありません。
また、MB1066カメラモジュールの紹介もあります(例:AN5020)。しかしこのモジュールのピンアウトは、B-U585I-IOT02Aのカメラモジュールコネクタと互換性がありません。
図1: カメラモジュールコネクタの表記が誤って
いるシルクスクリーンマーキング
図2: CN7 の1pinに1.8Vを供給(MB1183 カメラ
モジュールを使用する際に必要)するために
B-U585I-IOT02Aにはんだ付けした小型電圧
レギュレータ(SOT-23-3 パッケージ)
必要条件
このチュートリアルに沿って進めるには、以下のソフトウェアとハードウェアが必要です。
-
STM32CubeIDE(バージョン1.11.0)
- 別のIDEを使用したい場合は、スタンドアロンのSTM32CubeMXツールを使用し、プロジェクト設定で別のToolchain/IDEを選択するオプションも用意されています。生成されたコードは、任意の開発環境にインポートすることができます。この方法でも、以下の手順はガイドラインとして使用できます。
-
B-U585I-IOT02Aディスカバリボード
-
B-CAMS-OMVバンドル
- カメラモジュールMB1379とアダプタボードが付属しています。
-
Micro-B USBケーブル(例:993-1294-ND)
手順
この手順では、STM32U5がカメラモジュールを制御して画像を読み取ることができるように、設定と初期化 を行う方法を説明します。また、カメラ本体(OV5640)のドライバを追加する方法と、コーディングをさらに簡素化するための抽象化レイヤを提供する方法も紹介しています。CubeMXの構成にこだわらず、動作する例から始めたい場合は、STM32CubeU5 MCUパッケージのBSP例があります。
ステップ1.STM32CubeIDEプロジェクトを作成する。
もちろん、既存のSTM32U5プロジェクトから始める場合は、このステップをスキップすることができます。
-
File > New > STM32 Projectを選択して、STM32プロジェクトウィザードを開始します。
-
STM32 Project Target Selectionツールで、Board Selectorタブを選択し、図3に示すようにB-U585I-IOT02Aボードを選択します(左側のボードフィルタを使用して検索を絞り込 みます)。Next > をクリックします。
-
プロジェクト名(例:「b-u585i-iot02a_camera」)を入力し、Finishをクリックします。プロジェクトの作成中に、いくつかのプロンプトが表示されますので、以下のように回答してください。
-
「Initialize all peripherals with their default Mode?」と表示されたら、Noをクリックします。
-
「Device Configuration Tool editor is associated with Device Configuration Tool perspective. Do you want to open this perspective now?(Device Configuration Toolエディタは、Device Configuration Toolのパースペクティブに関連しています。このパースペクティブを開きますか?)」と表示されたら、Yesをクリックします。
-
「The instruction cache (ICACHE) must be enabled to reach the maximum performance. The ICACHE can be enabled from the Pinout tab under ICACHE. Do you still want to generate code?(最大の性能を発揮するためには、命令キャッシュ(ICACHE)を有効にする必要があります。ICACHEはPinoutタブのICACHEから有効にすることができます。それでもコードを生成しますか?)」というプロンプトが表示されたら、Yesをクリックします。
-
ステップ2.STM32CubeMXの設定
-
Pinout & Configurationタブで、パースペクティブの左側にあるコンポーネントリストから ICACHEコンポーネントを選択し、 Modeを「1-way(direct mapped cache)」に変更します(図4)。
-
コンポーネントリストからI2C1ペリフェラルを選択します。Modeパネルで、I2Cオプションを「I2C」に変更し、そうすることでピンアウトビューのピンPB8とPB9が緑色になることを確認します(これらには既にユーザー ラベルが付いているはずです)。オプションとして、ConfigurationパネルのParameter Settingsタブで、 I2C Speed Modeを「Fast Mode」に変更します。これらの手順は、図5に示されています。
-
コンポーネントリストから、DCMIペリフェラルを選択します。
-
ModeパネルでDCMIオプションを「Slave 8 bits External Synchro」に変更します。
-
Configurationパネルで、Parameter Settingsタブを選択します。Pixel clock polarityを「Active on Rising Edge」に、Vertical synchronization polarityを「Active High」に、そしてHorizontal synchronization polarityを「Active High」に変更します(図6)。
-
ConfigurationパネルでNVIC Settingsタブを選択し、チェックボックスをオンにし「DCMI/PSSI global interrupt」を有効にします(図7)。
-
Configurationパネルで GPIO Settingsタブを選択し、図8に示すように信号表に合わせてピンの割り当てを変更します。最も簡単な方法は、STM32CubeMX User Manual (UM1718)の4.4.5節で説明されています。
手動で機能を別のピンに再割り当てする場合は、以下の順序で行います。
-
ピン配列図で、CTRLキーを押しながら、ピンを左クリックし、保持します。
移設可能なピンであれば、青くハイライトされ、点滅します。 -
機能を目的のピンまでドラッグします。
-
-
-
ピン配列図を使用して、図9に示すように、ピンPI1をGPIO_Inputに、ピンPI2とPI3をGPIO_Outputに設定します。
図9: 残りのカメラ制御信号を有効にする。PLUG、RSTI、
およびXSDN(UM2839の表27を参照)。 -
コンポーネントリストからGPIOペリフェラルを選択し、PI1、PI2、およびPI3ピンを図10に示す信号表と一致するように設定します。
-
コンポーネントリストから、GPDMA1を選択します。
-
Modeパネルで、Channel 12 - 8 Words Internal FIFO / 2D addressingオプションを「Linked-List Mode」に変更します。
-
ConfigurationパネルでCH12タブを選択し、Execution Mode (circular/linear) of the Linked Listオプションを「Circular」に設定します(図11)。
-
Configurationパネルで、NVIC Settingsタブを選択し、「GPDMA1 Channel 12 global interrupt」を有効にするためにチェックボックスをオンにします(図12)。
-
-
コンポーネントリストから、LINKEDLISTを選択します。
-
Add Listボタンをクリックし、「YourQueueName」リストを選択します。図13のハイライトで示されるように、リストを設定します。
-
S「YourNodeName」ノードを選択し、図14のハイライトで示すようにノードを設定します。
-
Add Nodeボタンをクリックし、「YourNodeName」ノードを選択します。DCMINode1(図14)とまったく同じようにノードを設定しますが、ノード名に「DCMINode2」を使用することだけが違います(図15)。
-
-
Project Managerタブを選択し、Code Generatorオプションに切り替えます。「Generate peripheral initialization as a pair of ‘.c/.h’ files per peripheral」の横のボックスをチェックします。これは図16で示されています。
-
*.iocファイルを保存します(File > Savee)。「Do you want to generate Code?」というプロンプトが表示されたら、Yes.をクリックします。
ステップ3:リンクリストを初期化する
ステップ2(g)でリンクリストを設定しましたが、.iocファイルを保存する際にすべての初期化コードが自動生成されるわけではありません。リンクリストキューをGPDMAのチャンネル12に関連付けるには、main.c
ファイルに以下のコードスニペットを追加する必要があります。
-
main.c
ファイルで、USER CODE Includes
セクションに#include "linked_list.h"
という指令文を追加してください。 -
USER CODE PV
セクションに、以下のコード行を追加します。extern DMA_QListTypeDef DCMIQueue;
-
USER CODE 2
セクションに、以下のコード行を追加します。MX_DCMIQueue_Config(); HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel12, &DCMIQueue); __HAL_LINKDMA(&hdcmi, DMA_Handle, handle_GPDMA1_Channel12);
これらのサブステップは、以下の図17にまとめられています。この時点で、プロジェクトは正常にビルドされるはずです。
図17: 以前に設定した「DCMIQueue」をGPDMA1のチャネル12に
関連付けるように、main.c
ファイルを変更する。
ステップ4:カメラドライバを追加する
-
まず、OV5640ドライバを入手/配置する必要があります。これはSTM32CubeU5 MCU packageに含まれており、またstm32-ov5640 GitHub repositoryからも入手可能です。しかし、プロジェクトの作成にSTM32CubeIDEを使用したため、STM32CubeU5 MCUのパッケージが自動的にダウンロードされ、ローカルのSTM32Cube Repositoryに保存されています。ローカルリポジトリがマシンのどこにあるかわからない場合は、Window > Preferencesを選択し、STM32CubeカテゴリからFirmware Updaterを選択してください。すると、図18に示すように、ファームウェアのインストールリポジトリのパスが表示されます。以下のステップ4(d)では、この場所を使用することにします。
-
Project ExplorerでDriversディレクトリを右クリックし、Import… を選択します(図19)。
-
GeneralカテゴリからFile Systemを選択します(図20)。Next > をクリックします。
図20: インポートするリソースとして File System を選択する。 -
STM32CubeU5 MCU PackageのDriversディレクトリに移動します(上記のステップ4(a)に示しています)。ov5640 ドライバの横のボックスをチェックして選択します(図21 を参照)。Finish.をクリックします。
-
新しいヘッダファイルがプロジェクトに追加されたとき、コンパイラがそれらを見つけることができるように、それらを含むフォルダのパスがインクルードパスのリストに含まれている必要があります。Project Explorerで、先ほど追加したov5640ディレクトリを右クリックし、Add/remove include paths… を選択します(図22)。Select configurations to modifyダイアログボックスが表示されたら、「Debug」と「Release」の両方のオプションの横にあるボックスにチェックが入っていることを確認し、OKをクリックします。
ステップ5:BSPドライバを追加する
-
stripped-down B-U585I-IOT02A BSP files repositoryの内容をダウンロードし、B-U585I-IOT02Aディレクトリを<project_name>/Drivers/BSPディレクトリにコピーします。
-
ステップ4(e)と同様に、この新しいディレクトリをインクルードパスのリストに追加します。つまり、Project ExplorerでB-U585I-IOT02Aディレクトリを右クリックし、Add/remove include paths… を選択してください。そして、OKをクリックします。この時点で、プロジェクトには図23に示すようなドライバファイルが含まれています。
-
最後に
main.c
ファイルで、USER CODE Includes
セクションに#include "b_u585i_iot02a_camera.h"
という指令文を追加してください。
使用例
以上の手順で、STM32U5の設定/初期化、イメージセンサドライバの追加、BSP抽象化レイヤの組み込みを行うことで、接続したカメラモジュールのドーターボードから簡単に画像を取り込むことができます。その例として、カメラを初期化し、640x480サイズの画像を取り込み、SRAMにあるデータバッファに保存するコードを以下に示します。B-U585I-IOT02Aにはディスプレイが搭載されていないため、SRAMから画像を読み出し、PCで閲覧する方法がいくつか考えられますので、次章でご紹介します。
-
STM32CubeIDEで
main.c
ファイルを開いてください。USER CODE PV
セクションに、以下のコードを追加します。uint32_t CameraBuf[640*480/2]; volatile uint8_t frameFlag;
-
USER CODE 0
セクションに、以下のコードを追加します。void BSP_CAMERA_FrameEventCallback(uint32_t Instance) { frameFlag = 1; }
-
USER CODE 2
セクションに、以下のコードを追加します。// Start w/ LEDs off HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin, GPIO_PIN_SET); // Initialize camera if (BSP_CAMERA_Init(0, CAMERA_R640x480, CAMERA_PF_RGB565) != BSP_ERROR_NONE) { HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin, GPIO_PIN_RESET); } else { HAL_Delay(1000); // give the camera time to return good images // Take snapshot frameFlag = 0; BSP_CAMERA_Start(0, (uint8_t *)CameraBuf, CAMERA_MODE_SNAPSHOT); while (frameFlag == 0); HAL_GPIO_WritePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin, GPIO_PIN_RESET); }
これでプロジェクトが正常にビルドされます(Project > Build Project)。各ピクセルが2バイトのストレージを必要とする生のRGB565画像を保存しているため、RAMの使用率が非常に高いことに注意してください。したがって、640×480ピクセルには、(使用可能なSRAM768KiBのうち)600KiBのメモリが必要です。
取り込んだ画像を見る
追加ソフトウェアのインストールや追加コードの記述なしにデバイスメモリからデータを読み出す最も簡単な方法は、STM32CubeIDEデバッグツールを使用することです。
-
MB1379カメラモジュールをB-U585I-IOT02AディスカバリボードのCN7カメラコネクタに挿し込みます。PCとディスカバリボードのCN8 ST-LINK USBコネクタの間にUSBケーブルを接続します。
-
STM32CubeIDE プロジェクトをデバッグします(例:Run > Debug)。アプリケーションを初めて起動する場合は、Edit launch configuration properties(起動設定プロパティの編集)ダイアログボックスが表示されます。表示された場合は、OK.をクリックします。
-
アプリケーションがロードされ、デバッグセッションが開始されると、プログラムは
main()
関数の先頭で中断されます。 Run > Resume.を選択して、プログラムの実行を続行します。 -
B-U585I-IOT02Aの緑色のユーザーLED(LD7)が点灯したら、画像の取り込みは完了です。Run > Suspend.を選択して、デバッグセッションを一時停止します。
-
図24に示すように、Memoryビューを開き(Window > Show View > Memory)、緑色のプラス記号をクリックして、モニタする新しいアドレスを追加します。表示されたダイアログボックスで、テキストフィールドに「CameraBuf」と入力し、OKをクリックします。
図24: 進行中のデバッグセッションでMemoryビューにメモリモニタを作成する。 -
MemoryビューでExportアイコンをクリックします。表示されたExport Memoryダイアログボックスで、Formatオプションを「RAW Binary」に変更します。Lengthオプションには、CameraBuf配列の長さを入力します。CameraBuf を
uint32_t CameraBuf[640*480/2];
として定義したことを思い出してください。 したがって、\textrm{Length} = \frac{640 \cdot 480}{2} \cdot 4File nameフィールドに出力ファイルのパスを入力します。OKをクリックします(図25)。
-
RGB565の生画像を使用可能な形式に変換するには、幅広く使用されているffmpegツールを使用することができます。また、GIMPを使った代替案も以下に紹介します。インストールされていることを前提に、お好みのターミナルアプリケーションを開き、ffmpegを使って、以下のコマンドでRGB565画像をPNG画像に変換してください。図26のような出力が表示されます。
ffmpeg -vcodec rawvideo -f rawvideo -pix_fmt rgb565 -s 640x480 -i <input_file> -f image2 -vcodec png <output_file>
OV5640で取り込んだ画像を変換したものを図27に示します。
図27: B-U585I-IOT02Aディスカバリボード上のMB1379カメラモジュールで取り込んだ画像例 -
ffmpeg の代わりに、GNU Image Manipulation Program(GIMP)を使って、エクスポートされた RGB565 の生画像を表示したり操作したりすることも可能です。 拡張子.dataで画像を保存し(上の図25参照)、GIMPで開くだけです。図28に示すようなダイアログボックスが表示されます。画像の設定を図のように変更し、Openをクリックします。