温湿度管理システムを作成してみた¶
ESP-NOW通信を使用することで、
- WIFIが使用できない屋外でSIMカードなども使用せずに通信できること
- 省電力で駆動するため、電池駆動をすることができること
がメリットとして挙げられます。
今回は以下の図のようなシステムを作成していきたいと思います。
各ESP32デバイス(温度データを送信する子機)からESP32デバイス(温度データを受信する親機)にESP-NOW通信(Wi-Fiネットワークを使用せずに、デバイス間で直接データを送受信する通信)を使用してデータを送ります。
ESP32によるESP-NOW通信でのデータ送受信を行うメリットは、
- ESP32はDeepSleepモードを活用することで、長期間の電池駆動が可能であること。
これにより、農地に設置したセンサーやデバイスが頻繁なバッテリー交換を必要とせず、メンテナンスが容易になります。
- MACアドレスを使って直接通信することができ、Wi-Fiネットワークを介さないため、低遅延でのデータ送受信が可能であること
が挙げられます。
ESP-NOW¶
MACアドレスの確認
#include "WiFi.h"
void setup() {
Serial.begin(115200);
Serial.print("WiFi MAC Address:");
Serial.println(WiFi.macAddress());
}
void loop() {
Serial.print("WiFi MAC Address:");
Serial.println(WiFi.macAddress());
delay(5000);
}
ESP-NOW 受信プログラム
#include <esp_now.h>
#include <WiFi.h>
float temperature;
// データ受信時に実行されるコールバック関数
void OnDataRecv(const uint8_t *mac, const uint8_t *incomingData, int len) {
memcpy(&temperature, incomingData, sizeof(temperature));
Serial.print("Received Temperature: ");
Serial.println(temperature);
}
void setup() {
// シリアルモニタを初期化、通信速度115200bps
Serial.begin(115200);
WiFi.mode(WIFI_STA); // デバイスをWi-Fiステーションモードに設定
// ESP-NOWの初期化
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
// データ受信時のコールバック関数を登録
esp_now_register_recv_cb(OnDataRecv);
}
void loop() {
// メインループでは特に処理を行わない
}
ESP-NOW 送信プログラム
#include <esp_now.h>
#include <WiFi.h>
#include <Wire.h>
#include "Adafruit_SHT31.h"
// SHT31センサーのインスタンスを作成
Adafruit_SHT31 sht31 = Adafruit_SHT31();
// 送信先のMACアドレス(こちらに取得したMACアドレスを入力してください)
uint8_t broadcastAddress[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
// ピア情報を保持する構造体
esp_now_peer_info_t peerInfo;
// 送信するデータを保持する構造体
struct DataPacket {
int area_id;
float temperature;
};
// 送信するデータ
DataPacket dataToSend;
// データ送信後に実行されるコールバック関数
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print("\r\nLast Packet Send Status:\t");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}
void setup() {
// シリアルモニタを初期化、通信速度115200bps
Serial.begin(115200);
// SHT31センサーを初期化
if (!sht31.begin(0x45)) {
Serial.println("Couldn't find SHT31");
while (1) delay(1);
}
// デバイスをWi-Fiステーションモードに設定
WiFi.mode(WIFI_STA);
// ESP-NOWの初期化
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
// データ送信後のコールバック関数を登録
esp_now_register_send_cb(OnDataSent);
// ピア情報を設定
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
// ピアを追加
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add peer");
return;
}
// area_idを設定
dataToSend.area_id = 1;
}
void loop() {
// SHT31センサーから温度を取得
dataToSend.temperature = sht31.readTemperature();
if (!isnan(dataToSend.temperature)) { // 温度が正常に読み取れた場合
Serial.print("Temperature: ");
Serial.println(dataToSend.temperature);
// 温度データとエリアIDを送信
esp_now_send(broadcastAddress, (uint8_t *)&dataToSend, sizeof(dataToSend));
} else {
Serial.println("Failed to read temperature");
}
delay(5000); // 1秒間隔でデータを送信
}
参考資料¶
RaspberryとArduinoをシリアル通信する 【シリアル通信〜基礎編】USBを繋いでArduino Unoとラズパイ間で簡単なシリアル通信を行ってみる