2019年10月20日日曜日

電流電圧測定チップINA226をArduinoでライブラリを通して使う方法


背景

INA226とは、電圧電流が測定できるICチップです。

INA226を利用するにあたり、自分が使いやすいと思うライブラリが見当たらなかったので、INA226_asukiaaaというライブラリを作ってみました。
手軽にINA226を使う人が増えると良いと思うので、使い方を共有します。

使ったもの


組み立て+配線

INA226はA0とA1に接続する信号線を変えることでデバイスのアドレスを変えられます。
今回はA0とA1共にGNDに接続します。


Arduinoの電源とI2Cの通信線をINA226に接続します。

INA226モジュール 接続先
VDD (VS) ProMicroのVCC
GND ProMicroのGND
SDA ProMicroのD2(SDA) + VCCにプルアップ
SCL ProMicroのD3(SCL) + VCCにプルアップ
PDIS
(絶縁式のモジュールのみ)
GNDに接続するとモジュールが動作します
ALERT 未接続
V+ ProMicroのVCC
V- ProMicroのGND
ISENSE+ ProMicroのVCC
ISENSE- 電流量を測定したい負荷装置に電力を供給
今回は100Ωを経由してProMicroのGND

今回利用するモジュールはI2Cのプルアップ抵抗が無いものなので、I2Cの通信線を4.7~10kΩの抵抗でプルアップします。
ストロベリーリナックスで売られているモジュールは、絶縁版と絶縁されてない版でピンの配置が異なるので、どちらも同時に利用する場合は注意が必要です。

絶縁されてない版をpull up


絶縁版をpull up


動作確認用に100Ω抵抗に5Vを供給する回路を作り、その電流量を計測します。
100Ωの抵抗が無かったので、300Ωの抵抗3つを並列にして100Ωを作っています。


それぞれ接続するとこうなりました。

2mΩが実装された版


100Aを流せる外部抵抗版


ライブラリをインストール

INA226_asukiaaaをインストールしてください。

ArduinoIDEの場合はライブラリマネージャーからインストールできます。


PlatformIOの場合は、platormio.inoの依存ライブラリに情報を追加してください。
platformio.ini
lib_deps = INA226_asukiaaa

プログラムの説明

記事を書いている時点でのサンプルプログラムはこちらです。
ArduinoIDEの場合は、ファイル -> スケッチ例 -> INA226_asukiaaa -> printVoltageAndCurrent を選ぶと開けます。
#include <INA226_asukiaaa.h>

const uint16_t ina226calib = INA226_asukiaaa::calcCalibByResistorMilliOhm(2); // Max 5120 milli ohm
// const uint16_t ina226calib = INA226_asukiaaa::calcCalibByResistorMicroOhm(2000);
INA226_asukiaaa voltCurrMeter(INA226_ASUKIAAA_ADDR_A0_GND_A1_GND, ina226calib);

void setup() {
  Serial.begin(115200);

  // Wire2.begin(25, 26);
  // voltCurrMeter.setWire(&Wire2);

  if (voltCurrMeter.begin() != 0) {
    Serial.println("Failed to begin INA226");
  }
}

void loop() {
  int16_t ma, mv, mw;
  if (voltCurrMeter.readMV(&mv) == 0) {
    Serial.println(String(mv) + "mV");
  } else {
    Serial.println("Cannot read voltage.");
  }
  if (voltCurrMeter.readMA(&ma) == 0) {
    Serial.println(String(ma) + "mA");
  } else {
    Serial.println("Cannot read current.");
  }
  if (voltCurrMeter.readMW(&mw) == 0) {
    Serial.println(String(mw) + "mW");
  } else {
    Serial.println("Cannot read watt.");
  }
  delay(1000);
}

利用する抵抗を元にcalibの値の設定

INA226には調整のための数値(以後calib)を利用して、シャント抵抗(電流計測用に設置する抵抗)の電圧を電流量に変換します。

サンプルプログラムでは2mΩの値を使う場合のプログラムになっています。
ストロベリーリナックスで売られている2mΩの抵抗が表面実装されているモジュールであれば、calibは変更せずこのまま利用できます。
const uint16_t ina226calib = INA226_asukiaaa::calcCalibByResistorMilliOhm(200); // Max 5120 milli ohm

ストロベリーリナックスで売られている外部抵抗を利用するモジュールを使う場合は、シャント抵抗によってcalibの変更が必要です。
100Aを計測できるモジュールを利用する場合、商品ページでは抵抗値について言及されていませんが抵抗の側面と説明書に「100Aで75mVが発生する」という情報があるため、抵抗値は R = V/I = 0.075/100 = 0.00075 = 750μΩとなります。


