電流・電圧センサー(INA219モジュール)とArduinoで使って電流・電圧の測定を行ってみました。
今回はINA219モジュールの使い方とその精度を確認です。
概要
INA219(モジュール)は電流・電圧の測定(モニター)が可能なデバイスで、I2C通信で情報のやり取りを行うためArduinoやRaspberryPiなどから簡単に使えて、電流計や電圧計なども割と簡単に作成できるかと思います。
▼INA219モジュール▼
ライブラリが公開されているため、それをそのまま利用すれば簡単ですが、いつものようにライブラリは使わずに電圧・電流を測定したいと思います。
回路
▼ArduinoとINA219▼
INA219とArduinoの結線です。電流・電圧測定はVin+、Vin-ピンを使って、測定する回路に直列で繋ぎます。
ここではArduino(3.3v)から抵抗を経由する回路の電圧・電流を測定。±で測定できるので、Vin+、Vin-の極性は意識しないでも問題ないはずです。負荷には適当な抵抗を使用。
▼ブレッドボードで結線▼
スケッチ(ソース)
ソースを抜粋して説明します。今回使用したソース全体は記事最後に掲載してます。(ArduinoでI2C通信を使う方法はこちら)
▼コンフィグの設定▼
int16_t config_value = 0x399F; //デフォルト Wire.beginTransmission(0x40); //デバイスアドレス Wire.write(0x00); //configアドレス Wire.write((config_value >> 8) & 0xFF); Wire.write(config_value & 0xFF); Wire.endTransmission();
今回はデフォルトのままです。BUS電圧レンジ±32V(LSB4mV)、シャント抵抗間電圧レンジ320mV(ゲイン/8)、±2A、12bit。
▼BUS電圧の測定▼
Wire.beginTransmission(0x40); //デバイスアドレス Wire.write(0x02); //BusVoltageレジスタ Wire.endTransmission(); Wire.requestFrom(0x40, 16); while (Wire.available() < 16); BusVoltage = Wire.read() << 8 | Wire.read(); BusVoltage = (BusVoltage >> 3) * 4;
電圧測定値は「0x02」アドレスから2byte分で格納されてます。上位12bitが電圧で、LSBは4mVとなります。ので最後に右3シフトして4掛けてます。
▼電流(シャント抵抗間の電圧)の測定▼
Wire.beginTransmission(0x40); //デバイスアドレス Wire.write(0x01); //ShuntVoltageレジスタ Wire.endTransmission(); Wire.requestFrom(0x40, 16); while (Wire.available() < 16); ShuntVoltage = Wire.read() << 8 | Wire.read();
シャント抵抗間の電圧測定です。「0x01」アドレスから2byte分でLSBは0.01mVとなります。今回はシャント抵抗間の電圧から電流を計算する方法で電流値を測定してます。
電圧を測定するだけなら非常に簡単です。
そのほか、アドレス「0x04」から電流、アドレス「0x03」から電力を直接計測できるのですが、アドレス「0x05」のキャリブレーション設定とLSBの考え方が若干ややこしいので今回は使用してません。電流も電力も計算で求められるので問題ないかと・・・。ここら辺のより詳しい内容はデータシート参照ください。
精度確認
電圧と抵抗値を少しずつ変えて、電圧、電流の測定を行ってみました。
▼シリアルモニタでの計測結果表示▼
▼精度確認結果▼
電流は机上計算(理論値)と比較してます。手持ちの抵抗があまりなかったので微妙なN数ですが、まぁ概ね計算通りの結果です。
私が使用する用途くらいであれば十分な精度で電圧、電流が測定できます。Arduinoからであればリアルタイムに測定できますし、いろいろ遊べそうです。
▼ソース全体▼
今回のテスト測定に使用したソース全文です。
#include <Wire.h> int16_t BusVoltage, ShuntVoltage; void setup() { Serial.begin(115200); Wire.begin(); Wire.setClock(400000); int16_t config_value = 0x399F; //デフォルト Wire.beginTransmission(0x40); //デバイスアドレス Wire.write(0x00); //configアドレス Wire.write((config_value >> 8) & 0xFF); Wire.write(config_value & 0xFF); Wire.endTransmission(); } void loop() { //Get BusVoltage Wire.beginTransmission(0x40); //デバイスアドレス Wire.write(0x02); //BusVoltageレジスタ Wire.endTransmission(); Wire.requestFrom(0x40, 16); while (Wire.available() < 16); BusVoltage = Wire.read() << 8 | Wire.read(); BusVoltage = (BusVoltage >> 3) * 4; //Get ShuntVoltage Wire.beginTransmission(0x40); //デバイスアドレス Wire.write(0x01); //ShuntVoltageレジスタ Wire.endTransmission(); Wire.requestFrom(0x40, 16); while (Wire.available() < 16); ShuntVoltage = Wire.read() << 8 | Wire.read(); Serial.print("BusVoltage"); Serial.print(BusVoltage * 0.001); Serial.print("V"); Serial.print(" "); Serial.print("ShuntVoltage"); Serial.print(ShuntVoltage * 0.01); Serial.print("mV"); Serial.println(" "); }
コメント
はじめまして。参考にさせていただいたのですが動かなかったので良かったら質問させてください。
startのみ表示されてハングします。
同じように配線して、vin voutは未結線(結線しても同じですが)
void setup() {
Serial.begin(115200);
Wire.begin();
Wire.setClock(400000);
int16_t config_value = 0x399F; //デフォルト
Wire.beginTransmission(0x40); //デバイスアドレス
Wire.write(0x00); //configアドレス
Wire.write((config_value >> 8) & 0xFF);
Wire.write(config_value & 0xFF);
Serial.println(”A”);
Wire.endTransmission();
Serial.println(”B”);
}
上記のように変更してみたところ、Aだけが表示されます。
SCLの線を抜くと動き出しますが、当然計測結果は取れないので意味がありません。
INA219を新しいものに変えたり、Arduinoも新品に変えましたが同じ結果です。
何が悪いのでしょうか?
ともださん。サイト拝見くださり有難う御座います。
ご質問の件、原因はよくわからないのですが、Serial.を間に入れるのを一度やめてみて試してみてはどうでしょうか。
Wire.endTransmission();で一度I2Cの送信を完了させるとか、サンプルスケッチ等で動くか確認してみたり、、ハード・ソフト両面から問題の切り分けをしてみてはいかがでしょうか。
色々試行錯誤して自己解決しました。
止まるのはIna219故障のため
Voltが計測できなかったのは、
Vin+の手前に抵抗を入れていた為(Vin-とGNDの間に変更)で取れました
最終的にこちらの回路図みててピンときました。
無計測状態で電圧が0Vにならないのですが、そこはまぁ何とかなりそうなので無視します。
ありがとうございました。