#2001 Current Measure Brick Edition
ハードウェア開発中
基本原理は、ビーコン(負荷)に抵抗の小さい抵抗を直列に接続して、その抵抗の電位差が解れば電流値がわかることを利用しています。(i=v/R)
Connecting
I2Cコネクタへ接続します。
Support
Registor
Slave Address |
---|
0x40 |
Datasheet
Document |
---|
Schematic
ビーコンの電流計測方法
Sample Code
Arduino
電流計測はADV100msで行ってください。
//#2001CurrentMeasureBrickEdition
//Fabo Inc. 2015
#include <Wire.h>
//INA226のレジスターセット
#define ADDRESS B1000000 //HEX 0x40(INA226のアドレス)
#define CONFIG B0000000 //HEX 0x00
#define SHUNTV B0000001 //HEX 0x01
#define BUSV B0000010 //HEX 0x02
#define POWER B0000011 //HEX 0x03
#define CURRENT B0000100 //HEX 0x04
#define CALIB B0000101 //HEX 0x05
#define MASK B0000110 //HEX 0x06
#define ALERT B0000111 //HEX 0x07
//シリアルモニタ速度
#define Monitor 9600
//Battery Capacity CR2032 220mAh,{CR2477N 950mAh,CR2477 1000mAh}
//寿命予測する電池の容量を入力する。
#define BAT_Capacity 1000
//ビーコンのアドバタイズ間隔 100msでの場合
#define Adv_Interval 100
//テストID
#define TestID 0001
//測定値の補正する係数
const float miri = 0.001f;
const float Hosei = 1.0f;
//パケットを100msで出した場合143.36msに少なくとも1回はビーコンからは発射されるので100msに補正する。
//140μsごとに連続的に計測し1024回の平均だと143.36msになる。この数値は当然ながら実際よりも低い数値になる。
//140μS * 1024times = 143.36ms 143.36 / 100 = 1.436
const float Adj = 1.436f;
//シャント抵抗の補正 2.2Ω使用時
const float registoregit = 0.00113f;
//測定の設定 マスター(Arduino)からスレーブ(INA226)へデータを書き込み要求する関数
void Slave_write(byte regset, unsigned short regdata)
{
//通信開始 指定するスレーブ(0x40)を指定する。
Wire.beginTransmission(ADDRESS);
//データをスレーブに書き込みをする。
Wire.write(regset);
//バイト単位なので、上位桁から8ビットを送るので
Wire.write(regdata >> 8);
//のこり下位8ビットを書き込み要求。
Wire.write(regdata);
//スレーブに通信終了の信号を送る。
Wire.endTransmission();
}
//測定結果 マスター(Arduino)からスレーブ(INA226)へデータ送信要求し、スレーブからのデータ受信する関数。
unsigned short Slave_read(byte regset)
{
//** マスターの送信
short rd = 0;
//通信開始 指定するスレーブ(0x40)を指定する。
Wire.beginTransmission(ADDRESS);
//設定データをスレーブ(0x40)に送る。
Wire.write(regset);
//スレーブに通信終了を信号を送る。
Wire.endTransmission();
//** マスターの受信
// スレーブ(0x40)からの計測データを要求する。2は2バイト(16ビット)
Wire.requestFrom(ADDRESS, 2);
//受信できたバイト数だけ繰り返す。
while(Wire.available()) {
//左に1バイト分シフト。(スレーブからくる測定データは上位桁数から読むので8ビット分シフトする)
rd = rd * 256;
//reauestFromから受信したデータを取り出し、下の桁の8ビットに代入する。
rd += Wire.read();
}
return rd;
}
void setup() {
//シリアルモニタに9600bpsで表示する。
Serial.begin(Monitor);
//I2C通信を初期化する。
Wire.begin();
//コンフィグレーション(0x00)で測定の設定をスレーブに要求し、次のデータ(コンフィンングレーションレジスタ)0B100111011011111は、最下位ビット111は、シャントとバスを連続で測るモード、
//4から6ビット目011はシャントの測定時間140μ、7ビットから9ビット目011は、Fバス側の測定時間140μ、
//10から12ビット目は、111は1024回計測しその平均を出す。
Slave_write(CONFIG, 0B100111011011111);
Slave_write(CALIB, 2048);
}
void loop() {
//計測結果のid
static unsigned int c_id;
float bus_v,shunt_v,bus_v125,c;
//CSVのフィールド
static boolean pre;
//バス電圧データを求め、1ビットあたり1.25mVなので
bus_v125 = Slave_read(BUSV) * miri * 1.25f;
//シャント間の電圧を求める。シャント抵抗の1ビットあたり2.5μVであり平均を100msに補正する。
shunt_v = Slave_read(SHUNTV) * 0.000001 * 2.5f * Adj;
//1mAを0.1mAに修正する
c = (Slave_read(CURRENT) / Hosei) * Adj * registoregit;
int cc;
cc = (Slave_read(CURRENT) / Hosei);
c_id++;
Serial.println(c,4);
delay(1000);
}
Mac(python2.7.9)
計測されたサンプルの値をpythonでグラフ化します。Macはあらかじめ標準でPythonはインストールされていますが、実行に必要なモジュールをインストールしてください。
# coding: utf-8
#CurrentMeasureGraph Beta Fabo 2015
#Version 1.0
#Python Version 2.7.9
from __future__ import unicode_literals, print_function
import numpy as np
import matplotlib.pyplot as plt
import pygame
from pygame.locals import *
import serial
import sys
import math
import time
import datetime
import locale
def pause_plot():
# COMポート Macは、/dev/tty.usbmodem****' windowsはCOM*
ser = serial.Serial('/dev/tty.usbmodem1411')
fig, ax = plt.subplots(1, 1)
#バッテリーの設定 リチウム電池CR2477 1000mhA
batteryCapacity = 1000
#初期化
x = []
y = []
z = []
n = 63
x = n * [0]
y = n * [0]
# グリッドを表示
plt.grid(True)
# 軸の設定する
plt.xlim([0, 63])
plt.ylim([0, 2.5])
#軸の名前
plt.xlabel("Samples(Per Seconds)")
plt.ylabel("AverageCurrent[mA]")
#グラフタイトル
ax.set_title('Fabo CurrentMeasure ADV100ms TX=15 37,38,39ch Version 1.0Beta')
lines, = ax.plot(x, y, color="b", marker="p")
j = 0
w = 0
while True:
#Arduinoからデータの取得
d = float(ser.readline().rstrip())
#平均を出すのにデータを蓄積する。
z.append(d)
date = datetime.datetime.today()
#グラフの再描画
if j == 63:
j=0
for c in range(63):
x[c] = 0
for c in range(63):
y[c] = 0
#グラフを消去する。
for txt in ax.texts:
txt.set_visible(False)
y[j] = d
#データの取得していない部分は最新ポイントへ移動
for c in range(63 - j):
x[j+c] = j
y[j+c] = y[j]
#テキストの表示
h = ax.text(x[j]+1, y[j], d,color = 'k',size="7")
ax.texts
#日付の表示
v = ax.text(1, 1.1, '%s/%s/%s %s:%s:%s' % (date.year, date.month, date.day,date.hour,date.minute,date.second) ,color = 'k',size="12")
#平均の表示
ave = sum(z) / (w+1)
s = ax.text(1, 1, "AVERAGE = " + str(round(ave,5)) + "mA" + "(" + str(round(ave,5)*1000) + "uA" + ")",color = 'k',size="12")
#サンプル数の表示
r = ax.text(1, 0.9, "Samples = " + str(w+1),color = 'k',size="12")
#リチウム電池寿命の表示
b = ax.text(1, 0.8, "Expected battery life = " + str(int(round(batteryCapacity/ave/24))) + "Days",color = 'k',size="12")
#CVS形式で表示
if w == 1:
print("Time,Sample,Currnt(mA)")
print ('%s/%s/%s %s:%s:%s,' % (date.year, date.month, date.day,date.hour,date.minute,date.second) + str(w) + "," + str(d))
j += 1
w += 1
lines.set_data(x, y)
plt.pause(.01)
if __name__ == "__main__":
pause_plot()
Result
ADV100msで行った結果です。例えば300msでADVで行った場合の時間は単純に3倍となります。
Xcode(C)
マンガン、アルカリ乾電池では自己放電が高いため、考慮しなくてはいけません。下のコードは自己放電率は5%としています。以下のコードは計算をわかりやすくするため、1秒間の消費電流はADV100ms時は0.35mAでしたので1000msは0.035mAとします。1秒間に何回電波を出すかをAdvertiseTimesとしています。C言語ですので多くの環境で実行できますが、Xcodeを想定しております。
//
// main.c
// CurrentTImeEqution 1.0Beta
//
//
#include <stdio.h>
#include "main.h"
//条件を設定(アルカリ乾電池の自己放電率は5%,リチウム電池は1%)
#define BatteryVolum 4000
#define AvarageCurrent 0.035
#define AdvertiseTimes 10.0
#define SelfDischargeRate 0.95
#define Correctionfactor 0.8
int main(void){
unsigned int t = 0;
double RestCurretVolume = 0.0;
static double h = 365.0*24.0;
printf("********Processing Start******* \n");
do{
RestCurretVolume = BatteryVolum * pow( SelfDischargeRate, (t/h))-((AvarageCurrent*AdvertiseTimes)*t);
printf("Remaining capacity:%fmAh Elapsed hour:%d(h)\n",RestCurretVolume,t);
t++;
}while(RestCurretVolume >= 0);
//前の結果を取り出す。
printf("************Result************\n");
t = t - 2;
//バッテリー切れ時間の表示。
printf("Battery exhaustion time = %d (hours)\n",t);
//8掛けして、マージンを考慮した結果。
double Result = t * Correctionfactor;
//自己放電の影響度を算出。
double ImpactSelfDischargeRate = (1 - (Result / ((BatteryVolum / (AvarageCurrent * AdvertiseTimes)))))*100;
printf("Degree of influence by the self-discharge = %f (%%)\n",ImpactSelfDischargeRate);
//それぞれの単位で結果を表示。
printf("********Corrected value******* \n");
printf("| Resulthours | %f(hours)\t|\n",Result);
printf("| ResultDays | %f(days) \t|\n",Result/24);
printf("| ResultMouths| %f(months) \t|\n",Result/24/30);
printf("| ResultYears | %f(years) \t|\n",Result/24/30/12);
printf("********Processing Exit*******\n");
return 0;
}