Makato-kanのアイコン画像
Makato-kan 2024年10月19日作成 (2024年10月24日更新)
製作品 製作品 閲覧数 24
Makato-kan 2024年10月19日作成 (2024年10月24日更新) 製作品 製作品 閲覧数 24

屋外で使う 汎用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のアイコン画像
屋外で温度湿度を測定し記録するので、壊れやすいと思い大量にDHT11とESP-WROOM-02を購入したのですが思いのほか壊れなかったので、何にでもDHT11をくっつけています。
ログインしてコメントを投稿する