背景
INA226とは、電圧電流が測定できるICチップです。INA226を利用するにあたり、自分が使いやすいと思うライブラリが見当たらなかったので、INA226_asukiaaaというライブラリを作ってみました。
手軽にINA226を使う人が増えると良いと思うので、使い方を共有します。
使ったもの
- Arduinoにプログラムを書き込めるPC
ArduinoIDEかPlatformIOをインストールしてください。 - INA226モジュール
ストロベリーリナックスで2mΩの抵抗が実装されて20Aを計測できるモジュールや100Aを計測できる外部抵抗と測定回路が絶縁された基板のセットを買えます。
aliexpressでも0.1Ωが実装されたモジュールを買えます。 - Arduino
この記事ではArduino Leonardoの互換機としても動かせるProMicroを利用します。 - ブレッドボード
はんだ付けせずに部品から信号線を引き出せる部品です。 - ジャンパワイヤ
ブレッドボードと組み合わせて、はんだ付けせずに信号線を接続できる部品です。 - 10kΩ 抵抗
I2Cのpull upに2本利用します。 - 動作確認用として100Ω抵抗 + ワニ口クリップ
確認用の回路作りに利用します。
組み立て+配線
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.25100Aを流せる抵抗の側面にも抵抗値を計算するための情報が書かれていたので、写真を追加しました。
2019.11.02
VSSは電源のマイナス側を意味していたので、VSSと表記していたところをVDDに置き換えました。
ライブラリもバージョン1.1.0からVDD形式にしました。
2019.11.29
platformioの設定ファイルを「platformio.ino」と間違えていたので、「platformio.ini」 に修正しました。
2021.02.17
抵抗の英単語resistorをresisterと間違えていたので、ライブラリと合わせて修正しました。
はじめまして。
返信削除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);
}
////
はい、提示されたコードの下記の行のように定義する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
ほぼ動くであろうコードを書かれているので「これを試してみたが動かなかった」という形式の質問の方が、質問回数が減りそうで嬉しいです。
回答ありがとうございます。
返信削除スミマセン、手元にまだINA226がなくて、先に質問してしまいました。
後日、試して報告します。
お世話になります。
削除無事、3つのINA226センサーを1つのArduinoから制御できました。
ありがとうございました。
報告ありがとうございます。
削除成功されたようで良かったです。
自分で一からプログラムを作らなくて良いので助かります。
返信削除自作してる追尾式太陽電池の出力データを取るのに使わせて頂きます。
記事とプログラムが役に立ったようで良かったです。
削除