工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

Arduino×Python×Kerasで実現する高精度雨予報システムの構築

必要な部品と材料

部品数量
小型プラスチックケース(蓋着脱式、ネジ止め推奨)11×7×5cm程度1
単3電池ホルダー(3本用)1
単3ニッケル水素充電池3
6V小型ソーラーパネル1
Arduino Pro Mini 328 - 5V/16MHz1
ダイオード 1N4004(逆流防止用)1
汎用NPNトランジスタ + 1kΩ抵抗(周辺機器電源スイッチ用)1
雨センサー1
HC-12 シリアル通信モジュール1
HC-12 USBシリアルモジュール(基地局側)1
BME280 大気センサー(温湿度・気圧)1
BH1750 照度センサー1
PCB、配線、ハンダ、コネクタ類、接着剤1式
3.3Vレギュレータ1

必要な工具

プロジェクト概要

このプロジェクトの最終目標は、6時間先の雨の有無(Yes/No)を予測することです。既存のチュートリアルで完結したものが見つからなかったため、気象観測装置の自作からデータ収集、蓄積、機械学習によるモデル構築、予測・通知まで全工程をカバーします。

  1. 気象観測装置を自作:ソーラーパネルで完全オフグリッド、極低消費電力(数十μA/h)
  2. 装置をプログラミング:10分ごとにデータ取得・送信
  3. 基地局でデータ収集・蓄積:データベースに保存
  4. ニューラルネットワーク(Keras)で学習:Pandasでデータ前処理後、雨予測モデルを訓練
  5. 予測・通知:今後6時間の雨予測をメール通知

Arduino×Python×Kerasで実現する高精度雨予報システムの構築

Arduino×Python×Kerasで実現する高精度雨予報システムの構築

約600日分の気象データで学習させたモデルでは、パラメータによりますが約80%の精度で6時間先の雨予測が可能です。外部の気象APIや機械学習APIを使わず、実用的なエンドツーエンドのシステムをゼロから構築します。

ステップ1:部品と工具の準備

上記の部品リストと工具を用意します。必要なスキル:半田付け、基本的なArduinoプログラミング、Linuxサービス設定、一般的なプログラミングスキル。

ステップ2:気象観測装置の組み立て

装置は以下の4要素で構成:

  1. ソーラーパネル貼り付け済みケース
  2. 電子部品実装済みPCB
  3. 電池ホルダー(内蔵)
  4. BME280、照度センサー、雨センサー(外部配置)

ケースに4つの穴を開け(ソーラー配線用1つ、センサー用3つ)、パネルを接着して配線を内部に通します。PCBにはArduino、HC-12、3.3Vレギュレータ、ダイオード、トランジスタ、抵抗、コネクタ類を実装します。重要:ArduinoのオンボードLEDは除去するか片足をカットしてください。LEDが大量の電力を消費します。

センサー類を外部からコネクタ接続し、雨センサーは長めの配線で別置きします。設置場所は雨雪を避けられる場所を選び、強力な両面テープ等で固定します。

ステップ3:Arduinoコード

観測装置の役割:10分ごとにセンサーデータを基地局へ送信すること。

プログラムの流れ:

  1. センサー読み取り(湿度、温度、気圧、雨、照度、電圧)
  2. 第2ソフトウェアシリアルでエンコード送信(形式:H1:78|T1:12|PS1:1022|L1:500|R1:0|V1:4010|)
  3. 周辺機器(センサー、通信モジュール)の電源OFF
  4. Arduinoをスリープモード(10分、50μA以下)
  5. 電源ONして1〜4を繰り返し

電圧が4.2V以上なら通常のdelay()でスリープし、過充電を防ぎます。

主要ライブラリ(事前インストール必須)

スケッチ(抜粋)

#include "LowPower.h"
#include "SoftwareSerial.h"
#include "Wire.h"
#include "Adafruit_Sensor.h"
#include "Adafruit_BME280.h"
#include "BH1750.h"

SoftwareSerial serialComm(4, 5); // RX, TX
Adafruit_BME280 bme;
BH1750 lightMeter;
const byte rainPin = A0;
byte sensorsCode = 1;
int voltageDeepSleepThreshold = 4200;
const byte peripherialsPowerPin = 6;

struct sensorData {
  byte humidity;
  int temperature;
  byte rain;
  int pressure;
  long voltage;
  int light;
} sensors;

void setup() {
  Serial.begin(9600);
  serialComm.begin(9600);
  pinMode(peripherialsPowerPin, OUTPUT);
  digitalWrite(peripherialsPowerPin, HIGH);
  delay(500);
  if (!bme.begin()) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1) { customSleep(100); }
  }
  Serial.println("Initialization finished succesfully");
  delay(50);
}

void loop() {
  updateSenzors();
  transmitData();
  customSleep(75);  // 75×8秒 = 600秒 = 10分
}

void updateSenzors() {
  bme.begin();
  lightMeter.begin();
  delay(300);
  sensors.temperature = bme.readTemperature();
  sensors.pressure = bme.readPressure() / 100.0F;
  sensors.humidity = bme.readHumidity();
  sensors.light = lightMeter.readLightLevel();
  sensors.voltage = readVcc();
  sensors.rain = readRain();
}

void transmitData() {
  // シリアルバッファクリア後、各センサー値を送信
  transmitSenzorData("T", sensors.temperature);
  transmitSenzorData("H", sensors.humidity);
  transmitSenzorData("PS", sensors.pressure);
  transmitSenzorData("L", sensors.light);
  transmitSenzorData("V", sensors.voltage);
  transmitSenzorData("R", sensors.rain);
}

