tokagegeg が 2024年01月27日11時04分10秒 に編集
コメント無し
本文の変更
# 概要 生活をする上で身の回りには様々な危険があります。例えば、交通事故や害獣による人的被害、熱中症などがあります。そこで、SPRESENSEに様々なセンサを搭載して身の回りの危険を検知し、回転灯の点灯やLoRa通信を用いて危険を知らせるデバイスを製作しました。  # 構成 製作した回転灯、受信端末の構成は以下のとおりになります。 ## 回転灯 SPRESENSEに搭載したセンサ、通信モジュールを以下の構成図に示します。回転灯はNPNトランジスタによるスイッチング回路を介してSPRESENSEに接続しています。   ## 受信端末   ## 部品 「SPRESENSEメインボード」、「SPRESENSE HDRカメラボード」、「LoRa Add-onボード」はモニター提供して頂きました。 | 名称 | 型番 | 概要 | |:---:|:---:|:---:| | 回転灯 | | Amazonで購入 | | [SPRESENSEメインボード](https://www.switch-science.com/products/3900) | CXD5602PWBMAIN1 | メインマイコン | | [SPRESENSE拡張ボード](https://www.switch-science.com/products/3901) | CXD5602PWBEXT1 | SDカードスロット、GPIOピンを利用 | | [SPRESENSE HDRカメラボード](https://www.switch-science.com/products/8080) | CXD5602PWBCAM2W | 害獣の検出に利用 | | [LoRa Add-onボード](https://www.switch-science.com/products/8958) | DTH-SSLR | 回転灯のデータ送受信に利用 | | 加速度センサ | MPU6050 | 衝撃検知に利用 | | 大気圧温度センサ |BMP180 | 大気圧、気温取得に利用| | [CO2センサ](https://www.switch-science.com/products/7168)| SCD4x | 大気中CO2濃度測定に使用 | | SDカード 4GB| | 学習済データの保存に利用| # 機能 SPRESENSEやセンサ、通信モジュールを利用して以下の機能を実装しました。 ## 回転灯の制御 購入した回転灯は、主にDCモータ1個とLED1個で構成されていました。SPRESENSE単体では回転灯を動作させるために必要な電流を出力する事ができないため、以下のスイッチング回路を介して回転灯と接続することで制御しています。  以下のプログラムにより、3秒おきに点灯と消灯を繰り返すことを確認できました。 ```arduino:回転灯チカ void setup() { pinMode(2, OUTPUT); } void loop() { digitalWrite(2, HIGH); delay(3000); digitalWrite(2, LOW); delay(3000); } ```
@[twitter](https://x.com/tokagegeg/status/1750923507679322449)
@[twitter](https://twitter.com/tokagegeg/status/1750923507679322449)
 ## 各種センサからの値の取得 デバイスに搭載したセンサを利用して身の回りの危険を検知する機能の実装を行いました。 ### 加速度センサ(MPU6050)を利用した衝撃の検出 加速度センサを利用して衝撃を検知し、閾値を超えた場合回転灯が点灯するプログラムです。プログラムには、「[MPU6050](https://github.com/electroniccats/mpu6050)」ライブラリを使用しました。回転灯を車に搭載することで、事故の検出や盗難の検出に利用できると思います。 ```arduino:衝撃の検出 #include <Wire.h> #include <MPU6050.h> MPU6050 mpu; void setup() { Serial.begin(115200); Wire.begin(); mpu.initialize(); pinMode(2, OUTPUT); digitalWrite(2, LOW); if (!mpu.testConnection()) { Serial.println("MPU6050 connection failed"); while (1) ; } else { Serial.println("MPU6050 connection successful"); } } void loop() { if (detectImpact(1.1)) { // 閾値を1.2gとして衝撃を感知 Serial.println("Impact detected!"); digitalWrite(2, HIGH); delay(3000); digitalWrite(2, LOW); } delay(100); } bool detectImpact(double threshold) { int16_t ax, ay, az; mpu.getAcceleration(&ax, &ay, &az); double ax_g = ax / 16384.0; // 加速度センサの値をg単位に変換 double ay_g = ay / 16384.0; double az_g = az / 16384.0; double magnitude = sqrt(ax_g * ax_g + ay_g * ay_g + az_g * az_g); // 加速度の大きさを計算 return magnitude > threshold; // 閾値を超えたらtrueを返す } ``` ### 大気圧温度センサ、CO2センサを利用した悪環境の検出 大気圧温度センサとCO2センサを利用し、CO2濃度上昇による人体への悪影響や高温多湿による熱中症の危険を警告するプログラムです。「[Adafruit_BMP085](https://github.com/adafruit/Adafruit-BMP085-Library)」、「[SparkFun_SCD4x_Arduino_Library](https://github.com/sparkfun/SparkFun_SCD4x_Arduino_Library)」ライブラリを使用しました。 ```arduino:環境センサを利用した警告 #include <Wire.h> #include <Adafruit_BMP085.h> Adafruit_BMP085 bmp; #include "SparkFun_SCD4x_Arduino_Library.h" SCD4x scd4x; void lchika() { digitalWrite(2, HIGH); delay(3000); digitalWrite(2, LOW); } void setup() { Serial.begin(115200); Wire.begin(); pinMode(2, OUTPUT); digitalWrite(2, LOW); if (!bmp.begin()) { Serial.println("Could not find a valid BMP085 sensor, check wiring!"); while (1) {} } if (scd4x.begin() == false) { Serial.println(F("Sensor not detected. Please check wiring. Freezing...")); while (1) ; } } void loop() { if (scd4x.readMeasurement()) { // CO2濃度2000ppm以上で点灯 if (scd4x.getCO2() > 2000) { lchika(); } // WBGT値早見表より、熱中症厳重警戒以上で点灯 float tmp = bmp.readTemperature(); if (tmp > 37) { lchika(); } else if (20 + (38 - tmp) * 5 < scd4x.getHumidity()) { lchika(); } } delay(500); } ``` ## HDRカメラボードを使用した害獣の検出 最近、熊や猪などによる人的被害のニュースをよく目にします。そこで、SPRESENSEとHDRカメラボードを利用して熊や猪などの害獣を検出し警告するプログラムを作成しました。実装にあたり以下のサイトを参考にしました。 [SPRESENSE で小型AIカメラを作ってみた! - 息子と一緒に Makers](https://makers-with-myson.blog.ss-blog.jp/2020-02-18) [Spresenseを活用したAI駐車場監視システム - Fooping](https://elchika.com/article/d9158fa1-8d54-4bfe-b589-b75af7f266e9/) ニューロンモデルの作成には、ソニー独自のAIツールである「[Neural Network Console](https://dl.sony.com/ja/)」を利用しました。GUIの操作で完結するので機械学習初学者でもモデルの作成を行えました。    参考サイトのプログラムを参考に、熊や猪を検出し警告するプログラムを作成しました。熊と猪の検出はできたものの、熊を猪と判定したり猪を熊と判定するなど誤検知する問題が確認できました。今後、判定精度を向上のため、学習データ数を増やしたりパラメータの調整を行いたいです。  害獣検出するプログラムの実装の際に以下の2点に躓きました。 - 「Neural Network Console」を利用して、モデルを評価する際に混同行列が表示されない - [NNC Windows版で混同行列が表示されない件について](https://groups.google.com/g/neural_network_console_users_jp/c/NHIru9c34qw)を参考に、ネットワークの出力クラス数が正しく設定することで解決しました。 - clipAndResizeImageByHW()を実行の際に、「Invalid parameter is detected.」が発生してしまう - convertPixFormat()によりピクセルフォーマット変換をした画像データのりサイズはエラーを吐く?ので、convertPixFormat()をリサイズを行ったデータに対して実行することで解決しました。 ## LoRa Add-on ボードを利用した通信 回転灯で取得した各種センサのデータを、別端末に送信するためLoRa Add-on ボードを利用しました。[製品ページ](https://dragon-torch.tech/cat-components/extension-boards/dth-sslr/)で公開されているプログラムを参考に、環境センサ(大気圧温度センサ、CO2センサ)で取得したデータを受信端末に送信しました。送信の際には、「[Arduino_JSON](https://github.com/arduino-libraries/Arduino_JSON)」ライブラリを利用しJSONフォーマットのデータ送信する仕様にしました。  ```arduino:LoRA_Add-onボードを用いたデータの送信(抜粋) JSONVar myObject; myObject["CO2"] = (int)scd4x.getCO2(); myObject["Temperature"] = scd4x.getTemperature(); myObject["Humidity"] = scd4x.getHumidity(); myObject["Temperature_"] = bmp.readTemperature(); myObject["Pressure_"] = bmp.readPressure(); String jsonString = JSON.stringify(myObject); if (lora.SendFrame(config, (uint8_t *)jsonString.c_str(), strlen(jsonString.c_str())) == 0) { SerialMon.printf("send succeeded.\n"); SerialMon.printf("\n"); } else { SerialMon.printf("send failed.\n"); SerialMon.printf("\n"); } ``` 受信端末で受信したデータを、シリアル通信でPCに転送することでグラフとして描画しました。プログラムはPython言語を用いて作成しました。  ```python:グラフ描画プログラム import serial import json import matplotlib.pyplot as plt # シリアルポートの設定 serial_port = 'COM7' baud_rate = 115200 # シリアルポートを開く ser = serial.Serial(serial_port, baud_rate) # データを格納するためのリスト temperature_data = [] humidity_data = [] # 初期グラフ設定 fig, ax1 = plt.subplots() # 温度用の軸設定(左側) ax1.set_xlabel('Time') ax1.set_ylabel('Temperature', color='tab:red') ax1.tick_params(axis='y', labelcolor='tab:red') # 湿度用の軸設定(右側) ax2 = ax1.twinx() ax2.set_ylabel('CO2', color='tab:blue') ax2.tick_params(axis='y', labelcolor='tab:blue') try: while True: # シリアルポートから行を読み取る line = ser.readline() if line: # 行が空でないことを確認 data = json.loads(line) # 温度と湿度をリストに追加 temperature_data.append(data['Temperature']) humidity_data.append(data['CO2']) # データの可視化 ax1.plot(temperature_data, label='Temperature', color='tab:red') ax2.plot(humidity_data, label='CO2', color='tab:blue') # 軸の範囲を固定 ax1.set_ylim(0, 40) # 温度の範囲 ax2.set_ylim(0, 2000) # 湿度の範囲 # 凡例の設定 lines, labels = ax1.get_legend_handles_labels() lines2, labels2 = ax2.get_legend_handles_labels() ax2.legend(lines + lines2, labels + labels2, loc='upper left') plt.pause(0.1) # グラフを更新 ax1.lines = [] ax2.lines = [] except KeyboardInterrupt: print("Program terminated") finally: ser.close() ``` 環境センサ(大気圧温度センサ、CO2センサ)で取得したデータの他にも、HDRカメラボードを使用して検出した害獣の情報を送信するなど様々な用途に使用できることが確認できました。 # おわりに SPRESENSEに様々なセンサを搭載して身の回りの危険を検知し、回転灯の点灯やLoRa通信を用いて危険を知らせるデバイスを製作しました。。SPRESENSEではArduino言語を使用してプログラムを作成できるので、豊富な既存ライブラリを利用して開発することが出来ます。加えて、従来のArduino言語でプログラミングできるマイコンでは難しい、機械学習を用いた機能の実装を簡単に行えるので強力なデバイスだと思いました。他にもマルチコアなど様々な特徴があるので今後使用したいです。 期末課題やテストが迫って来ているので実装は一旦お休みしますが、今後は以下のイメージのように見た目を整えて行きたいと考えています。電子工作系のコンテストへの参加は久々でしたが、楽しんで取り組むことができました。また、記事投稿を行うのはこの投稿が初めてなので、これを機にアウトプットの習慣をつけていきたいと思います。 