ArduinoとSTM32マイコンをつないでマイコンシステム開発をしてみる その24 ~実装③~
マイコンシステム開発の要件定義から総合テストまでの工程をたどってみます。
題材としては、空調管理システムにします。
機材はいま手元にあるArduino1台とSTM32マイコン1台を使います。
実装の続きです
システム構成
下記の3つのシステムから構成されています
・気温データ送信ユニット (実装完了)
・アクチュエータ (実装完了)
・空調管理システム
1. read_temperature()関数 (トラブルシューティング中)
前回は空調管理システムの実装へ進みましたが、read_temperature()関数の単体テストでトラブル発生です。
今回はトラブルシューティングをおこないます
不具合の事象:
気温データ送信ユニットから送信された気温データを受信するread_temperature()関数において、送信データと異なる値を受信してしまう。
原因調査
1. SPI通信速度の見直し
マスター側のクロック周波数を低くしました。
現在は分周比が16ですので、48 ÷ 16 で 3MHzのクロック周波数です。
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
さらに低くします。
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
しかし、状況は変わらず、不具合は解消されません
2. データ整合性の強化
受信したデータが不完全な場合に備え、データ整合性チェックするコードを追加しました。たとえば、送信データの先頭でマジックバイト( 0xff)を格納し、受信データがこのマジックバイトで始まるかを確認する方法です。
STM32(マスター)側のコードの修正:
送信データ配列のサイズを2から3に変更し、
data[0] には 0xff を格納しておく。
data[1] は符号と整数部、
data[2] は小数部を格納して、data[0]~data[2] の3バイトを送信。
//uint8_t data; // 送信データ
unsigned char data[3] = {0xff,0,0};
void makeSendData(float temperature_celsius){
/* データ配列に変換 */
int16_t temp_integer = (int16_t)temperature_celsius; // 整数部
unsigned char temp_fraction = (unsigned char)((fabs(temperature_celsius - temp_integer)) * 10 + 0.5f); // 小数部(絶対値で計算し四捨五入)
/* 符号ビットと整数部を設定 */
if (temp_integer < 0) {
data[1] = 0x80 | ((-temp_integer) & 0x7F); // 符号ビット(1)と絶対値
} else {
data[1] = (temp_integer & 0x7F); // 符号ビット(0)と整数部
}
/* 小数部を設定 */
data[2] = (temp_fraction & 0x0F); // 小数部を4ビットで格納
}
/* SPIデータ送信 */
if (HAL_SPI_Transmit(&hspi1, data, 3, HAL_MAX_DELAY) != HAL_OK) {
/* エラー処理 */
Error_Handler();
}else{
snprintf(msgbuf, sizeof(msgbuf), "temperature=%.1f°C\r\n", temperature_celsius);
CDC_Transmit_FS((uint8_t *)msgbuf, strlen(msgbuf));
snprintf(msgbuf, sizeof(msgbuf), "data[0]=0x%02x data[1]=0x%02x data[2]=0x%02x\r\n", data[0],data[1],data[2]);
CDC_Transmit_FS((uint8_t *)msgbuf, strlen(msgbuf));
}
Arduino(スレーブ)側のコードの修正:
受信したデータが 0xff なら読み飛ばすコードを追記しました。
ISR(SPI_STC_vect) {
receivedData[receivedIndex++] = SPDR;
if (receivedData[0] != 0xff) { // マジックバイト確認
receivedIndex = 0; // データ不整合ならリセット
return;
}
if (receivedIndex >= 3) {
receivedIndex = 0;
dataAvailable = true;
}
}
単体テストをおこないます
マスター側は、正常に data[0] ~ data[2] のデータを送信できてます。
受信側も正常に読み込みました!