yuyuのアイコン画像
yuyu 2024年09月20日作成 (2024年10月30日更新) © MIT
製作品 製作品 Lチカ Lチカ 閲覧数 140
yuyu 2024年09月20日作成 (2024年10月30日更新) © MIT 製作品 製作品 Lチカ Lチカ 閲覧数 140

ラズパイ水位計~かわりに田んぼの様子見てくる~

キャプションを入力できます

概要

田 ん ぼ の 水 路 の 水 位 を リ ア ル タ イ ム で 監 視 し 、 大 雨 や 異 常 な 水 位 変 動が 発 生 し た 場 合 に 、農 家 や 管 理 者 に 通 知 を 送 信 す る こ と で 、適 切 な 対 策を 促 す こ と が で き る 。こ れ に よ っ て 、洪 水 の リ ス ク を 軽 減 し 、農 作 物 の保 護 と 水 管 理 の 効 率 化 を 実 現 し ま す 。

システム・設置イメージ図

システムイメージ図↓

システムイメージ図

設置イメージ図(通常時)↓
設置イメージ図
設置イメージ図(危険時)
設置イメージ図

追記
現段階で超音波センサで測定した値によって通知を送信することができている。今後、ラズパイを追加してLoRa通信できるように開発していく予定

アイデア詳細

今回製作したシステムの基本機能を紹介する。

  • リアルタイム水位監視:超音波センサで水面までの距離を定期的に測定し、データをラズパイに送信する。
  • 自動警告通知システム:測定した距離から異常な水位上昇を検知するとLineNotifyを通じて警告を通知する。
  • 履 歴 デ ー タ の 記 録 : 測 定 デ ー タ を 保 存 し 、長 期 的 な 水 位 の 変 動 を可 視 化する。

全 体 の 処 理 の 流 れ と し て は 、常 時 ラ ズ パ イ と 接 続 し て い る 超 音 波 距離セン サ ー モ ジ ュ ー ル で 水 路 の 水 位 を 測 定 し 、 CSV フ ァ イ ル に 保 存 し 、5回測定するごとにLineに送信されます。
ま た 、 測 定 し た 値 が 基 準 値 を 超 え る と 水 位 が 危 険 な 状 態 と 判 断 し て 、LoRa で ラ ズ パ イ 間 を 通 信 し 、 ラ ズ パ イ か ら ス マ ホ へ と LineNotify を通 じ て 通 知 を 送 信 し ま す 。

使用した部品

今回の製作で使用した部品を紹介する

  • Raspberry pi 4 × 2
  • 超音波センサ(AJ-SR04M)
  • ブレッドボード
  • LoRaモジュール
  • 配線(ジャンパー線など)

実際の配置イメージ

溝に沿うようにセンサの先を固定できるような外装にする予定。センサは、防水使用のものなので実際の設置場所でも正常に動作すると思われる。
実際の配置イメージ
ハードについて 
現時点では、ラズパイ1つのみ使用して動作させているが遠距離でデータを受信できるようにもう1つラズパイを追加し通信させることを考えている。また、電源をバッテリーにし、屋外での使用も考えている

LineNotifyの動作画面

センサで測定した水位が危険値の時(今回のプログラムでは、30cmを超えるとき)、警告文と具体的な距離が通知される。また、5回測定ごとにセンサの測定値を送るように動作している。
LineNotifyの動作画面

接続

接続方法は以下の通りになっていて、ジャンパー線でブレッドボードを介して直接接続している。

センサ側 ラズパイ側
AJ-SR04M Raspberry Pi 4
5V 5V
Trig Pin 15
Echo Pin 14
GND GND

接続図↓
接続図

ソースコード

以下、ラズパイのプログラムになります。
センサ側動作プログラムの概要は、距離センサで測定した値が30cmを超えると、測定値とともに危険文が通知されます。さらに、5回測定する毎にCSVファイルに保存した値をまとめて通知してみることができるようになっています。

センサ側動作プログラム

