This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi,
I am trying to monitor voltage and current of 5 different devices using 5 different INA219 sensors, but the currents are off a bit and the currents fluctuate when they shouldn't.
shunt resistor value: 0.01 ohm
calibration value: 409
max expected current total throughout the board: 12 A
max expected on each device 5 A
Computing System: Raspberry Pi
Attached is the code:
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <endian.h> #include <string.h> #include <time.h> #include <getopt.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <fcntl.h> #include <linux/i2c-dev.h> #define CONFIG_REG 0 #define SHUNT_REG 1 #define BUS_REG 2 #define POWER_REG 3 #define CURRENT_REG 4 #define CALIBRATION_REG 5 #define INA_ADDRESS_1 0x40 #define INA_ADDRESS_2 0x41 #define INA_ADDRESS_3 0x42 //change this depending what address you have #define INA_ADDRESS_4 0x43 #define INA_ADDRESS_5 0x44 int interval = 60; int i2c_bus = 1; int i2c_address_1 = INA_ADDRESS_1; int i2c_address_2 = INA_ADDRESS_2; int i2c_address_3 = INA_ADDRESS_3; int i2c_address_4 = INA_ADDRESS_4; int i2c_address_5 = INA_ADDRESS_5; int handle; int i2c_read( void *buf, int len ) { int rc = 0; if ( read( handle, buf, len ) != len ) { printf( "I2C read failed: %s\n", strerror( errno ) ); rc = -1; } return 0; } int i2c_write( void *buf, int len ) { int rc = 0; if ( write( handle, buf, len ) != len ) { printf( "I2C write failed: %s\n", strerror( errno ) ); rc = -1; } return rc; } int register_read( unsigned char reg, unsigned short *data ) { int rc = -1; unsigned char bite[ 4 ]; bite[ 0 ] = reg; if ( i2c_write( bite, 1 ) == 0 ) { if ( i2c_read( bite, 2 ) == 0 ) { *data = ( bite[ 0 ] << 8 ) | bite[ 1 ]; rc = 0; } } return rc; } int register_write( unsigned char reg, unsigned short data ) { int rc = -1; unsigned char bite[ 4 ]; bite[ 0 ] = reg; bite[ 1 ] = ( data >> 8 ) & 0xFF; bite[ 2 ] = ( data & 0xFF ); if ( i2c_write( bite, 3 ) == 0 ) { rc = 0; } return rc; } int get_voltage( float *mv ) { short bus; if ( register_read( BUS_REG, (unsigned short*)&bus ) != 0 ) { return -1; } *mv = ( float )( ( bus & 0xFFF8 ) >> 1 ); return 0; } int get_current( float *ma ) { short shunt; if ( register_read( SHUNT_REG, &shunt ) != 0 ) { return -1; } *ma = (float)shunt; return 0; } void show_current( void ) { float ma; if ( get_current( &ma ) ) { fprintf( stderr, "Error reading current\n" ); return; } } void show_voltage( void ) { float mv; if ( get_voltage( &mv ) ) { fprintf( stderr, "Error reading voltage\n" ); return; } printf( "%4.0f\n", mv ); } void show_voltage_current( void ) { float mv, ma; if ( get_current( &ma ) || get_voltage( &mv ) ) { fprintf( stderr, "Error reading voltage/current\n" ); return; } else { printf( "Load Voltage: %g Current: %4.1fmA\n", (mv/1000), (ma-7) ); } } int main( int argc, char *argv[] ) { char filename[ 20 ]; register_write(CALIBRATION_REG, 409); snprintf( filename, 19, "/dev/i2c-%d", i2c_bus ); handle = open( filename, O_RDWR ); if ( handle < 0 ) { fprintf( stderr, "Error opening bus %d: %s\n", i2c_bus, strerror( errno ) ); exit( 1 ); } while(1) { if ( ioctl( handle, I2C_SLAVE, i2c_address_1 ) < 0 ) { fprintf( stderr, "Error setting address %02X: %s\n", i2c_address_1, strerror( errno ) ); exit( 1 ); } { printf("+5: "); show_voltage_current(); sleep(1); } if ( ioctl( handle, I2C_SLAVE, i2c_address_2 ) < 0 ) { fprintf( stderr, "Error setting address %02X: %s\n", i2c_address_2, strerror( errno ) ); exit( 1 ); } { printf("+5: "); show_voltage_current(); sleep(1); } if ( ioctl( handle, I2C_SLAVE, i2c_address_3 ) < 0 ) { fprintf( stderr, "Error setting address %02X: %s\n", i2c_address_3, strerror( errno ) ); exit( 1 ); } { printf("-5: "); show_voltage_current(); sleep(1); } if ( ioctl( handle, I2C_SLAVE, i2c_address_4 ) < 0 ) { fprintf( stderr, "Error setting address %02X: %s\n", i2c_address_4, strerror( errno ) ); exit( 1 ); } { printf("+12: "); show_voltage_current(); sleep(1); } if ( ioctl( handle, I2C_SLAVE, i2c_address_5 ) < 0 ) { fprintf( stderr, "Error setting address %02X: %s\n", i2c_address_5, strerror( errno ) ); exit( 1 ); } { printf("+5 "); show_voltage_current(); sleep(1); printf("\n"); } } return 0; }
Hi Shideh,
Can you share a schematic/layout of your system? Bad current readings can be related to layout issues.
For the digital section:
We have a training video that discusses how to program the digital output current shunt monitors for direct current and power readouts. Refer to Video 15.
[FAQ] Where can I learn about current sensing techniques, product selection and achievable accuracy?...
Also, you can take a look at the following C code for application reference.
Hi shideh,
Your Max Expected current should be 5A, as you will be programming each device individually. With a Rshunt of 0.01ohms, Max Expected Current of 5A and a Current LSB of 1mA/bit my calibration register is 1000(Hex). Using my EVM GUI. Which Current LSB value you used to obtain the Calibration Register value?