屋外で使う 汎用IOTステーション
ラズベリーパイとESP32C3で作る 汎用IOTステーションです
センサーデータをASCIIコード CSV形式にして、時刻情報をラズパイで受信したときに付与する事でセンサー側の時計機能を不要にしました。
センサーは送信時ASCIIコードになるようにします。
センサーとの通信はESP-NOWを使います。(最大送信量は250バイトですが)
概念図
部品例
ラズベリーパイZERO-W
ESP32C3(通信距離を伸ばしたいなら外部アンテナ付がよいかも)
電源として 太陽電池パネル 12Vバッテリー チャージコントローラー 12V-5VDC-DCコンバータ
インターネット環境無い場所で使うなら ラズベリーパイ用RTC
データフォーマット
センサーデータは先頭にIDをつけて、プログラムで仕分けできるようにします
103, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0
上記のデータを取得したらシェルスクリプトで時刻を付与すると下記のようになります。
2024,10,12,"07:32",103, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0
ラズベリーパイのセットアップ
ラズパイOSはbookwormのlite版を使います。
シリアル接続でメンテナンスをしたいので、UART経由でログインできるよう設定します。
SDカード破損を考慮しデータを受信した都度外部に送信するのにMQTTを使用します。
ESP32C3のセットアップ
ESP-32C3はセンサー子機に対する親機となりラズパイとはUSB接続します。
通信はESP-NOWを使い、センサーデータを受け取ります。
データはASCIIコードで受け取るようにしてprintでラズパイに送ります。
ラズベリーパイで使うプログラム
2つのプログラムを使います、保存先はホームディレクトリ直下に置き、実行形式にしておきます。
プログラム1 ラズパイ起動時にUSBにESP32C3がついているのを確認しついていれば、
ESP32からのデータを読み込むプログラム()sample.shを起動します
設定方法:/etc/rc.localの最終行 exit 0 より上の行に以下の内容を追加します。
sudo -u pi /home/pi/check_USB .sh &
check_USB.sh
#!/bin/bash
check_connection(){
if [ -e /dev/ttyACM0 ]; then
return 0
else
return 1
fi
}
while true; do
if check_connection; then
echo "found USB"
/home/ppi/html/Commands/sample.sh &
break
else
sleep 2
fi
done
このプログラムでやっている事
シリアル接続のポートがあるかどうか確認してあればプログラム2を起動します。
プログラム2 ESP32からおくられてきたデータに時刻を付与して保存し、MQTTで外部に送信します
sample.sh
#!/bin/bash
TTY="/dev/ttyACM0" #ラズパイUSB用
MOSQ_C="mosquitto_pub -h 受信ホスト名.local -u ログイン名 -P パスワード -t トピック名n -l"
MOSQ_C20="mosquitto_pub -h 受信ホスト名.local -u ログイン名 -P パスワード -t トピック名20 -l"
MOSQ_C10="mosquitto_pub -h 受信ホスト名.local -u ログイン名 -P パスワード -t トピック名10 -l"
while true; do
read -r ttyline < "$TTY"
if [[ "$ttyline" == 20* ]]; then
TIMESTAMP=$(date '+%Y,%m,%d,"%H:%M",')
echo "${TIMESTAMP}${ttyline}" >>/home/pi/sensor-log/sensor-20-log.txt
echo "$ttyline" |eval $MOSQ_C20
elif [[ "$ttyline" == 10* ]]; then
TIMESTAMP=$(date '+%Y,%m,%d,"%H:%M",')
echo "${TIMESTAMP}${ttyline}" >>/home/pi/sensor-log/sensor-10-log.txt
echo "$ttyline" |eval $MOSQ_C10
else [[ "$ttyline" == * ]];
TIMESTAMP=$(date '+%Y,%m,%d,"%H:%M",')
echo "${TIMESTAMP}${ttyline}" >>/home/pi/sensor-log/sensor-n-log.txt
echo "$ttyline" |eval $MOSQ_C
fi
done
RTCのセットアップ
RTCはラズベリーパイ用でセットアップ方法がついてくるものを買うと便利です
ESP32C3のサンプルプログラム
ESP32C3にはESP-NOWで受信したデータをシリアルプリントするだけのプログラムを入れます
これは"ArduinoIDE"で作成しました。
Arduino ESP32-IDEの3.0を使うとプログラムはコンパイルエラー出るようになったので,ボードマネージャーでESP32 by Espressif Systemsの2.0.17をインストールして使いました。
ESP32C3
#include <esp_now.h>
#include <WiFi.h>
#define MEASUREMENT_TIMEINTERVAL 180
esp_now_peer_info_t slave;
typedef struct struct_message {
int id; //sender ID
float b; //
float c; //
float d; //
float e; //
float f; //
float g; //
float h; //
int z; //
} struct_message;
// Create a struct_message called myData
struct_message myData;
// Create a structure to hold the readings from each board
struct_message board1;
struct_message board2;
struct_message board3;
struct_message board4;
struct_message board5;
struct_message board6;
// Create an array with all the structures
struct_message boardsStruct[6] = {board1, board2, board3, board4, board5, board6};
// callback function that will be executed when data is received
void OnDataRecv(const uint8_t * mac_addr, const uint8_t *incomingData, int len) {
memcpy(&myData, incomingData, sizeof(myData));
boardsStruct[myData.id-1].id = myData.id;
boardsStruct[myData.id-1].b = myData.b;
boardsStruct[myData.id-1].c = myData.c;
boardsStruct[myData.id-1].d = myData.d;
boardsStruct[myData.id-1].e = myData.e;
boardsStruct[myData.id-1].f = myData.f;
boardsStruct[myData.id-1].g = myData.g;
boardsStruct[myData.id-1].h = myData.h;
boardsStruct[myData.id-1].z = myData.z;
//シリアルでデータを送信したら終わり
String data = ""+String(myData.id)+", "+String(myData.b)+", "+String(myData.c)+", "+String(myData.d)+", "+String(myData.e)+", "+String(myData.f)+", "+String(myData.g)+", "+String(myData.h)+", "+String(myData.z);
Serial.println(data);
}
void setup() {
//Initialize Serial Monitor
Serial.begin(9600);
//Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
//Init ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
// Once ESPNow is successfully Init, we will register for recv CB to
// get recv packer info
esp_now_register_recv_cb(OnDataRecv);
}
void loop() {
}
箱に入れる前の状態写真
UART接続でデータを送った場合
UART接続でデータを送った場合ラズパイはデータ取りこぼしをする事がわかりました。
これはESP32側は送りっぱなしでラズパイ側は何も制御していないのが原因で解消するにはCTS/RTSやxon/xoffなども実装する必要ある事がわかりUSB接続でデータをもらうようにしました。
MQTTについて
このラズベリーパイではMQTTのパブリッシャー機能を使ってデータを転送しています、簡単な説明ですが
ラズベリーパイにMQTTブローカーの設定して pub/subを試してみる。の記事を書きましたのでそちらも見ていただけると助かります。
ESP-NOWを使ってセンサーからデータを送る方につきましては現在作成中でした。
投稿者の人気記事
-
Makato-kan
さんが
2024/10/19
に
編集
をしました。
(メッセージ: 初版)
-
Makato-kan
さんが
2024/10/22
に
編集
をしました。
(メッセージ: 最後にを変更)
-
Makato-kan
さんが
2024/10/24
に
編集
をしました。
ログインしてコメントを投稿する