import RPi.GPIO as GPIO import time import requests import csv import os # GPIOの設定 GPIO.setmode(GPIO.BCM) TRIG = 15 ECHO = 14 GPIO.setup(TRIG, GPIO.OUT) GPIO.setup(ECHO, GPIO.IN) # Line Notifyのアクセストークン LINE_NOTIFY_TOKEN = 'トークン' LINE_NOTIFY_URL = 'https://notify-api.line.me/api/notify' # CSVファイルの設定 csv_file = 'sensor_data.csv' # CSVファイルの初期化 with open(csv_file, mode='w', newline='') as file: writer = csv.writer(file) writer.writerow(['Time', 'Distance (cm)']) # ヘッダー def send_line_notify(message, token): headers = { 'Authorization': f'Bearer {token}', 'Content-Type': 'application/x-www-form-urlencoded' } payload = {'message': message} response = requests.post(LINE_NOTIFY_URL, headers=headers, data=payload) return response def get_distance(): GPIO.output(TRIG, False) time.sleep(2) GPIO.output(TRIG, True) time.sleep(0.00001) GPIO.output(TRIG, False) start_time = time.time() stop_time = time.time() while GPIO.input(ECHO) == 0: start_time = time.time() while GPIO.input(ECHO) == 1: stop_time = time.time() time_elapsed = stop_time - start_time distance = (time_elapsed * 34300) / 2 return distance def read_csv(): with open(csv_file, mode='r') as file: reader = csv.reader(file) next(reader) # ヘッダーをスキップ data = [row for row in reader] return data try: while True: distance = get_distance() current_time = time.strftime('%Y-%m-%d %H:%M:%S') with open(csv_file, mode='a', newline='') as file: writer = csv.writer(file) writer.writerow([current_time, f"{distance:.2f}"]) # データ行の追加 print(f"距離: {distance:.2f} cm") if distance > 30: message = f"\n⚠️警告: 距離が {distance:.2f} cm を超えました!" response = send_line_notify(message, LINE_NOTIFY_TOKEN) if response.status_code == 200: print("通知が送信されました") else: print("通知の送信に失敗しました") # CSVの内容をLINEに送信 if time.time() % 60 < 1: # 1分ごとに送信 csv_data = read_csv() message = "\n📊 センサーデータ:\n" + "\n".join([f"{row[0]}: {row[1]} cm" for row in csv_data]) response = send_line_notify(message, LINE_NOTIFY_TOKEN) if response.status_code == 200: print("データが送信されました") else: print("データ送信に失敗しました") time.sleep(1) except KeyboardInterrupt: print("プログラムが中断されました") finally: GPIO.cleanup()

以下のプログラムは、超音波距離センサの動作確認プログラムになります。
ピンをマイコンと接続することで動作確認が可能になります。接続図を参考にしてみてください。

超音波センサ動作確認プログラム

import RPi.GPIO as GPIO import time # GPIOの設定 GPIO.setmode(GPIO.BCM) TRIG = 15 ECHO = 14 GPIO.setup(TRIG, GPIO.OUT) GPIO.setup(ECHO, GPIO.IN) def get_distance(): # センサーの初期化 GPIO.output(TRIG, False) time.sleep(2) # トリガー信号を発信 GPIO.output(TRIG, True) time.sleep(0.00001) GPIO.output(TRIG, False) start_time = time.time() stop_time = time.time() # エコー信号の開始と終了を計測 while GPIO.input(ECHO) == 0: start_time = time.time() while GPIO.input(ECHO) == 1: stop_time = time.time() # 時間差を計算し、距離を算出 time_elapsed = stop_time - start_time distance = (time_elapsed * 34300) / 2 return distance try: while True: distance = get_distance() print(f"距離: {distance:.2f} cm") time.sleep(1) except KeyboardInterrupt: print("プログラムが中断されました") finally: GPIO.cleanup()

これから
LoRaを用いた遠距離通信に挑戦していく予定

参考文献

yuyuのアイコン画像
生粋のウェイブ使い
ログインしてコメントを投稿する