太陽光+3Gモデム+防水ケースで屋外用RaspberryPiデータロガーを作る レシピ RaspberryPiZero ラズパイ用カメラモジュール SIM用USBモデム 防水ケース 12v鉛蓄電池 太陽光パネル(10W~30W) PWMチャージコントローラ 12v to 5v DC-DCコンバータ ケーブル類 今回データロガー用に使う使う基盤 ina219(電圧・電流センサー) bme280(温湿度・気圧センサー) 概要 自作したラズパイ用防水ケースの性能をチェックするため、bme280で防水ケース内の温湿度を測定します。また、太陽光の発電量を確認するため、ina219でバッテリー電圧および電流を測定します。取得したデータはSIM用USBモデムを用いた3Gモバイルデータ通信を通してPython3でMachinistに送信します。また、ラズパイカメラモジュールで撮影した画像をdropbox_uploader.shを使ってDropboxに送信します。 RaspberryPi Zero用屋外防水ケースを3Dプリンターで自作する 配線図 後で書く。 データログ送信スクリプト Machinistにデータを送信するプログラムをPython3で書きます。jsonで送るようになっているので公式リファレンス通りに作ります。APIKEYが必要なのでユーザーページからコピーします。 ina219とbme280ではi2cを利用します。sudo raspi-configからi2cを有効にしてください。 またライブラリもインストールしておきます。 sudo pip3 install pi-ina219 RPi.bme280 #Python3 import smbus2 import bme280 from ina219 import INA219 import urllib.request import json bme280_address=0x76 #0x76 or 0x77 SHUNT_OHMS = 0.1 #milli ohm APIKEY = "xxxxxxxxxxxxxxxxxx" Url = "https://gw.machinist.iij.jp/endpoint" method = "POST" def machinist_body_property(agent: str): data = {} data['agent'] = agent data['metrics'] = [] return data def machinist_metrics_property(name: str, value): metric = {} metric['name'] = name metric['data_point'] = {'value': value} return metric def sendMachinist(data): headers = { "Content-Type": "application/json", "Authorization": "Bearer " + APIKEY, "User-Agent": "Python3" } senddata = json.dumps(data).encode("ascii") try: req = urllib.request.Request(Url, senddata, headers) data = urllib.request.urlopen(req) html = data.read().decode("ascii") if "Succeeded" in html: print("Send succeeded") data.close() except Exception as e: print(e) #ina219 ina = INA219(SHUNT_OHMS) ina.configure() #bme280 i2c = smbus2.SMBus(1) calibration_params = bme280.load_calibration_params(i2c,bme280_address) data = bme280.sample(i2c, bme280_address, calibration_params) #make_senddata senddata=machinist_body_property('SolarPi') senddata['metrics'].append(machinist_metrics_property('BatteryVoltage',ina.voltage())) senddata['metrics'].append(machinist_metrics_property('BatteryCurrent',ina.current())) senddata['metrics'].append(machinist_metrics_property('Temperature',data.temperature)) senddata['metrics'].append(machinist_metrics_property('Humidity',data.humidity)) senddata['metrics'].append(machinist_metrics_property('Pressure',data.pressure)) sendMachinist(senddata) 通信制御スクリプト USBモデムはアイドル時でもやや消費電力を食うので、通常はバスパワーをオフにしておき、データを送信する時のみオンにしてデータ送信を行えるようにスクリプトを書きます。スクリプトはcrontabで10分毎に動作させます。バスパワーON時の消費電力は20mA、OFFにすると5mA程度です。bashで書きます。 #!/bin/bash #指定したUSBモデムの接続が確立しているか判定 function check_network_connection () { /sbin/ifconfig | grep -q "$1" } #main 通信確立後に実行したいやつを書く function main () { python3 /home/pi/sendMachinist.py #データログ送信 raspistill -o /home/pi/image.jpg -q 10 -w 1200 -h 900 #写真撮影 /home/pi/dropbox_uploader.sh upload /home/pi/image.jpg pi/`date +%Y-%m-%d_%H:%M:%S`.jpg #dropbox送信 } SOC_USB=/sys/devices/platform/soc/20980000.usb/buspower echo 1 | sudo tee SOC_USB >/dev/null #USBバスパワーON sudo /sbin/ifup ppp0 #USBモデムアップ #接続確立まで15秒待機 for ((i=0; i<15; i++)) do if check_network_connection ppp0; then echo "Online" main break else sleep 1 fi done sudo /sbin/ifdown ppp0 #USBモデムダウン echo 0 | sudo tee SOC_USB >/dev/null #USBバスパワーOFF cronに登録します。 crontab -e */10 * * * * /home/pi/script.sh 動作確認 送信された温湿度、大気圧、バッテリー電流、電圧はこのように表示されます。 くもり、雨を考えると太陽光は30W欲しいです。バッテリーも容量多ければ多いほどよい。 ssh通信で遠隔メンテナンス 遠隔でssh接続ができれば屋外に設置してあるラズパイを取り外して持って帰ってコード編集・・・などの手間がなくなります。 sshポートフォワーディングを利用して遠隔でssh通信ができるようにします。一般的なSIMのデータ通信は外部からアクセスできないので、踏み台となるsshサーバーを用意する必要があります。 ①ラズパイからリモートフォワードでsshポートをsshサーバー内部に転送後、②アクセス端末側からsshサーバーにsshログインし、③さらに先ほどsshサーバー内部に転送されたポートにsshログイン(多段ssh)することで、踏み台sshサーバーを介してラズパイに接続できます。踏み台サーバーは条件を満たせば永久無料で使えるGoogleComputeEngineサービスを使いました。自宅で固定IPもしくはDDNSを設定しているのであれば、宅内にsshサーバーを置いて外部公開(ポート開放)でも良いです。 なお、先ほど紹介したbashスクリプトはデータ送信時にしか通信を行わないため、ラズパイとsshサーバー間のssh接続を維持できません。ssh通信したいときだけネットワーク接続を遮断しないようにしておく必要があります。今回はGCEにhttpサーバーを立て、sshの有効・無効状態(1か0)を返すページを作っておいて、スクリプト動作時にそのページにアクセスし、1が返ってきた場合は通信を切らずにautosshでリモートフォワード接続を維持、0が帰ってきたら通信を切るようスクリプトを書きます。これで必要な時だけssh通信ができるようになります。 ShareFacebookTwitteremail