太陽光発電の発電量をロギングしてみた。(5)温度の計測(DS18B20) ＆ RaspberryPiで電流・電圧・温度をロギング

[【太陽光発電の発電量をロギングしてみた。目次】](https://qiita.com/takoyakiya/items/6b318ab83bcac86c966c)
## DS18B20について

太陽光発電の発電効率は、パネル温度によって変化する。
夏は日射が強くたくさん発電しそうだが、パネル温度の上昇に伴い発電効率が低下し、思ったほど発電しないこともあるようだ。
そこで、パネル温度を測定するために、AmazonでDS18B20の入った温度プローブを購入した。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627239/fb6a9b7d-3239-c716-4541-ff7997395444.png)

Microbitにも温度センサはついているが、あくまで、MicrobitのCPU温度なので、太陽光パネル温度の測定には使えない。

DS18B20は、I2CでもSPIでもなく、1-Wireという異なったシリアルインターフェースを使用する。
SPIは3本、I2Cは2本通信線が必要だが、1-Wireは1本で済むため、配線は簡単である。しかし、通信プロトコルは複雑である。

ここは、ライブラリ頼みである。
Microbitでは、MakeCodeの拡張機能からDS18B20用の拡張ブロックや1-Wire用通信用の拡張ブロックを入手できそうだ。

[Connect DS18B20 temperature sensor to micro:bit](http://www.suppertime.co.uk/blogmywiki/2019/04/microbit-ds18b20-temperature-sensor/)

早速、拡張機能をインストールし、MakeCodeでプログラムを組んでみて、ダウンロードしようとしたが、、、なぜかダウンロードできない！！！
2020年の秋にMicrobit V2向けにMakeCodeがアップデートされたとのこと。
拡張ブロックが使用するポートが標準機能の使用ポートと重なってしまったためかよくわからないが、使用不能になってしまっていた。
早くアップデートしていただきたいものである。

しかし、すぐにアップデートされる可能性は薄いため、いた仕方なく、これまでのMicrobit路線を、RaspberryPiオンリー路線へと方針転換することを決断した。

## 新ハードウェア構成

最新のラズパイ4をゲットしたいと思いながらも、ありもの活用主義で、家の倉庫で眠っていたRaspberryPi1 Model B を引っ張り出した。

実は、この初期モデルには無線LANもBluetoothも付いていない。
屋外の太陽光パネルに接続して測定したデータをアップロードするにはインターネットに接続しなければならない。
さすがに家の中からLANケーブルを引っ張り出すのは困難なので、低電力の無線LAN子機を入手した。

これまでMicrobitに接続していたINA260と、今回購入したDS18B20をラズパイのGPIOに接続する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627239/22ffaa25-f88a-6192-66cf-6ce524b945da.png)
<h6 style="text-align: center;">図1　GPIO接続図</h6>

DS18B20にはパラサイトパワードモードがあり、GND線と信号線の2本のみの接続で使用できるようだが、今回は使用しなかった。ちなみにこのモードを使用すると、温度センサーを複数連結して使用できるとのことである。

