Text Size
Main

You can measure DC Voltage, Current and Power in a voltage range from 0V to 26V. This circuit use a high-side current shunt and power monitor with an I2C interface INA209 from Texas Instruments and an Arduino UNO as microcontroller. The values are shown on a 2x16 LCD display. 

Hardware description

All the measurements are made by Texas Instruments INA209, it's a high-side current shunt and power monitor with an I2C interface. The INA209 monitors both shunt drop and shunt bus voltage. A programmable calibration value, combined with an internal multiplier, enables direct readouts in amperes. The INA209 also includes an analog comparator and a programmable 12 bit digital-to-analog converter (DAC) that combine to provide the fastest possible responses to current overload conditions. The INA209 senses across shunts on buses that can vary from 0V to 26V.

INA209 Features

  • Senses BUS Voltage from 0V to +26V
  • Reports Current, Voltage, Power and stores Peaks
  • Triple Watchdog Limit:
    • Lower Warning with Delay
    • Upper Over-Limit, No Delay
    • Fast Analog Critical
  • High Accuracy: 1% Max Over Temp

For more details see Texas Instruments INA209 datasheet.

The comunication between INA209 and Arduino occurs through the I2C bus. Arduino controls all function of INA209 and reads the value measured from the dedicated registers. You can read the INA209 status or set the configuration parameters.

In this version of firmware I designed only the basic functions for continuos measurements of instantaneous Voltage, Current and Power but you can control all function of INA209 with my library as described on page INA209 Arduino Library.

The Voltage, Current and Power values are are shown on a 16x2 LCD display connected to digital pin of Arduino. LCD display is a standard 16x2 character model YM1602C and is connected to Arduino digital pins 12, 11, 5, 4, 3, 2. The contrast is regulated by a 10k trimmer and the backlight is software controlled by Arduino PWM digital output on pin 6.

The figure below shown the block diagram of DC Power Monitor.

DC Power Monitor by ADPSLAB

In this version of firmware I designed only the basic function for continuos measurements of instantaneous Voltage, Current and Power but you can control all function of INA209 with my library as described on page INA209 Arduino Library.

Circuit schematics

Technical specifications

General features
Averaging results 2 ÷ 128 samples
Voltage Measurement
Digits

5

Full-Scale range

0 ÷ 26 V

Resolution

4mV

Measurement error

± 0.5% max

Measurement error over temperature

± 1% max

Current Measurement
Digits

5

Full-Scale range

0 ÷ 6 A

Resolution

1mA

Measurement error

± 0.5% max

Measurement error over temperature ± 1% max
Power Measurement
Digits 6
Full-Scale range 0 ÷ 156 W
Resolution 4mW
Measurement error ± 1% max
Measurement error over temperature ± 2% max

 

Firmware

The most important part of the firmware is the INA209 library I have written and you can see it on page INA209 Arduino Library. The library is used for control all functions of INA209 through the I2C bus. The measured value are read from INA209 using a simple and intuitive function call and you don't need to know how I2C works.

/*
  DC Power Monitor by ADPSLAB
  Created 12 Sep. 2012 (Rev. 1.0)
  Copyright (c) 2012 Antonio Dambrosio (This email address is being protected from spambots. You need JavaScript enabled to view it.).  All rights reserved.
  
  This sketch is for control a Texas Instruments INA209 chip through I2C bus 
  and shown on a LCD Display 2x16 character these values:
  Voltage measurement in a range from 0 to +26V with 4mV resolution; 
  Current measurement in a range from 0 to 6A with mA resolution;
  Power measurement with 4mW resolution.
    
  See the schematics on:
  https://www.adpslab.com/en/electronics/arduino/22-dc-power-monitor-with-ina209-and-arduino  
*/

#include <Wire.h>              //I2C library 
#include <INA209.h>            //INA209 library
#include <LiquidCrystal.h>     //LCD library

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);   // initialize the LCD library with the numbers of the interface pins
#define   BACKLIGHT_PIN  6               // define PIN for PWM Backlight control 
INA209 ina209a(0x40);                    // creation of an instance of the INA209 class called ina209a with I2C slave address = 0x40
int intro = 0;          // costant value for intro message

