微生物燃料電池で小型冷却ファンを回すマイプロジェクトを実行中である。
前回は、電流発生菌の餌となりうるお酢や乳酸菌飲料を入れることで電池の性能が上がるか実験したが、思った結果が得られなかった。性能を測る上での測定条件がばらついていることや、測定データが少ないことが原因の可能性もあるので、この辺りの懸念を取り除くよう、自動で電圧を測定できる仕組みを構築しようと思う。
実現したいこと(要求仕様)
- 電池のI-V特性を測るため、開放電圧及び、負荷電圧を自動で測定する。測定は、一定時刻(AM6:00)に開始し、以下4つの状態の電圧を測定する。
1) 開放状態
2) 2kΩ抵抗接続時
3) 1kΩ抵抗接続時
4) 680Ω抵抗接続時 - 負荷抵抗を接続した後は、電圧が安定するまで一定時間待ち、その後、電圧を測定する。
- 負荷電流は、接続する抵抗が既知であることからオームの法則で求める。I=V/R
- 測定が完了したら、測定した電圧値及び求めた電流値をスマホへ通知する。
※I-V特性のフラフは、上記1)~4)の状態の電圧・電流から手動でグラフを作る。将来的には、グラフの作成も自動化したいと思う。
システムの概要
上図は、要求仕様を満たすためのシステムの概要となる。小型コンピュータであるRaspberry Pi3に、AD変換モジュール(アナログ値をデジタル値へ変換するモジュール)を接続し電圧を測定する。AD変換モジュールは、4チャンネル/分解能16ビット/I2Cインターフェース対応のADS1115のチップを搭載したモジュールを使用。アナログ値からデジタル値へ変換された電圧データはI2Cインターフェースを経由してRaspberry Pi3で取得する。
また4つの状態の切り替えはリレーモジュールによって実現する。リレーとは電磁石を利用したスイッチである。スイッチなのでオンとオフの状態を切り替えられる。例えば下図で考えると、リレー1のスイッチをオン、リレー2のスイッチをオフとすると、電池には抵抗1がつながる。また、リレー1のスイッチをオフ、リレー2のスイッチをオンとすると、電池には抵抗2がつながる。リレー1とリレー2のスイッチを両方オフにすると、電池には抵抗がつながらない状態、つまり開放状態になる。
なので、3つのスイッチを使えば、1)抵抗を繋げない状態(開放状態)、2)2kΩ抵抗を繋いだ状態、3)1kΩ抵抗を繋いだ状態、4)680Ω抵抗を繋いだ状態を作り出すことができる。それぞれのリレースイッチの状態は、Raspberry Pi3の信号(GPIO)から制御できる。
リレースイッチをオン・オフするためのGPIOの制御、測定した電圧を得るためのI2Cインターフェースの制御、そして、電圧データをスマホへ送信するためのLine Notifyの制御は、Python3のプラグラムを作成し、そのプログラムを定時に起動する。
完成したシステム
上の写真は、自動で電圧を測定するシステム概観である。朝06:00にPython3のプログラムが起動し、4つの状態の電圧を測定したあと、計算で求めた負荷電流とともにLineへメッセージが送られるようになった。
これまで、電圧計を使って手動で測定していたが、私が寝ている間にも、自動で測定してくれるので、とても楽になった。
現状は1台の電池の測定しかできないが、リレーモジュールを増やせば同時に複数の電池の測定も可能となるだろう。しかし、実験している電池は2台であるので、電池を繋ぎ変えることで十分対応ができる。06:00と07:00にPython3プログラムを2回起動するようにしておけば、私がやることはたった2つだ。
- 1回目の測定が完了する06:30にLine Notifyからのプッシュ通知がスマホにくるので、この音で目覚める。
- そして、次の測定が始まる07:00までの間に、別の電池へ繋ぎ変える。
電池の繋ぎ変え作業があると思うと2度寝が絶対にできないので、軽い使命感のもと早起きができて、朝の時間を有効に使うことにも役立っているように思う。
作り方を知りたい人は、以降の記事も読み進めてほしいと思う。
使用した部材
- Raspberry Pi 3 x1
OS: Raspbian GNU/Linux 8.0 (jessie)
Python: 3.6.9 - AD変換モジュール(HiLetgo 2個セット ADS1115 4チャンネル 16ビット I2C ADC モジュール ゲインアンプ Arduino Rpiと互換) x1
- リレーモジュール(SODIAL(R) 4チャンネル5Vリレーモジュール) x1
- 抵抗 2kΩ x1、1kΩ x1、680Ω x1
- 線材
- みのむしクリップ x2
接続方法
I2Cのスレーブアドレスは、ADDRピンを繋ぐ場所によって4種類から設定できるが、今回はVDD(+3.3V)へ繋ぐことで0x49とした。
また、差動入力A0-A1を電池の+と-に接続して電圧を測定した。
Raspberry Pi3の初期設定
I2Cの有効化
以下コマンドを入力し、Raspberry Pi3の初期設定画面を起動する。Interfacing Options->I2CからI2Cを有効化する。
ライブラリのインストール
以下コマンドを入力し、ライブラリをインストールする。
adafruit-circuitpython-ads1x15
adafruit-circuitpython-busdevice
Adafruit-PlatformDetect
Adafruit-PureIO
Line Notifyの初期設定
Line Notifyを使ってRaspberry Pi3からスマホのLineへメッセージを送るには、次の設定が必要になる。
- スマホのLineアプリで、メッセージを受け取るためのトークルームを作る。
- 次に、LINE Notifyのホームページからログインした後、マイページの「アクセストークンを発行」によってアクセストークンを発行する。発行の際に、トークン名(通知の際に表示される文字)と通知を送信するトークルーム(1で用意したもの)を入力する。発行されたアクセストークンは、Python3のプログラムで使うので、メモ帳などにコピーしておく。
- LINE NotifyのLINEアカウントを、1で用意したトークルームに招待する。
作成したコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import requests from datetime import datetime import time import board import busio import adafruit_ads1x15.ads1115 as ADS from adafruit_ads1x15.analog_in import AnalogIn import RPi.GPIO as GPIO I2C_ADDR=0x49 T_WAIT = 60*10 #[sec] R_OPEN = 0 R_2K = 2000 R_1K = 1000 R_680 = 680 def get_voltage(): # Create the I2C bus i2c = busio.I2C(board.SCL, board.SDA) # Create the ADC object using the I2C bus ads = ADS.ADS1115(i2c, gain=4, address=I2C_ADDR) # Create differential input between channel 0 and 1 chan = AnalogIn(ads, ADS.P0, ADS.P1) print("{:>5}\t{:>5.3f}".format(chan.value, chan.voltage)) return chan.voltage def r_switch(sel_mode): GPIO.setmode(GPIO.BCM) GPIO.setup(18, GPIO.OUT) GPIO.setup(23, GPIO.OUT) GPIO.setup(24, GPIO.OUT) if sel_mode == R_2K: GPIO.output(18, False) GPIO.output(23, True) GPIO.output(24, True) elif sel_mode == R_1K: GPIO.output(18, True) GPIO.output(23, False) GPIO.output(24, True) elif sel_mode == R_680: GPIO.output(18, True) GPIO.output(23, True) GPIO.output(24, False) elif sel_mode == R_OPEN: GPIO.output(18, True) GPIO.output(23, True) GPIO.output(24, True) else: GPIO.output(18, True) GPIO.output(23, True) GPIO.output(24, True) def line(s_mes): url = "https://notify-api.line.me/api/notify" token = "xxx"#ここへアクセストークンを記述する headers = {"Authorization" : "Bearer "+ token} s_now = '({0:%Y/%m/%d %H:%M:%S})'.format(datetime.now()) message = "測定完了" + s_now + "\n" + s_mes payload = {"message" : message} r = requests.post(url, headers = headers, params=payload) print(message) print(r.text) def main(): print('start') # 開放状態へ切り替え # r_switch(R_OPEN) # 開放電圧の測定 v_open = get_voltage() # 2kΩ抵抗の接続切り替え r_switch(R_2K) # 安定するまで待つ time.sleep(T_WAIT) # 2kΩ抵抗接続時の負荷電圧の測定 v_2k = get_voltage() # 1kΩ抵抗の接続切り替え r_switch(R_1K) # 安定するまで待つ time.sleep(T_WAIT) # 1kΩ抵抗接続時の負荷電圧の測定 v_1k = get_voltage() # 680Ω抵抗の接続切り替え r_switch(R_680) # 安定するまで待つ time.sleep(T_WAIT) # 680Ω抵抗接続時の負荷電圧の測定 v_680 = get_voltage() # 開放状態へ切り替え # r_switch(R_OPEN) # 出力文字列 s_vout = 'V[V],Opne={0:5.3f},2K={1:5.3f},1K={2:5.3f},680={3:5.3f}'.format(v_open, v_2k, v_1k, v_680) s_iout = 'I[mA],,2K={0:5.3f},1K={1:5.3f},680={2:5.3f}'.format(v_2k/R_2K*1000, v_1k/R_1K*1000, v_680/R_680*1000) s_out = s_vout + '\n' + s_iout print(s_out) # lineへ通知 line(s_out) GPIO.cleanup() if __name__ == '__main__': main() |
プログラムの定時起動
プログラムを定時に起動するには、crontabファイルを編集する。以下のコマンドを入力するとエディタが開く。
1 2 |
00 06 * * * /usr/local/bin/python3 /home/pi/smfc/smfc_iv.py 00 07 * * * /usr/local/bin/python3 /home/pi/smfc/smfc_iv.py |