太陽光+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通信ができるようになります。

コメントを残す

メールアドレスが公開されることはありません。