void setup() {
  
  analogWrite(BACKLIGHT_PIN, 240);
  lcd.begin(16, 2);          // set up the LCD's number of columns and rows 
  Serial.begin(9600);        // setup serial
  Wire.begin();              // join i2c bus
  
  // ------------- General Configuration --------- 
  /* Configuration Register 00h (Read/Write)
     Default settings -> writeCfgReg(14751)
        Bus Voltage Range = 32V
        PGA (Shunt Voltage Only) = +/- 320mV
        BADC Bus ADC Resolution/Averaging = 12bit
        SADC Shunt ADC Resolution/Averaging = 12bit
        Operating Mode = Shunt and Bus, Continuos
  */
  // ina209a.writeCfgReg(14751); // Default settings no averaging
  // ina209a.writeCfgReg(15839); // 8 averaging samples bus and shunt 
  ina209a.writeCfgReg(16247);       // 64 averaging samples bus and shunt
  
  // -------------- Calibration ------------------
  /* Calibration Register 16h (Read/Write)
    This register sets the current that corresponds to a full-scale drop across the shunt. 
    Full-scale range and the LSB of the current and power measurement depend on the value entered in this register.
    See the Programming the INA209 Power Measurement Engine section of INA209 datasheet.         
    In this example:
            Vbus_max = 32V
            Vshunt_max = 0,32V
            Rshunt = 0,05 Ohm
        ->  Max Expected Current = +/- 6A
            Current LSB = 200uA
            Calibration Reg = 4096
            Power LSB = 4mW
            Max Power = 204,8W 
  */
  ina209a.writeCal(4096);
    
  // ---------- WARNING WATCHDOG REGISTERS -------
  /* These registers set warning limits that trigger flags in the Status Register 
     and activate the Warning pin.
  */
  ina209a.writeShuntVolPwrn(30000);        // set Shunt Voltage Positive Warning limit to 30000 (= 300mV) 
  ina209a.writeShuntVolNwrn(-500);         // set Shunt Voltage Negative Warning limit to -500 (= -5mV) 
  ina209a.writePowerWrn(10000);            // set Power Warning limit
  ina209a.writeBusOVwrn(52000);            // set Bus Over-Voltage Warning limit, if you want a limit of 26V you have to set 26000*2 = 52000 
  ina209a.writeBusUVwrn(10000);            // set Bus Under-Voltage Warning limit, if you want a limit of 5V you have to set 5000*2 = 10000 
  
  // ---------- OVER-LIMIT/CRITICAL WATCHDOG REGISTERS ----------------
  /* These registers set the over-limit and critical DAC limits that trigger flags to be set in the Status Register 
     and activate the Overlimit pin or the Critical pin.
  */
  ina209a.writePowerOL(12000);             // set Power Over-Limit
  ina209a.writeBusOVOL(60000);             // set Bus Over-Voltage Over-Limit, if you want a limit of 30V you have to set 30000*2 = 60000 (see the datasheet for other functions)
  ina209a.writeBusUVOL(6000);              // set Bus Under-Voltage Over-Limit, if you want a limit of 3V you have to set 3000*2 = 6000
  ina209a.writeCrShuntPV(51200);           // set Critical DAC+ Register (Critical Shunt Positive Voltage). No sign bit (sets a positive limit only). At full-scale range = 255mV; LSB = 1mV; 8-bit.
                                           // if you want a limit of +200mV you have to set 200*256 = 51200;
                                           // this register control GPIO PIN, see the datasheet.
  ina209a.writeCrShuntNV(51200);           // set Critical DAC– Register (Critical Shunt Negative Voltage). No sign bit (sets negative limit only). At full-scale range = –255mV; LSB = 1mV; 8-bit.
                                           // if you want a limit of -200mV you have to set 200*256 = 51200;
                                           // this register control DAC Comparator output filter, see the datasheet.
  }
  
  