この場合、下記のように元のcalibの定義をコメントアウトしつつ、μΩの抵抗値からcalibを算出する関数を利用して750μΩの場合のcalibを算出して利用してください。
// const uint16_t ina226calib = INA226_asukiaaa::calcCalibByResistorMilliOhm(2); // Max 5120 milli ohm
const uint16_t ina226calib = INA226_asukiaaa::calcCalibByResistorMicroOhm(750);

aliexpressで売られているモジュールを利用する場合、0.1Ωの抵抗が実装されているため、下記のようにmΩからcalibを算出する関数を利用してcalibを算出して利用してください。
const uint16_t ina226calib = INA226_asukiaaa::calcCalibByResistorMilliOhm(100); // Max 5120 milli ohm

アドレスの設定

INA226はA0とA1に接続する線によってアドレスを変えられます。
サンプルプログラムはどちらもGNDを接続した場合の記述になっています。
INA226_asukiaaa voltCurrMeter(INA226_ASUKIAAA_ADDR_A0_GND_A1_GND, ina226calib);

このライブラリでは、INA226のアドレス用にこれらの値を定義しています。
#define INA226_ASUKIAAA_ADDR_A0_GND_A1_GND B1000000
#define INA226_ASUKIAAA_ADDR_A0_VDD_A1_GND B1000001
#define INA226_ASUKIAAA_ADDR_A0_SDA_A1_GND B1000010
#define INA226_ASUKIAAA_ADDR_A0_SCL_A1_GND B1000011
#define INA226_ASUKIAAA_ADDR_A0_GND_A1_VDD B1000100
#define INA226_ASUKIAAA_ADDR_A0_VDD_A1_VDD B1000101
#define INA226_ASUKIAAA_ADDR_A0_SDA_A1_VDD B1000110
#define INA226_ASUKIAAA_ADDR_A0_SCL_A1_VDD B1000111
#define INA226_ASUKIAAA_ADDR_A0_GND_A1_SDA B1001000
#define INA226_ASUKIAAA_ADDR_A0_VDD_A1_SDA B1001001
#define INA226_ASUKIAAA_ADDR_A0_SDA_A1_SDA B1001010
#define INA226_ASUKIAAA_ADDR_A0_SCL_A1_SDA B1001011
#define INA226_ASUKIAAA_ADDR_A0_GND_A1_SCL B1001100
#define INA226_ASUKIAAA_ADDR_A0_VDD_A1_SCL B1001101
#define INA226_ASUKIAAA_ADDR_A0_SDA_A1_SCL B1001110
#define INA226_ASUKIAAA_ADDR_A0_SCL_A1_SCL B1001111

aliexpressで売られているモジュールは裏側にA0とA1を電源に接続するためのパッドが用意されています。
このパッドにはんだを盛ってA0とA1を共に電源に接続した場合は、下記のように記述すればデバイスを認識できると思います。
INA226_asukiaaa voltCurrMeter(INA226_ASUKIAAA_ADDR_A0_VDD_A1_VDD, ina226calib);

Wire以外のI2Cポートを利用

Teensy、Arduino MEGA、ESP32など、複数のI2Cポートを持っているボードでWire以外のI2Cポートを利用したい場合、下記のようにINA226のbeginの前にWireをbeginしてsetWire関数に渡せば、利用するポートを変えられます。
void setup() {
  Serial.begin(115200);

  Wire2.begin();
  voltCurrMeter.setWire(&Wire2);

  if (voltCurrMeter.begin() != 0) {
    Serial.println("Failed to begin INA226");
  }
}

動作確認

2mΩが実装された版

A0とA1にはGNDを接続して、2mΩのシャント抵抗を利用するため、プログラムのcalibとアドレスは下記のように設定します。
const uint16_t ina226calib = INA226_asukiaaa::calcCalibByResistorMilliOhm(2);
INA226_asukiaaa voltCurrMeter(INA226_ASUKIAAA_ADDR_A0_GND_A1_GND, ina226calib);
テスターで電圧を測定したところ4.46VがVCCから供給されていました。


100Ωの抵抗に流れる電流量はI = V/R = 4.46/100 = 0.0446 = 44.6mAとなります。
消費電力はIV = 4.46 x 0.0446 = 0.198916 ≒ 199mWとなるはずです。
シリアル通信でProMicroから信号を受け取ると、
4455mV
43mA
200mW
となっており、ほぼ期待通りの値が表示されました。

100Aを流せる外部抵抗を利用する版

A0とA1にはGNDを接続して、100Aを流せる(100Aで75mVが発生する -> 0.075/100 = 0.00075 = 750μΩ)シャント抵抗を利用するため、プログラムのcalibとアドレスは下記のように設定します。
const uint16_t ina226calib = INA226_asukiaaa::calcCalibByResistorMicroOhm(750);
INA226_asukiaaa voltCurrMeter(INA226_ASUKIAAA_ADDR_A0_GND_A1_GND, ina226calib);
テスターで電圧を測定したところ4.39VがVCCから供給されていました。


