Raspberry Pi で電流電圧センサーモジュール(INA219)の使用方法

 電流・電圧を簡単に測定することができるセンサーモジュール(INA219)をRaspberry Pi Pico(ラズパイPico)から使ってみます。

 以前、INA219をArduinoから使ったことがあるのですが、今回は同じ内容をそのままPicoでやってるだけです。Picoの開発環境はArduinoIDEを使用するため、内容はほとんどArduinoと同様になります。

スポンサーリンク

結線

 INA219モジュールとの結線方法です。

▼INA219▼

 秋月だったかAmazonだったか忘れてしまったのですが、以前入手したモジュールです。I2C通信でマイコンとやり取りします。

▼結線▼

 ブレッドボードで結線してます。

INA219 Vcc ⇔ Pico 3V3(OUT)(36pin)
INA219 Gnd ⇔ Pico Gnd(38pin)
INA219 Sda ⇔ Pico GP16(I2C0 SDA)
INA219 Scl ⇔ Pico GP17(I2C0 SCL)

▲PicoとINA219との結線。Picoの場合、I2C通信に使用するピンがある程度自由に決められます。特に意味はありませんが今回はGP16/17ピンに割り当ててます。(ブレッドボード上で近くのピンにしたかっただけです。)

▲で電流・電圧を測定したい回路にINA219のVin+、Vin-を直列に挟めば準備完了。±方向はどちらでも測定可能。電流「±」で出力されて、流れる方向がわかるようになってます。

ソース

 ラズパイPicoに書き込むソースです。部分的に切り取って解説していきます。ソース全体は記事最下段に掲載してます。開発環境はArduinoIDEを使用するため、このソースはそのままArduinoでも使えます。

#include <Wire.h>

void setup() {
  //Wire.setSDA(16);       //I2C0 SDA GP16
  //Wire.setSCL(17);       //I2C0 SCL GP17
  Wire.setClock(400000);
  Wire.begin();            //I2C0 begin

▲まず、I2C通信を開始します。Pico(earlephilhowerのライブラリを使用)の場合、ピンアサインを変更する場合はコメントアウトします。デフォルトは確かSDA:GP4ピン、SCL:GP5ピンです。Unoの場合、A4/A5ピンになります。

  int16_t config_value = 0x399F;         //INA219 デフォルト
  Wire.beginTransmission(0x40);          //INA219 デバイスアドレス
  Wire.write(0x00);                      //configアドレス
  Wire.write((config_value >> 8) & 0xFF);
  Wire.write(config_value & 0xFF);
  Wire.endTransmission();

▲次にINA219の初期設定です。BUS電圧レンジ±32V(LSB4mV)、シャント抵抗間電圧レンジ320mV(ゲイン/8)、±2A、12bitの設定です。詳しくはデーターシートをみましょう。難しければこのままおまじないと思って記述しましょう。一度実行するだけなのでsetup内の記述でOK。

  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;

▲電圧の読み取りです。読み取るたびにこの記述を行います。この記述は、[mV]となります。

  Wire.beginTransmission(0x40);                   // デバイスアドレス
  Wire.write(0x01);                               // Shuntvoltageレジスタ
  Wire.endTransmission();
  Wire.requestFrom(0x40, 16);
  while (Wire.available() < 16);
  shuntvoltage_raw = Wire.read() << 8 | Wire.read();
  current_mA       = shuntvoltage_raw * 0.1;    

▲電流値です。シャント抵抗間の電圧を測定してから電流値を計算してます。単位は、mAです。

精度確認

 適当な電圧と負荷を設定して電流値の測定精度比較をしてみます。。

▼シリアルモニタ表示▼

▼精度確認▼

電圧[mV]抵抗[Ω]電流(理論値)[mA]電流(計測)[mA]
32843309.99.9
286420143134.6
435220217206
499233015.114.7

 あまり大きな電流値で測定してませんがそれなりな精度かと・・・。

ソース全体

 今回の測定に使用したソース全文です。PICO用ですが、ピンアサインのところを修正するのみでArduino UNOでもそのまま使えます。

#include <Wire.h>

int16_t BusVoltage_mV, ShuntVoltage_raw;
float   ShuntVoltage_mV, current_mA;

void setup() {
  pinMode(25, OUTPUT);
  Serial.begin(115200);
  Wire.setSDA(16);       //I2C0 SDA GP16
  Wire.setSCL(17);       //I2C0 SCL GP17
  Wire.setClock(400000);
  Wire.begin();          //I2C0 begin

  int16_t config_value = 0x399F;         //INA219 デフォルト
  Wire.beginTransmission(0x40);          //INA219 デバイスアドレス
  Wire.write(0x00);                      //configアドレス
  Wire.write((config_value >> 8) & 0xFF);
  Wire.write(config_value & 0xFF);
  Wire.endTransmission();

  digitalWrite(25, HIGH);
}

void loop() {
  //Get BusVoltage
  Wire.beginTransmission(0x40);                 //デバイスアドレス
  Wire.write(0x02);                             //BusVoltageレジスタ
  Wire.endTransmission();
  Wire.requestFrom(0x40, 16);
  while (Wire.available() < 16);
  BusVoltage_mV = Wire.read() << 8 | Wire.read();
  BusVoltage_mV = (BusVoltage_mV >> 3) * 4;

  //Get ShuntVoltage
  Wire.beginTransmission(0x40);                 //デバイスアドレス
  Wire.write(0x01);                             //ShuntVoltageレジスタ
  Wire.endTransmission();
  Wire.requestFrom(0x40, 16);
  while (Wire.available() < 16);
  ShuntVoltage_raw = Wire.read() << 8 | Wire.read();
  ShuntVoltage_mV  = ShuntVoltage_raw * 0.01;     // *0.01[mV]  // *10[uV]
  current_mA       = ShuntVoltage_mV * 10;      //I=V/R=V/0.1=V*10

  Serial.print("BusVoltage ");
  Serial.print(BusVoltage_mV);
  Serial.print("mV  ");
  Serial.print("ShuntVoltage ");
  Serial.print(ShuntVoltage_mV);
  Serial.print("mV  ");
  Serial.print("Current ");
  Serial.print(current_mA);
  Serial.println("mA");
  delay(500);
}

コメント