稼働中

マイクロビット(e_45)INA219 双方向電流センサー

INA219 (I2C)

INA219は双方向電流/電力モニタです。I2C通信で制御できます。
INA219モジュールをmicro:bitで使ってみました。
使用したINA219モジュールのシャント抵抗は0.1Ω(R100)です。プログラムゲイン(PGA)を±320mVにすれば3.2Aまでの測定レンジになります。

外観

INA219モジュールの外観写真とピン配置です。Vin+とVin-間にR100(0.1Ω)のシャント抵抗(Rsh)が搭載されています。この電圧を測定して電流値を測ることになります。
INA219モジュールのプリントパターンA0やA1をはんだ接続するとA0やA1が電源電圧になり、INA219のスレーブアドレスを変更できます。
写真のままの開放状態なら0x40、A0なら0x41、A1なら0x44、A0とA1両方なら0x45になります。
※詳細はデータを参照ください。
INA219モジュール

接続例

INA219の電源電圧は3.0V~5.5Vなのでmicro:bitの電源が使えます。負荷に1.5kΩの抵抗を使いました。外部電源に1.5kΩ+Rsh(0.1Ω)=1500.1Ωが接続されたようになります。
接続例
※micro:bitのピン配置図は「https://tech.microbit.org/hardware/edgeconnector/」からの引用です。

実体接続した写真です。
実体図

INA219のレジスタ

INA219のレジスタは下図のように0x00~0x05にConfiguration、Shunt Voltage、Bus Voltage、Power、Current、Calibration名のレジスタがあります。
データシートをみると、Configuration、Calibrationのレジスタは書込み可能です。何らかの設定が必要なようです。
INA219_Register
※TIのデータシートより抜粋して、赤枠を追記

Configuration RegisterはBus Voltage RangeやPGA(gain and range)、ADC Settings、Operating Modeを設定します。
デフォルト値は0x399Fで、バス電圧~32V、GAIN/8 Range±320 mV、ADCは12 bitでConversion Timeが532 μsになります。ADC Settingsには2~128サンプリング平均の設定もあります。※詳細はデータシートを参照ください。

Calibration Registerには下式Calで得られる値を書込みます。
計算式
※TIのデータシートより抜粋

データシートの「Typical Application」に、
R SHUNT = 2 mΩ
Maximum expected load current = 15 A 
の例があります。
計算すると、Current LSB=457.78 µA/bitとなるのですが、例ではround upして1mA/bitで計算しています。
その結果、Cal=0.04096/(1/1000*2/1000)=20480 (‘0x5000’)となり、Calibration Registerには’0x5000’を書込むようになっています。
電流値は下式(4)で算出されるCurrent RegisterにCurrent LSBを掛けて算出するので大きく丸めても辻褄が合うようです。Current LSB=458で計算すると、Cal=44716 (‘0xaeac’)になります。この数値を書込んでも問題ないです。

そのため、測定するにはCalibration Registerにデータ書込みが必須です。
計算式
※TIのデータシートより抜粋

Shunt voltageはLSB値が10uV、Bus voltageはLSB値が4mVと固定値です。各々のレジスタ値を読出して掛け算すれば算出できます。

Powerは(3)式のPower_LSBをPowerレジスタ値に掛け算して算出します。
Powerレジスタ
※TIのデータシートより抜粋

Shunt Voltage RegisterはPGAの設定によって符号ビットが変わります。
例えば、PGA = /8なら16bit符号付きデータ、PGA = /1なら13bit符号付きデータになります。
Bus Voltage Registerは[3:15]の13bitがデータになります。
※他の詳細はデータシートを参照ください。

スクリプト

Configuration 設定値を得るスクリプトと電流などの測定値を得るスクリプトとを分けて作成しました。
※thonny-microbitのMicroPythonを使っています。

Configuration用


# ina219のconfigデータの生成だけ
def conf_dat(d_BRNG='1',d_PGA='11',d_BADC='0011',d_SADC='0011'):
        # config set data (default 0x399F)
        RST='0'
        BRNG=d_BRNG  # 16V(0)32V(1)
        PGA=d_PGA    # PG1|PG0  ±40mV(00)80mV(01)160mV(10)320mV(11)
        BADC=d_BADC  # 12bit(0011) 8times(1011)16times(1100)128times(1111)
        SADC=d_SADC  # 12bit(0011)
        MODE='111'   # Shunt&Bus-continue Power-down(000)triggered(011)
        config='0b'+RST+'0'+BRNG+PGA+BADC+SADC+MODE
        config=int(config)

        # ShuntVoltage signed bit
        PGA='0b'+PGA
        s_bit=int(PGA)+13
        
        return config,s_bit

conf_dat(d_BRNG='1',d_PGA='11',d_BADC='0011',d_SADC='0011')
print('config=',hex(config),'s_bit=',s_bit)

