この一連の記事ではスマート卓上ファンを作ってみます。このファンにはSTマイクロエレクトロニクスのToF(Time-of-Flight)測距センサを使っています。一部のToF測距センサはst.comで提供されるスマート人感検出(以下SPD : Smart Presence Detection)を使うことで高度な人感センサとして動作します。このSPDの結果を使い、羽の回転や左右の首振りを制御します。
前の記事へのリンク
前回までの記事ではToFとSPDの紹介から始まり、機構・モータ制御の考察、STM32H533のプロジェクトの作成を進めてきました。この記事ではSPDライブラリ内にあるSTM32F401のプロジェクトをSTM32H533のプロジェクトに移植していきます!がんばっていきましょう!
4. SPDをNUCLEO-H533REへ移植する
次はSPDをNUCLEO-H533REに移植していきます。STSW-IMG048がSPDのソフトウェアライブラリのパッケージとなっており、ドライバやライブラリをはじめ、サンプルコードとしてSTM32のプロジェクトもありますが、NUCLEO-F401RE用になっています。ちまたで人気のSTM32H5シリーズには対応していません。粛々と移植をしていくしかありません。移植の途中で少し後悔をしたこともありましたので、素直にNUCLEO-F401REを使用しても大丈夫です。その場合は、この章は飛ばしていただけます。では、気を取り直して進めていきます。
4.1 ファイルのコピー
STSW-IMG048の「SmartPresenceDetectionKit_F401_1.0.0」フォルダからファイルをコピーします。Core/Inc,Core/Srcにコピーするファイルは以下のリストを参照してください。「VL53LMZ_ULD_API」フォルダはフォルダごとコピーします。「SPD_lib」フォルダは.aファイル以外をコピーして、.aファイルはMPUに合ったものが必要なので、「SPD_compiled_libraries_1.0.0」フォルダにある「libSPD_m33.a」をコピーします。
「VL53LMZ_ULD_API」フォルダをコピーしたときには注意が必要です。STM32CubeIDEでは新しく出現したフォルダはコンパイルから外されます。フォルダを右クリックしてプロパティを開き、「Exclude resource from build」のチェックを外すのを忘れないようにしましょう。
4.2 ファイルの小修正
前のファイルのコピーで小修正となっているファイルを修正しました。修正は少ないです。
ファイルごとの小修正コード詳細
#include <stdint.h>
#include <string.h>
- #include "stm32f4xx.h"
+ #include "stm32h5xx.h"
#ifdef STM32F401xE
#include "stm32f4xx_hal.h"
#define MCU_NAME "STM32F401xE"
#endif
#ifdef STM32L476xx
#include "stm32l4xx_hal.h"
#define MCU_NAME "STM32L476"
#endif
+ #ifdef STM32H533xx
+ #include "stm32h5xx_hal.h"
+ #define MCU_NAME "STM32H533xx"
+ #endif
#include "platform.h"
+ #include "main.h"
static void _ParseError( const char *fmt, ...){
va_list ap;
va_start(ap,fmt);
SB_vprintf(fmt, ap);
- SB_VDebug(fmt,ap);
+ //SB_VDebug(fmt,ap);
}
/**
* Force TRACE_UART to 0 by default (if not defined in the project)
*/
- #define TRACE_UART 0
+ #define TRACE_UART 1
4.3 main.hの修正
ここも修正はありますが、そこまで多くありません。注意点としては参考にしているNUCLEO-F401RE用のプロジェクトではVL53L8CXが使われていることです。VL53L8CXを使う場合にはそのまま使えますが、VL53L7CXの場合にはコントロールするピンが1つ増えます。
main.hの修正コード詳細
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
/** Timing data
*/
+ typedef struct {
+ float ranging_frequency; // [Hz]
+ int ranging_period; // [msec]
+ int prev_tstp; // [msec]
+ int curr_tstp; // [msec]
+ } APP_time_data;
/* USER CODE END ET */
/* Private defines -----------------------------------------------------------*/
#define SWDIO_Pin GPIO_PIN_13
#define SWDIO_GPIO_Port GPIOA
#define SWCLK_Pin GPIO_PIN_14
#define SWCLK_GPIO_Port GPIOA
#define JTDI_Pin GPIO_PIN_15
#define JTDI_GPIO_Port GPIOA
#define SWO_Pin GPIO_PIN_3
#define SWO_GPIO_Port GPIOB
/* USER CODE BEGIN Private defines */
+ #define SPDKit_ULD_version "1.0.0"
+
+ // L7 - H533 - Main
+ #define INT_C_Pin GPIO_PIN_1 //
+ #define INT_C_GPIO_Port GPIOB //
+ #define INT_C_EXTI_IRQn EXTI1_IRQn // INT (A2 -> B1)
+ #define PWR_EN_C_Pin GPIO_PIN_0 //
+ #define PWR_EN_C_GPIO_Port GPIOB // PWR_EN_Sensor (A3 -> B0)
+ #define I2C_RST_C_Pin GPIO_PIN_3 //
+ #define I2C_RST_C_GPIO_Port GPIOB // I2C_RST only for L7 (D3 -> B3)
+ #define LPn_C_Pin GPIO_PIN_4 //
+ #define LPn_C_GPIO_Port GPIOB // IO_LPn (D5 -> B4)
/* USER CODE END Private defines */
4.4 プロジェクト設定の修正
ここでプロジェクトの設定を先にします。プロジェクトのプロパティを開いて、Paths and Symbolsのところで、以下のようにIncludesでフォルダ、LibrariesでSPD_m33.a、Library PathsでSPD_libを追加します。
ここで一度プロジェクトをBuildしておきます。成功しましたか??
4.5 main.cの修正
最後に一番大きな山であるmain.cに挑みます。NUCLEO-F401RE用のプロジェクトのmain.cからの移植になります。必要な部分だけ移植しようとも考えます。コードをみる限り、綺麗に分離するのは難しそうです。しかたがないので、まるごと移植を試みます。移植の個所は大きく分けて以下の3か所に分かれています。
- 冒頭の宣言部分
- main関数(ループの前、ループの中)
ループの前の初期化部分には元のVL53L8CX使用時のコードにはない、VL53L7CXの電源ONのコードを入れます。 - 独自の関数たちの定義です。
それぞれ順番に説明していきます。
4.5.1 最初の宣言の部分
元のmain.cから新しいmain.cへ冒頭の宣言部分をそれぞれ移植していきます。/* USER CODE BEGIN PM */
の下にマクロをいれて、/* USER CODE BEGIN PV */
にプライベートな変数を書きます。/* USER CODE BEGIN PFP */にプライベートな関数の宣言を書きます。
ちょっと込み入っているので修正コードの詳細は割愛させていただきます。この辺りが元のコードでは分かれていないのが私には気になってしまいます。
4.5.2 main関数
元のmain()関数のメインループwhile(1)の前のにコードを/* USER CODE BEGIN 2 */
から/* USER CODE END 2 */
の間にコピーします。VL53L7CXでは元のソースにはないパワーONのコードが入っているところに注意してください。
main.cのループ前に必要な修正コード詳細
/* USER CODE BEGIN 2 */
int status = 0;
int off = 0;
UartComm_Start(); // restart RX
/* Clean the Serial Terminal */
HAL_Delay(1000);
uart_printf("\x1b[2J");
uart_printf("\x1b[1;1H");
uart_printf("SPD ULD SW Kit version %s\n", SPDKit_ULD_version);
/* Enable Power */
HAL_GPIO_WritePin(PWR_EN_C_GPIO_Port, PWR_EN_C_Pin, GPIO_PIN_RESET);
HAL_Delay(100);
HAL_GPIO_WritePin(PWR_EN_C_GPIO_Port, PWR_EN_C_Pin, GPIO_PIN_SET);
HAL_Delay(100);
/* Initialize VL53LMZ I2C address */
LMZDev.platform.address = 0x52;
/* Initialize sensor */
status = init_vl53lmz_sensor();
if (status != VL53LMZ_STATUS_OK){
uart_printf("init_vl53lmz_sensor failed : %d\n",status);
}
/* Sensor identification */
Params.spdRangingPeriod = LMZDev.module_type == 1 ? SPD_RANGING_PERIOD_L7 : SPD_RANGING_PERIOD_L8;
Params.spdIntegrationTime = LMZDev.module_type == 1 ? SPD_INTEGRATION_TIME_L7 : SPD_INTEGRATION_TIME_L8;
Params.spdAutonomousIntegrationTime = LMZDev.module_type == 1 ? SPD_AUTONOMOUS_INTEGRATION_TIME_L7 : SPD_AUTONOMOUS_INTEGRATION_TIME_L8;
/* Initialize SPD algo */
SPD_Init(1);
// Reset sensor settings in Tracking mode (after SPD init)
SEN_SetParamsForTracking();
/* Initialize SPD algo */
SPD_Init(1);
// Reset sensor settings in Tracking mode (after SPD init)
SEN_SetParamsForTracking();
/* USER CODE END 2 */
ループの中には/* USER CODE BEGIN 3 */
の下に、コードをコピーしていきます。コメントのブロックでいうと、/*UART RX Receiver management*/
、/*START command*/
、/*RANGING Mode*/
、/*STOP command*/
、/*OFF command*/
、/*SET command*/
までになります。
#ifdef VL53LMZ_XTALK_CALIBRATION
以下は使用していないので、コピーしません。
main.cのメインループ内に必要な修正コード詳細
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
/*******************************/
/* UART RX Receiver management */
/*******************************/
if (UartComm_CmdReady) {
SC_HandleCmd(UartComm_RXBuffer);
UartComm_CmdReady = 0;
UartComm_Start(); // restart RX
}
// 以下省略
4.5.3 独自の関数たちの定義
独自関数たちはMX_GPIO_Init
の宣言の後の/* USER CODE BEGIN 4 */
以下にコピーしていきます。
init_vl53lmz_sensor()
、vl53lmz_sci_calculate_required_memory()
、vl53lmz_Configure()
、vl53lmz_spd_set_output_pipe()
、get_ranging_data()
、SPD_Init()
、SEN_update_info()
、SEN_CopyMeasurementData()
、SEN_SetParamsForTracking()
、SEN_SetParamsForAutonomous()
、SPD_ChangeSensorMode()
、HAL_GPIO_EXTI_Falling_Callback()
の関数になります。最後のGPIOの割り込みCallbackも忘れずにコピーします。これのCallbackがないとデータが来たことを検知できず、動きません。
ここまでできたらコンパイルしてみます。エラーが出たらひとつひとつ、つぶしていきましょう!
今回はSTM32F401プロジェクトのコードをSTM32H533に移植していきました。細かいコードが続いて気がめいります。他のSTM32へのSPDの移植でも参考になる情報となっていることを願っています。次回はSPDライブラリの結果でモータを制御していきます。次の記事につづきます!