void customSleep(long eightSecondCycles) {
  if (sensors.voltage > voltageDeepSleepThreshold) {
    delay(eightSecondCycles * 8000);
    return;
  }
  digitalWrite(peripherialsPowerPin, LOW);
  for (int i = 0; i < eightSecondCycles; i++) {
    LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
  }
  digitalWrite(peripherialsPowerPin, HIGH);
  delay(500);
}

long readVcc() {
  // 内部1.1V基準電圧でVccを測定
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  delay(2);
  ADCSRA |= _BV(ADSC);
  while (bit_is_set(ADCSRA, ADSC));
  uint8_t low = ADCL;
  uint8_t high = ADCH;
  long result = (high << 8) | low;
  result = 1125300L / result;  // 1.1*1023*1000
  return result;  // mV単位
}

完全なコード:GitHubリポジトリ

ステップ4:基地局(サーバー)の準備

Linuxマシン(PC、ラップトップ、開発ボード等)にHC-12 USBモジュールを接続し、常時稼働させて10分ごとのデータを受信します。私はUbuntu 18.04のラップトップを使用しました。

  1. Anacondaインストール:Python環境管理用
  2. MongoDBインストール:時系列データ保存用(スキーマレスで扱いやすい)
  3. プロジェクトクローン:git clone https://github.com/danionescu0/home-automation.git
  4. Conda環境構築:
    cd weather-predict
    conda create --name weather python=3.6.2
    conda activate weather
    pip install -r requirements.txt
    
    主なパッケージ:Keras、Pandas、PyMongo、scikit-learn
  5. 設定ファイル(config.py)調整:MongoDBホスト/ポート、シリアルポート(/dev/ttyUSB0等)

ステップ5:実運用

テストデータのインポート

mongoimport -d weather -c weather_station --file sample_data/weather_station.json

※ 自分のデータと混ぜるとハードウェア差異で精度が下がる可能性があります。

新規データ収集

conda activate weather
python serial_listener.py
# 10分ごとにデータ受信を確認

予測モデルの訓練

python train.py --days_behind 600 --test-file-percent 10 --datapoints-behind 8 --hour-granularity 6

グラフ表示

python graphs --days-behind 10

雨予測とメール通知

python predict.py --datapoints-behind 8 --hour-granularity 6 \
  --from-addr gmail_address --from-password gmail_password --to-addr destination_email

Gmailで「安全性の低いアプリの許可」をONにする必要があります。cronに登録すれば定期実行可能です。

ステップ6:仕組みの解説

1. プロジェクト全体像

観測装置(データ収集・送信のみ)と基地局(蓄積・学習・予測)を分離する利点:

データベースはMongoDBを採用。10分ごとのデータポイントをBSON形式で保存。

2. 機械学習の基本概念

ニューラルネットワークは生物のニューロンを模倣。入力層→隠れ層→出力層で信号を伝播し、バックプロパゲーションで重みを調整して学習します。教師あり学習(入力と正解ラベルのペアで学習)を採用。

3. データ準備(最重要ステップ)

4. Kerasによるニューラルネットワーク構築

from keras.models import Sequential
from keras.layers import Dense, Dropout

input_dim = X.shape[1]
model = Sequential()
model.add(Dense(input_dim//2, activation='relu', input_dim=input_dim))
model.add(Dropout(0.05))
model.add(Dense(input_dim//2, activation='relu'))
model.add(Dropout(0.05))
model.add(Dense(1, activation='sigmoid'))  # 二値分類

model.compile(optimizer='rmsprop', loss='mean_absolute_error', metrics=['accuracy'])
model.fit(X, y, batch_size=1, epochs=50)
model.save('model_file_name')

活性化関数(ReLU, Sigmoid)、損失関数、オプティマイザ、バッチサイズ、エポック数等はデータセットに合わせてチューニングすべきです。--grid-searchオプションで自動探索も可能。

5. 今後の改善点

ステップ7:ボーナス - 公式気象データセットの活用

より信頼性の高いデータで精度向上を図るため、Dark Sky API(現Apple WeatherKit)の過去データを試しました。風速、突風、UV指数、視程等の豊富なパラメータを含みます。

  1. APIキー取得後、python download_import/darksky.py -d 1000でデータ取得(無料枠は1日1000リクエスト)
  2. または私の収集済みデータ(ブカレスト)をインポート:mongoimport -d weather -c darksky --file sample_data/darksky.json
  3. python train.py -d 2000 -p 20 -dp 4 -hg 6 --data-source darkskyで学習

結果:全体精度が約80%→約90%に向上。雨の日の予測精度も改善。データセットの質がモデル性能を大きく左右することが確認できました。

回路図

Arduino×Python×Kerasで実現する高精度雨予報システムの構築

Arduinoスケッチ完全版:GitHub

製造プロセス

  1. Raspberry PiとPythonでリモート温度センサーを構築 – ステップバイステップガイド
  2. Arduino Nano RP2040で作るDIY Photoshopコントロールコンソール
  3. Python連携で信頼性向上: Arduino RFID勤怠管理システム
  4. Arduinoと1Sheeldで作る万能Androidリモコン──IR制御で家電を一括操作
  5. Arduinoとスマホで作るスマート電圧計 – 簡単DIYプロジェクト
  6. Arduinoで作る赤外線心拍センサー:低コスト・リアルタイム波形表示のステップバイステップガイド
  7. Arduino UNOで周波数とデューティサイクルを高精度測定
  8. ArduinoとNokia 5110ディスプレイで自作電圧計:ステップバイステップガイド
  9. Arduino超音波センサーとProcessingで作るリアルタイム距離測定ソナー
  10. Bolt IoTとArduino UNOでLED輝度をシームレス制御
  11. Python os.rename()でファイル・ディレクトリをリネーム:ステップバイステップガイド