100Ωの抵抗に流れる電流量はI = V/R = 4.39/100 = 0.0439 = 43.9mAとなります。
消費電力はIV = 4.39 x 0.0439 = 0.1927 ≒ 193mWとなるはずです。
シリアル通信でProMicroから信号を受け取ると、
4381mV
43mA
200mW
となっており、電圧と電流量はほぼ期待通り、電力量は計算単位が小さいためか約4%の誤差を含んで表示されました。

まとめ

Arduinoでライブラリを利用してINA226を動かせました。

更新履歴

2019.10.25
100Aを流せる抵抗の側面にも抵抗値を計算するための情報が書かれていたので、写真を追加しました。
2019.11.02
VSSは電源のマイナス側を意味していたので、VSSと表記していたところをVDDに置き換えました。
ライブラリもバージョン1.1.0からVDD形式にしました。
2019.11.29
platformioの設定ファイルを「platformio.ino」と間違えていたので、「platformio.ini」 に修正しました。
2021.02.17
抵抗の英単語resistorをresisterと間違えていたので、ライブラリと合わせて修正しました。

7 件のコメント :

Unknown さんのコメント...

はじめまして。
1点質問です。

下記ソースのようにしたら、2つのINA226を同時に使用できますか?

////
#include

const uint16_t ina226calib1 = INA226_asukiaaa::calcCalibByResisterMicroOhm(375); // for 200A-shunt
const uint16_t ina226calib2 = INA226_asukiaaa::calcCalibByResisterMicroOhm(750); // for 100A-shunt
INA226_asukiaaa voltCurrMeter1(INA226_ASUKIAAA_ADDR_A0_GND_A1_GND, ina226calib1); // INA226-1
INA226_asukiaaa voltCurrMeter2(INA226_ASUKIAAA_ADDR_A0_VDD_A1_GND, ina226calib2); // INA226-2

void setup() {
Serial.begin(115200);

if (voltCurrMeter1.begin() != 0) {
Serial.println("Failed to begin INA226-1");
}
if (voltCurrMeter2.begin() != 0) {
Serial.println("Failed to begin INA226-2");
}
}

void loop() {
int16_t ma, mv, mw;

if (voltCurrMeter1.readMV(&mv) == 0) {
Serial.println(String(mv) + "mV");
} else {
Serial.println("Cannot read voltage.");
}
if (voltCurrMeter1.readMA(&ma) == 0) {
Serial.println(String(ma) + "mA");
} else {
Serial.println("Cannot read current.");
}
if (voltCurrMeter1.readMW(&mw) == 0) {
Serial.println(String(mw) + "mW");
} else {
Serial.println("Cannot read watt.");
}

if (voltCurrMeter2.readMV(&mv) == 0) {
Serial.println(String(mv) + "mV");
} else {
Serial.println("Cannot read voltage.");
}
if (voltCurrMeter2.readMA(&ma) == 0) {
Serial.println(String(ma) + "mA");
} else {
Serial.println("Cannot read current.");
}
if (voltCurrMeter2.readMW(&mw) == 0) {
Serial.println(String(mw) + "mW");
} else {
Serial.println("Cannot read watt.");
}

delay(1000);
}
////


Asuki Kono さんのコメント...

はい、提示されたコードの下記の行のように定義するina226のインスタンスのアドレスを変えて利用するina226のアドレス線にもそのようにGNDかVDD(他の選択しとしてはSDAかSCL)を接続すれば、複数個(最大16個)のina226を1つのI2Cのバスに接続できます。

INA226_asukiaaa voltCurrMeter1(INA226_ASUKIAAA_ADDR_A0_GND_A1_GND, ina226calib1); // INA226-1
INA226_asukiaaa voltCurrMeter2(INA226_ASUKIAAA_ADDR_A0_VDD_A1_GND, ina226calib2); // INA226-2

現状最新版で設定可能なアドレスはここに記述してあります。
https://github.com/asukiaaa/INA226_asukiaaa/blob/1.1.2/src/INA226_asukiaaa.h#L8-L23

ほぼ動くであろうコードを書かれているので「これを試してみたが動かなかった」という形式の質問の方が、質問回数が減りそうで嬉しいです。

Unknown さんのコメント...

回答ありがとうございます。
スミマセン、手元にまだINA226がなくて、先に質問してしまいました。
後日、試して報告します。

Unknown さんのコメント...

お世話になります。

無事、3つのINA226センサーを1つのArduinoから制御できました。
ありがとうございました。

Asuki Kono さんのコメント...

報告ありがとうございます。
成功されたようで良かったです。

Tomo さんのコメント...

自分で一からプログラムを作らなくて良いので助かります。
自作してる追尾式太陽電池の出力データを取るのに使わせて頂きます。

Asuki Kono さんのコメント...

記事とプログラムが役に立ったようで良かったです。