編集履歴一覧に戻る
Makato-kanのアイコン画像

Makato-kan が 2024年10月24日11時27分07秒 に編集

コメント無し

本文の変更

##### ラズベリーパイとESP32C3で作る 汎用IOTステーションです センサーデータをASCIIコード CSV形式にして、時刻情報をラズパイで受信したときに付与する事でセンサー側の時計機能を不要にしました。 センサーは送信時ASCIIコードになるようにします。 センサーとの通信はESP-NOWを使います。(最大送信量は250バイトですが) ##### 概念図 ![](https://camo.elchika.com/fffef898706e126359370e9d186d73c717991353/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f66373831653764372d303336352d343131662d613663362d3663623238333931346464342f36313432393439342d396361662d343936652d386236322d366234313762366438613262/)  ##### 部品例  ラズベリーパイZERO-W  ESP32C3(通信距離を伸ばしたいなら外部アンテナ付がよいかも)  電源として 太陽電池パネル 12Vバッテリー チャージコントローラー 12V-5VDC-DCコンバータ  インターネット環境無い場所で使うなら ラズベリーパイ用RTC ##### データフォーマット  センサーデータは先頭にIDをつけて、プログラムで仕分けできるようにします ```arduino: 103, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0 ``` 上記のデータを取得したらシェルスクリプトで時刻を付与すると下記のようになります。 ```arduino: 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 & ``` ```arduino: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で外部に送信します ```arduino: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をインストールして使いました。 ```arduino: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() { } ``` ##### 箱に入れる前の状態写真 ![キャプションを入力できます](https://camo.elchika.com/c49b4bb122cd7b05f2af97c831403eef74e10738/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f66373831653764372d303336352d343131662d613663362d3663623238333931346464342f32633435663730342d343736352d343538332d623865372d366134363330663439663932/) ##### UART接続でデータを送った場合 UART接続でデータを送った場合ラズパイはデータ取りこぼしをする事がわかりました。 これはESP32側は送りっぱなしでラズパイ側は何も制御していないのが原因で解消するにはCTS/RTSやxon/xoffなども実装する必要ある事がわかりUSB接続でデータをもらうようにしました。

+

##### MQTTについて  このラズベリーパイではMQTTのパブリッシャー機能を使ってデータを転送しています、簡単な説明ですが [ラズベリーパイにMQTTブローカーの設定して pub/subを試してみる。](https://elchika.com/article/ea67de45-ab62-4515-8a63-e9f83f056eed/)の記事を書きましたのでそちらも見ていただけると助かります。 ESP-NOWを使ってセンサーからデータを送る方につきましては現在作成中でした。