ArduinoとSTM32マイコンをつないでマイコンシステム開発をしてみる その20 ~検証実験⑫~
マイコンシステム開発の要件定義から総合テストまでの工程をたどってみます。
題材としては、空調管理システムにします。
機材はいま手元にあるArduino1台とSTM32マイコン1台を使います。
実装に入る前に検証実験をおこないます
以下の3点をおこないます。
① STM32で計測した気温データをSPI通信でArduinoに送信。
1)STM32単体で、計測した気温データをUSB経由で端末エミュレータに出力。(完了)
2)SPI通信でSTM32からArduinoにテストデータを送信。(完了)
② Arduinoは気温データを受信し、LCDに表示。
1)LCDに文字を出力するテスト(完了)
2)受信した気温データをLCDに表示(完了)
③ ArduinoからSTM32に制御データを送信し、LEDを点灯。(今回行います)
前回は
Arduinoで受信した気温データをLCDに出力するテストをおこないました
今回、
ArduinoからSTM32に制御データを送信し、LEDを点灯します。
1.プログラムを作成します
① 制御データを送信するArduino側のプログラム
受信したデータが25未満であれば0を送信、25以上であれば1を送信します。
#include <SPI.h>
#include <LiquidCrystal.h>
volatile byte receivedData;
volatile bool dataAvailable = false;
// LiquidCrystalオブジェクトの作成(ピン指定)
LiquidCrystal lcd(8, 9, 7, 6, 5, 4);
void setup() {
Serial.begin(9600);
Serial.println("SPI Slave Initialized");
// SPIスレーブの初期化
pinMode(MISO, OUTPUT);
SPCR |= _BV(SPE); // SPI Enable
SPCR &= ~_BV(MSTR); // スレーブモード
// 割り込みでデータ受信
SPCR |= _BV(SPIE);
lcd.begin(16, 2); // LCDを16x2モードで初期化
}
ISR(SPI_STC_vect) {
receivedData = SPDR; // 受信データを取得
dataAvailable = true;
}
void loop() {
if (dataAvailable) {
dataAvailable = false;
Serial.print("Received Data: ");
Serial.println(receivedData);
lcd.clear();
lcd.print(receivedData); // LCDに受信データを表示
// データ判定と送信
byte sendData = (receivedData < 25) ? 0 : 1;
SPDR = sendData; // データ送信
// 送信成功メッセージを表示
Serial.print("Send OK ");
Serial.println(sendData);
}
}
実行すると、うまく動作しました
受信データが19のときは、”Send OK 0" と表示されます。
温度センサを指で触って温度を上げると、
受信データが25以上のときは、”Send OK 1" と表示されました。
② 制御データを受信するSTM32側のプログラム
受信データが1ならLEDを点灯、0ならLEDを消灯させることにします。
while (1)
{
/* 温度測定モードを設定 */
i2cbuf[0] = 0x11; // CTRL_REG2 レジスタアドレス
HAL_I2C_Mem_Write(&hi2c1, I2C_ADDR_W, 0x11, I2C_MEMADD_SIZE_8BIT, i2cbuf, 1, 1000);
/* 測定が完了するまで繰返し */
while (1) {
i2cbuf[0] = 0;
HAL_I2C_Mem_Read(&hi2c1, I2C_ADDR_R, 0x27, I2C_MEMADD_SIZE_8BIT, i2cbuf, 1, 1000);
if ((i2cbuf[0] & 0x03) == 0x03) {
break; // 測定完了
}
HAL_Delay(10);
}
/* 温度データを取得 */
HAL_I2C_Mem_Read(&hi2c1, I2C_ADDR_R, 0x2B, I2C_MEMADD_SIZE_8BIT, i2cbuf, 2, 1000);
int16_t raw_temp = (int16_t)((i2cbuf[1] << 8) | i2cbuf[0]); // 2の補数形式でデータを取得
/* 温度を°Cに変換 */
float temperature_celsius = raw_temp / 100.0f;
/* 整数部だけを送信 */
data = (uint8_t)temperature_celsius;
/* SSピンをLOWに設定して通信を開始 */
HAL_GPIO_WritePin(SS_PORT, SS_PIN, GPIO_PIN_RESET);
/* SPIデータ送信 */
if (HAL_SPI_Transmit(&hspi1, &data, 1, 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));
}
/* --- スレーブからデータを受信 --- */
uint8_t receivedData = 0;
/* SSピンをLOWに設定して通信を開始 */
HAL_GPIO_WritePin(SS_PORT, SS_PIN, GPIO_PIN_RESET);
/* SPIデータ受信 */
if (HAL_SPI_Receive(&hspi1, &receivedData, 1, HAL_MAX_DELAY) == HAL_OK) {
/* 受信データをシリアルモニタに表示 */
snprintf(msgbuf, sizeof(msgbuf), "Received Data: %d\r\n", receivedData);
CDC_Transmit_FS((uint8_t *)msgbuf, strlen(msgbuf));
/* 受信データに応じてPA15のLEDを制御 */
if (receivedData == 0) {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET); // 消灯
} else if (receivedData == 1) {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET); // 点灯
}
} else {
/* エラー処理 */
Error_Handler();
}
/* SSピンをHIGHに設定して通信を終了 */
HAL_GPIO_WritePin(SS_PORT, SS_PIN, GPIO_PIN_SET);
/* 1秒待機 */
HAL_Delay(1000);
}
実行すると、
受信データが正しくありません。
Arduionoから送られてきているのは、STM32が送信したデータそのもののようです。
Arduino側のシリアルモニタの出力を見てみると、
制御データ0を送信した後に、そのデータを受信しているような挙動です。
LCDの出力を見ると、0が表示され続けてます。