Raspberry Pi Pico(d_23)INA219 双方向電流センサ
INA219 DC Current Monitor (I2C)
INA219は双方向電流/電力モニタです。I2C通信で制御します。INA219モジュールのシャント抵抗は0.1Ω(R100)です。プログラムゲイン(PGA)を±320mVにすれば3.2Aまでの測定できます。Raspberry Pi PicoでINA219モジュールの動作確認をしました。
※micro:bitの記事e_45からRaspberry Pi Picoで使えるように追記、修正等をしました。
外観
INA219モジュールの外観写真です。(以後はINA219と記載します)
Vin+とVin-間にR100(0.1Ω)のシャント抵抗(Rsh)が搭載されています。この電圧をAD変換して電流値を測ります。
INA219モジュールのプリントパターンA0やA1をはんだで接続(電源電圧になる)させることで、INA219のスレーブアドレスを変更できます。
写真のままの開放状態なら0x40、A0なら0x41、A1なら0x44、A0とA1両方なら0x45になります。詳細はINA219のデータシートを参照ください。
接続例
INA219の電源電圧は2.7V~5.5VなのでRaspberry Pi Picoと接続できます。
I2C通信にはI2C1のSDA(GP10)SCL(GP11)を使いました。電流測定動作を確認するために、外部電源5Vに負荷抵抗1.5kΩを接続しています。
接続出来たらI2Cデバイスのスレーブアドレスを調べてみます。
ThonnyのShellで確認しました。
INA219のスレーブアドレスは以下のように64(0x40)でした。
>>> from machine import I2C,Pin
>>> i2c = I2C(1, scl=Pin(11), sda=Pin(10), freq=400_000)
>>> i2c.scan()
[64]
>>>
INA219の説明
データシートから抜粋してINA219の説明します。
INA219のレジスタは下図のように0x00~0x05にConfiguration、Shunt Voltage、Bus Voltage、Power、Current、Calibration名のレジスタがあります。
Configuration RegisterはBus Voltage RangeやPGA(gain and range)、ADC Settings、Operating Modeを設定します。
デフォルト値は0x399fで、バス電圧~32V、GAIN/8 Range±320 mV、ADCは12 bit、Modeはcontinuousです。
ADC Settingsには2~128サンプリング平均の設定もあります。※詳細はデータシートを参照ください。
リセットすると、Configurationはデフォルトの設定(0x399f)になります。Power、Current、Calibrationのレジスタは消去されます。そのため、リセット後はCalibration値の書き込みが必要です。
※ TIのINA219データシートから抜粋
Calibration値は以下の式で計算します。
データシートのTypical Applicationに、R SHUNT = 2 mΩ、Maximum expected load current = 15 Aの例があります。
Current LSBを計算すると
>>> 15/(2**15)*10**6
457.7637
Current LSB=457.78 µA/bitとなるのですが、例ではround upして1mA/bitになっています。
そのため、
Cal=0.04096/(1mAx2mΩ)=0.04096/(1/1000*2/1000)=20480(‘0x5000’)となり、Calibration Registerには’0x5000’を設定しています。
※ TIのINA219データシートから抜粋
Current Registerの値は下式(4)で算出されます。
電流値はCurrent RegisterにCurrent LSBを掛けて算出するので、Current LSB値を大きく丸めても大丈夫なようです。
ちなみに、Current LSB=458で計算すると、Cal=44716’0xaeac’になります。この数値を書込んでも問題ないと思います。
Shunt voltage、Bus voltageは各レジスタ値に、各々10uV、4mVを掛け算して算出します。
Shunt voltage = Shunt voltage Register x 10uV
Bus voltage = Bus voltage Register x 4mV
Shunt Voltage RegisterはPGAの設定によって符号ビットが変わります。
例えば、PGA = /8なら16bit符号付きデータ、PGA = /1なら13bit符号付きデータになります。
Bus Voltage Registerは[3:15]の13bitデータになります。
Powerは(3)式のPower_LSBをPowerレジスタ値に掛け算して算出します。
※その他の詳細はデータシートを参照ください。
※TIのデータシートより抜粋
スクリプト
INA219のスクリプトは以下のようにしました。
configurationをデフォルト(0x399f)の設定からバス電圧レンジを16Vに変更し0x199fで設定しました。
Calibrationなどはmax_expect_current=1.5A、Rsh=0.1Ωで計算しています。
以下の値や測定値を表示しています。
configurationの値を表示
Shunt Voltageの符号ビット
Shunt Voltage
Bus Voltage
Shunt Voltage + Bus Voltage
current(I)
power
I^2*R
リセット後のconfiguration
current
リセット解除後のconfiguration
current
※開発環境はThonnyです。ThonnyでMicroPythonをRaspberry Pi Pico with RP2040にインストールして使っています。
※Raspberry Pi Pico単独で動作させるには’main.py’としてRaspberry Pi Picoにuploadして使います。
pico_INA219_test_02b.py
#!/usr/bin/env python
# -*- coding: utf-8 -*
from machine import I2C,Pin
import time
# INA219 current power monitor
#slave address hex(64)='0x40' A1,A0=0,0
i2c = I2C(1, scl=Pin(11), sda=Pin(10), freq=400_000)
addr=0x40
# register map 各レジスタのアドレス
Cfg=0x00 # configuration R/W 設定が必要
Vsh=0x01 # shunt voltage R signed
Vbs=0x02 # bus voltage R [3:15] 13bit 読出し注意
Pow=0x03 # power R
Cur=0x04 # current R signed
Cal=0x05 # calibration R/W 設定が必要
Vsh_LSB=10*10**-6 #Shunt voltage LSB 10uV fixed
Bus_LSB= 4*10**-3 #Bus voltage LSB 4mV fixed
# Input Data
# MaxCurrent Rsh-ohm
IMAX=1.5 # max_expect_current
Rsh=0.1 # shunt register ohm
# config set data
RST='0'
BRNG='0' # 16V(0)32V(1)
PGA='11' # PG1|PG0 ±40mV(00)80mV(01)160mV(10)320mV(11) program gain
BADC='0011' # default 12bit 532us(0011) 8times(1011)16times(1100)128times(1111)
SADC='0011' # default 12bit 532us(0011)
MODE='111' # Shunt&Bus-continue(111) triggered(011) Power-down(000)
config='0b'+RST+'0'+BRNG+PGA+BADC+SADC+MODE
config=int(config)
print('{:#018b}'.format(config),hex(config))
#config=0x399F #0b_0011_1001_1001_1111 R/W 32V Default
#config=0x199f #0b_0001_1001_1001_1111 R/W 16V
#config=0x1ddf #0b_0001_1101_1101_1111 R/W 16V 8samples ave
# PGの値から符号ビットを特定する
PG='0b'+PGA
s_bit=int(PG)+13
print('Vsh_SIGN_bit=',s_bit)
# Calc
Cur_LSB=IMAX/2**15 #(2)式
Pow_LSB=20*Cur_LSB #(3)式
CAL=int(0.04096/(Cur_LSB*Rsh)) #(1)式
# read register
def r_reg(reg):
buf=bytearray(1)
buf[0]=reg
i2c.writeto(addr,buf)
r_dat=i2c.readfrom(addr,2) # |MSB|LSB| 2byte
# 8bit*2 >> 16bit
dat=r_dat[0]<<8 | r_dat[1] # 2bytes 16bitデータにする
return dat
# 符号計算
def sig(dat,num):
if dat >= (2**(num-1)):
dat=dat-(2**num)
return dat
# write register
def w_reg(reg,dat):
buf=bytearray(3) # pointer MSByte LSByte の3bytes
buf[0]=reg
buf[1]=(dat>>8 & 0xff) # MSB 16bit wo shift site 8bit
buf[2]=(dat & 0xff) # LSB
#print('w_reg=',hex(pointer),hex(dat),buf)
i2c.writeto(addr,buf)
time.sleep_us(10)
# config-regi data
def read_Cfg():
r_dat=r_reg(Cfg)
d_PRN(r_dat)
# 16bit bin format
def d_PRN(dat):
print('{:#018b}'.format(dat),hex(dat))
# RST: Reset Bit
def RST_set(RST='0'):
global config
RST='0b'+RST
config=(config & 0x7fff)| (int(RST) <<15) #reset bit change
w_reg(Cfg,config)
# calibrate set リセット後は必要
w_reg(Cal,CAL)
time.sleep_ms(10)
return config
## main
# config set
w_reg(Cfg,config)
# calibrate set
w_reg(Cal,CAL)
# シャント電圧測定 シャント電圧レジスタ*10uV
vsh=sig(r_reg(Vsh),s_bit)*Vsh_LSB*10**6 # uA signed PGA/?bit
print('Vsh(uV)=',vsh)
# バス電圧測定 バス電圧レジスタ*4mV
vbs=(r_reg(Vbs)>>3)*Bus_LSB*1000 # mV Vbs 13bit
print('Vbus(mV)=',vbs)
## calculation
# 電源電圧算出
vcc=(vsh/1000) + vbs
print('Vcc=Vsh+Vbs(mV)=',vcc)
# 電流値算出 current reg*Cur_LSB
cur=sig(r_reg(Cur),16)*Cur_LSB*1000 # mA signed 16bit
print('I(mA)=',cur)
# 電力算出 パワーレジスタ*Pow_LSB
pow=(r_reg(Pow))*Pow_LSB*1000 # mW
print('Pow(mW)=',pow)
# 電力を別計算してみるI^2*R
mW=(cur/1000)**2*1500*1000 # W=I^2R R_load=1.5k
print('I^2R mW=',mW)
# Reset 動作を確認
print('')
print('RST-1 リセット')
dat=RST_set('1')
read_Cfg()
# 電流値算出
cur=sig(r_reg(Cur),16)*Cur_LSB*1000 # mA signed 16bit
print('I(mA)=',cur)
print('RST-0 解除')
dat=RST_set('0')
read_Cfg()
# 電流値算出
cur=sig(r_reg(Cur),16)*Cur_LSB*1000 # mA signed 16bit
print('I(mA)=',cur)
関数 部分説明
■Configuration Registerに設定する値は、BRNG=’0’等をセットして
config=’0b’+RST+’0’+BRNG+PGA+BADC+SADC+MODE
config=int(config)
で与えています。
■PGの値からShunt Voltage Registerの符号ビットを
PG=’0b’+PGA
s_bit=int(PG)+13
で決めています。
■sig(dat,num)
符号計算値を返します。
dat:符号計算をするデータ
num:ビット数
■w_reg(reg,dat)
registerに2バイトデータを書き込みます。
reg:registerのアドレス
dat:書き込む2bytes(16bit)データ
■r_reg(reg)
registerの値を返します。2bytesデータです。
reg:registerのアドレス
■read_Cfg()
Configuration Registerの値を表示します。
■RST_set(RST=’0′)
Configuration Registerのリセットビットを操作します。
‘1’でリセットします。’0’で解除します。
実行結果
結果は以下のようになりました。※Thonnyのshellに表示されます。
電圧5V、負荷1.5kΩの電流を測定しました。測定できているようです。
リセット動作も確認できました。
>>> %Run -c $EDITOR_CONTENT
0b0001100110011111 0x199f # configuration値
Vsh_SIGN_bit= 16 # 符号ビット
Vsh(uV)= 310.0001 # Shunt Voltage
Vbus(mV)= 4904.001 # Bus Voltage
Vcc=Vsh+Vbs(mV)= 5214.0 # Shunt Voltage + Bus Voltage
I(mA)= 3.387451 # current 5V/1.5kΩ = 3.33mA
Pow(mW)= 16.47949 # power
I^2R mW= 17.21224 # power
RST-1 リセット
0b0011100110011111 0x399f # リセットでデフォルトに戻る
I(mA)= 3.02124
RST-0 解除
0b0001100110011111 0x199f # 設定値に戻る
I(mA)= 3.112793
>>>
まとめ
Raspberry Pi PicoでINA219を使ってD/A変換ができました。