void loop() {

  if (intro == 0) {                 // Intro message
      lcd.home ();                   
      lcd.setCursor(4, 0); 
      lcd.print ("ADPSLAB");
      lcd.setCursor(0, 1);
      lcd.print ("DC Power Monitor");
      delay (3000);
      lcd.clear ();
      intro = 1;
  }
  
  lcd.setCursor(0, 0);                      // set the cursor to (0 at first line)
  lcd.print (msg2dot3(ina209a.busVol()));   // show Voltage measured 
  lcd.print (" V");
  lcd.setCursor(8, 0);
  lcd.print (msg2dot3(current_mA(200)));    // show Current measured 
  lcd.print (" A");
  lcd.setCursor(0, 1);
  lcd.print (");
  lcd.print (msg3dot3(power_mW(4)));        // show Power measured 
  lcd.print (" W>");
  lcd.setCursor(7, 1);
 
}

int current_mA (int current_LSB) {          // set Current in mA, current_mA = ina209a.current() * current_LSB (uA) / 1000
    int y = 1000 / current_LSB;  
    int x = ina209a.current() / y;    
    return x;
}

long power_mW (int power_LSB) {              // set Power in mW, power_mW = ina209a.power() * power_LSB (mW) 
    long x = ina209a.power() * power_LSB;    
    return x;
}

String msg2dot3 (int xvalue) {              // format integer to string 2.3 character
    String strvalue = 0;
    if (xvalue >= 0){
      strvalue = String (xvalue);
      switch (strvalue.length())
      {
       case 1:
        strvalue = String (" .00" + strvalue.substring(0));
        break;   
       case 2:
        strvalue = String (" .0" + strvalue.substring(0));
        break;   
       case 3:
        strvalue = String (" ." + strvalue.substring(0));
        break; 
       case 4:
        strvalue = String (" " + strvalue.substring(0,1) + "." + strvalue.substring(1));
        break; 
       case 5:
        strvalue = String (strvalue.substring(0,2) + "." + strvalue.substring(2));
        break; 
       default:
        strvalue = String ("error"); 
      }
     } else {
      strvalue = String (abs(xvalue));
      switch (strvalue.length())
      {
       case 1:
        strvalue = String (" -.00" + strvalue.substring(0));
        break;   
       case 2:
        strvalue = String (" -.0" + strvalue.substring(0));
        break;   
       case 3:
        strvalue = String (" -." + strvalue.substring(0));
        break; 
       case 4:
        strvalue = String ("-" + strvalue.substring(0,1) + "." + strvalue.substring(1));
        break; 
       case 5:
        strvalue = String (strvalue.substring(0,2) + "." + strvalue.substring(2) + "-");
        break; 
       default:
        strvalue = String ("error"); 
      } 
     } 
   return strvalue;
}

String msg3dot3 (long pvalue) {              // format long integer to string 3.3 character
    String strvalue = 0;
    strvalue = String (pvalue);
    switch (strvalue.length())
    {
     case 1:
      strvalue = String (" .00" + strvalue.substring(0));
      break;   
     case 2:
      strvalue = String (" .0" + strvalue.substring(0));
      break;   
     case 3:
      strvalue = String (" ." + strvalue.substring(0));
      break; 
     case 4:
      strvalue = String (" " + strvalue.substring(0,1) + "." + strvalue.substring(1));
      break; 
     case 5:
      strvalue = String (" " +strvalue.substring(0,2) + "." + strvalue.substring(2));
      break;
     case 6:
      strvalue = String (" " +strvalue.substring(0,3) + "." + strvalue.substring(3));
      break; 
     default:
      strvalue = String ("error"); 
    }
   return strvalue;
}

 

Download the library files and Arduino sketch file.

Download INA209 Arduino Library Rev.1.0:  INA209_Arduino_Library.rar
You have to copy the entire INA209 directory in the Arduino "/libraries" directory.
Download DC Power Monitor Rev.1.0:  DC_Power_Monitor_rev1.0.rar
This file contain the DC Power Monitor Arduino sketch file.

 

Tests on prototype board

The figure below shown the circuit on a prototype board. In this version Arduino, INA209 and LCD Display are powered by USB supply. The power supply under test are connected on the bananas connector on the left of photo.

 

The video below shown some tests on a prototype board.

Category: Arduino
Bottom