【参照】
[DS18B20データシート](https://datasheets.maximintegrated.com/en/ds/DS18B20.pdf)
[Arduino+DS18B20で温度測定してみた](https://qiita.com/hnw/items/315fad0d4b60ada10d00)

## RaspberryPiのインターフェース設定

「設定」-「PaspberryPiの設定」を起動し、インタフェース設定で「I2C」と「1-Wire」を有効化する。

![Rasberry1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627239/c502f9f5-0741-9c29-ca26-2e9a5e41e988.png)

![Rasberry2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627239/edc334cb-ac2e-44e1-e0fb-202810df7b5f.png)


## プログラム説明

```python
import time
import subprocess
import os
import glob
from datetime import date, datetime
import board
import adafruit_ina260

import serial
import struct
import datetime as dt
import json
from simple_salesforce import Salesforce

USERNAME = "ユーザー名"
PASSWORD = 'パスワード'
SECURITY_TOKEN = "セキュリティトークン"

# Salesforceログイン関数
def Login():
    sf = Salesforce(username=USERNAME, password=PASSWORD,
                    security_token=SECURITY_TOKEN)
    return sf

# INA260の初期化
i2c=board.I2C()
ina260=adafruit_ina260.INA260(i2c,0x42)

# Salesforceにログイン
sf = Login()

# DS18B20の計測結果出力フォルダ
dirs = os.listdir("/sys/bus/w1/devices")
counter = 0
try:
    while True:
        for dir in dirs:
            if "28-" in dir:
                counter += 1
                # catコマンドでw1_slaveファイルの内容を取得
                tfiles = subprocess.check_output(['cat','/sys/bus/w1/devices/' + dir + '/w1_slave'])
                stfiles = str(tfiles)
                if "YES" in stfiles :
                    pos = stfiles.find("t=",50,80)
                    temp = int(stfiles[pos+2:-3])/1000.0 # ファイル中の文字列から温度を取得
                    print("Current: %.2f Voltage: %.2f Power: %.2f Temp: %.2f" % (ina260.current, ina260.voltage, ina260.power, temp))
                    st = "{0},{1},{2},{3},{4}\n".format(datetime.now(), ina260.current, ina260.voltage, ina260.power, temp)
                    with open('/home/pi/Documents/current_{}.log'.format(date.today()), mode='a') as f:
                        f.write(st)
                    
                    datas = st.split(",")
                    if len(datas)<3:
                        continue
                    t1 = datas[0][0:19]
                    t2 = t1.replace(" ","T") + "Z" # SalesfoeceのDatetime型表現は「2002-10-09T19:00:00Z」
                    try:
                        for i in range(1,len(datas)):
                            datas[i] = datas[i].replace("b'","").replace("\\r\\n'","").strip()
                            
                        if len(datas[1])==0 or len(datas[2])==0 or len(datas[1])>10 or len(datas[2])>10 :
                            continue
                        if datas[1][:1].isdigit()==False or datas[2][:1].isdigit()==False:
                            continue

                        res = sf.GeneratorLog__c.create({'Name': t1,
                                                                'MeasDate__c': t2,
                                                                'Current__c': float(datas[1]),
                                                                'Voltage__c': float(datas[2]),
                                                                'PowerMeas__c': float(datas[3]),
                                                                'Temperature__c': float(datas[4])})
                        if res.get('error'):
                            raise Exception(response.get('error_description'))

                        print(json.dumps(res, indent=6))
                    
                    except Exception as e: # セッション切れでログアウト時の例外を拾い、再ログイン後リトライする。
                            sf = Login()
                            res = sf.GeneratorLog__c.create({'Name': t1,
                                                                'MeasDate__c': t2,
                                                                'Current__c': float(datas[1]),
                                                                'Voltage__c': float(datas[2]),
                                                                'PowerMeas__c': float(datas[3]),
                                                                'Temperature__c': float(datas[4])})
                            print(json.dumps(res, indent=6))
        
        time.sleep(60)

except Exception as ex:
    print(ex)
```

今回、INA260からデータ取得するために、adafruit_ina260というライブラリを使用した。
このライブラリ、電流はmA、電圧はV、電力はmWになっているので、上記コードではそのままの値を使用しているが、必要であれば電流と電力を1000で割ること。

【参照】
[adafruit_ina260 Library APIマニュアル](https://circuitpython.readthedocs.io/projects/ina260/en/latest/api.html)
[[ラズパイ] 電圧・電流をラズパイで計測する](https://androiphone.uvs.jp/?p=2306)

DS18B20に関しては、RaspberryPi側に1-Wire用のドライバがあり、ファイルに書き出された測定値を取得するだけなので、特別なライブラリは必要ない。
以下のサイトを参照させてもらった。

[5ドル！ラズパイ・ゼロ（Raspberry pi Zero）でIoT](https://www.denshi.club/pc/raspi/5raspberry-pi-zeroiot161.html)

## RaspberryPiの電源について

Microbitで電流測定するときは、ダイソーの300円2000mAhモバイルバッテリーを使用して6時間ほど稼働させても十分だった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627239/52f3e479-b3d5-9acc-002d-0c8d45b12d50.png)

今回も同様にRaspberryPiにこのバッテリーを使用してみた。
ちゃんと稼働したが・・・2時間半で測定不能になった。
そのため、12000mAhのモバイルバッテリーを購入。このサイズなら余裕で半日はもつ。
ただ、ここではRaspberryPi1Bを使用しているので問題ないが、よりハイスペックなRaspberry4だと消費電力も電源推奨電流値も大きいので、モバイルバッテリーのみでいけるかどうかは不明である。

これで電流・電圧・温度をロギングできるようになった。
データがある程度たまったら解析的なことも行っていきたい。

[【太陽光発電の発電量をロギングしてみた。目次】](https://qiita.com/takoyakiya/items/6b318ab83bcac86c966c)