実行結果
conf_dat(d_BRNG=’1′,d_PGA=’11’,d_BADC=’0011′,d_SADC=’0011′) # default値


>>> %Run ina219_conf_b.py
config= 0x399f s_bit= 16        #Bus 32V,±320mV,12bit

conf_dat(d_BRNG=’0′,d_PGA=’11’,d_BADC=’1011′,d_SADC=’1011′)


>>> %Run ina219_conf_b.py
config= 0x1ddf s_bit= 16        #Bus 16V,±320mV,12bit 8samples ave

電流等の測定用

Configuration Register設定値は先に算出した 0x1ddfとし、Shunt Voltage Registerの符号ビットはs_bit= 16としました。
Max_expect_currentは1.5Aとしました。


from microbit import i2c
# read register
def r_reg(reg):
    buf=bytearray(1)
    buf[0]=reg
    i2c.write(addr,buf)
    r_dat=i2c.read(addr,2)          # MSByte(0)LSByte(1)の2byte
    # 8bit*2>>16bit
    dat=r_dat[0]<<8 | r_dat[1] # 2bytes 16bitデータにする 
  return dat

# signed data 符号付き計算
def sig(dat,num):
    if dat >= (2**(num-1)):
        dat=dat-(2**num)
    return dat

# regi-pointer,dat(16bit= msb,lsb 8bit)
def w_reg(pointer,dat):
    buf=bytearray(3)        # pointer MSByte LSByte の3bytes
    buf[0]=pointer
    buf[1]=(dat>>8 & 0xff)  # MSB
    buf[2]=(dat & 0xff)           # LSB
    i2c.write(addr,buf)

#i2c.init(freq=100000, sda=pin20, scl=pin19)
i2c.init()

## Const
#slave address A1(GND)A0(GND)
addr=0x40  
# config setting ina219_conf_b.pyで算出
s_bit= 16
config= 0x1ddf # 16V 8samples ave  default= 0x399F

Vsh_LSB=10*10**-6   #Shunt voltage LSB 10uV fixed
Bus_LSB= 4*10**-3   #Bus   voltage LSB 4mV  fixed

# Input Data
IMAX=1.5   # max_expect_current
Rsh=0.1    # shunt register ohm
# Calc
Cur_LSB=IMAX/2**15
Pow_LSB=20*Cur_LSB
CAL=int(0.04096/(Cur_LSB*Rsh))

# 0x00 config-regi setting
w_reg(0x00,config)

# 0x05 calibrate-regi setting
w_reg(0x05,CAL)

# 各種計算
# 電流値測定 current reg*Cur_LSB
# 0x04 current-regi
cur=sig(r_reg(0x04),16)*Cur_LSB*1000        # mA signed 16bit
print('I(mA)=',cur)

# シャント電圧測定 シャント電圧レジスタ*10uV
# 0x01 # shunt voltage-regi
vsh=sig(r_reg(0x01),s_bit)*Vsh_LSB*10**6    # uA signed  PGA/?bit
print('Vsh(uV)=',vsh)

# バス電圧測定 バス電圧レジスタ*4mV
# 0x02 # bus voltage-regi   読出し注意13bit[3:15] 
vbs=(r_reg(0x02)>>3)*Bus_LSB*1000    # mV Vbs 13bit
print('Vbs(mV)=',vbs)

# Vccの検算
vcc=(vsh/1000) + vbs
print('Vcc=Vsh+Vbs(mV)=',vcc)

# 電力測定 パワーレジスタ*Pow_LSB
# 0x03 power-regi
pow=(r_reg(0x03))*Pow_LSB*1000  # mW
print('Pow(mW)=',pow)

実行結果
外部電源 10V、負荷1.5kΩで測定しました。


>>> %Run ina219_mesu_b.py
I(mA)= 6.50024              # 10V/1500.1Ω ≒ 6.666mA
Vsh(uV)= 649.999
Vbs(mV)= 9728.0
Vcc=Vsh+Vbs(mV)= 10378.0    # 10V
Pow(mW)= 63.1714
>>>

外部電源 15V、負荷1.5kΩで測定しました。


>>> %Run ina219_mesu_b.py
I(mA)= 9.8877 # 15V/1500.1Ω ≒ 9.999mA
Vsh(uV)= 989.999
Vbs(mV)= 14720.0
Pow(mW)= 145.569
>>>

ほぼ正確に電流測定が出来ていると思います。
ちなみに、Max_expect_currentを0.2Aに下げると異常な測定値になりました。
Cur_LSB = 0.2/(2**15)=6.10352(uA/bit) が小さくなり過ぎるからでしょうか?

まとめ

micro:bitでINA219モジュールを使って電流などの測定が出来ました。