UPSを使ってると、必ず出会うのがバッテリ交換。
環境温度にもよるそうですが、UPSメーカによると3から5年程度で寿命を迎えるのが一般的だそうです。
でまぁ、うちのサーバ系でもUPSが稼働してるんですが、そのうち1台で1年半ほど前に警告がでて交換しました。まぁ、これで当分は大丈夫だろ・・・と思ってたんですが、またしても交換警告が。しかも今回は2台連続で。1台は稼働開始から3年ほどたったUPSなんで、まぁ妥当っちゃぁ妥当なんですが、もう一台が1年半前に交換したUPS。
えぇー?なんで・・・・?
ちうわけで、調べてみることにしました。
ぐぐってみると、バッテリー寿命は電池の内部抵抗を見てるとか。というわけで、こんな装置をつくってみました。
制御系にRaspberry PIを利用して、電池からの放電制御と電流・電圧測定を行います。
負荷は、バッテリーを直結しておおよそ1Aが流れるくらい、すなわち10Ωくらいの抵抗。で、この抵抗がめっちゃめちゃ発熱するので、金属板に熱伝導シールで貼り付けてあります。
これでどーするかというと、
- 負荷出力OFF状態で、バッテリの開放電圧を測定
- 負荷出力をONに遷移させて、バッテリの両端電圧と電流を測定
- 開放電圧と、ON時電圧・電流からバッテリの内部抵抗を計算
- 負荷出力をONにしたまま、一定時間おきに電圧・電流値を測定
- 電圧が11Vに達した時点で負荷出力をOFFし、時間を計測
- 記録した電流・電圧からAh値を計算
まぁ、やってることは、ぜーんぜん大したことなくて、手動でもできるんですが、Pythonスクリプトでやったら楽だなってことで、PI にやってもらいます。
でまぁ、測定結果はこんな感じ
Ah | 内部抵抗 | |
オムロン 新品バッテリ |
6.15 |
0.124 |
UPS1号機から外したバッテリ | 3.37 | 0.152 |
UPS1号機から2回目に外したバッテリ | 6.68 | 0.138 |
UPS2号機から外したバッテリ | 5.88 | 0.111 |
6年前にUPSから外したバッテリ | 0.11 | 0.261 |
長期放置したバッテリは容量スカスカになってますが、交換で外したばかりのバッテリ、 全然劣化してるように見えないんですが・・・・・・?
内部抵抗も、新品と、交換したてバッテリ2個でほとんど変わらない。
数字じゃわかりにくいので、グラフにしてみよう。
右下の3個の測定点の違いが判らない・・・・・新品より容量が大きいのもあれば、内部抵抗が小さいのもある。
これ、UPSのバッテリ診断を信用していいんか・・・・?
最後におまけ。
測定スクリプトも載せておきましょう
#coding: utf-8
import io
import sys
import smbus
import time
import locale
import psycopg2
import struct
import RPi.GPIO as GPIO
bus_number = 1
args = sys.argv
i2c_addr = 0x47
interval = 5
lowlimit = 11.0
bus = smbus.SMBus(bus_number)
def writeReg(reg_addr , data):
bus.write_word_data(i2c_addr , reg_addr , data)
class INA226:
vol = 0
amp = 0
def __init__(self):
writeReg(0x05 ,0x000a)
time.sleep(1)
def readData(self):
val = bus.read_word_data(i2c_addr , 0x02)
val = struct.unpack(">H" , struct.pack("<H" , val))[0]
self.vol = val * 1.25 / 1000
val = bus.read_word_data(i2c_addr , 0x04)
val = struct.unpack(">h" , struct.pack("<H" , val))[0]
amp = val
self.amp = val / 1000.0
#print "Voltage %0.3f (V)" % (vol)
#print "Current %0.3f (A)" % (amp)
def DBwrite():
item = pg_con.cursor()
item.execute("BEGIN;")
SQL = "LOCK TABLE %s IN ACCESS EXCLUSIVE MODE;" % (table)
item.execute(SQL)
SQL = "SELECT max(\"id\") FROM %s;" % (table)
item.execute(SQL)
itemRes = item.fetchone()
newid = int(itemRes[0]) + 1
SQL = "INSERT INTO %s " % (table)
SQL += "(\"id\" , \"date\" , \"sensor_id\" , \"voltage\" , \"current\") "
SQL += "VALUES('%d' , now() , '%d' , " % (newid , sensor_id)
SQL += "'%7.3f' , '%7.4f') ;" % (vol , amp)
item.execute(SQL)
item.execute("COMMIT;")
def setup():
GPIO.setmode(GPIO.BCM)
GPIO.setup(14 , GPIO.OUT)
GPIO.output(14 , 0)
ina226 = INA226()
setup()
ina226 = INA226()
def InterImp():
ina226.readData()
volOff = ina226.vol
GPIO.output(14,1)
time.sleep(0.1)
ina226.readData()
GPIO.output(14,0)
vol = ina226.vol
amp = ina226.amp
imp = (volOff - vol) / amp
print "Open Voltage %0.3f (V)" % volOff
print "Inter impedance %0.3f (OHM)" % imp
time.sleep(1)
def Discharge():
past = 0
print "\"time\",\"Voltage\",\"Cirrent\""
GPIO.output(14,1)
time.sleep(0.1)
while(1):
ina226.readData()
vol = ina226.vol
amp = ina226.amp
print "%d,%0.3f,%0.3f" % (past , vol , amp)
if(vol < lowlimit):
GPIO.output(14,0)
print "Discharge time %d (sec)" % past
return;
time.sleep(interval)
past += interval
if __name__ == '__main__':
InterImp()
Discharge()
PIからの接続は、このスクリプトからリバースエンジニアリングしてください(をひ
使ってるのは、スクリプトからもわかる通り、INA226のモジュールです。このモジュールをPI から叩きたい方も、サンプルにどーぞ
コメントする