简体   繁体   中英

How to calibrate ti INA219 sensor? (in C)

SO I calculated the calibration register value based on this :

My shunt resistor value is 0.01 ohms. My currents are off even though I'm calibrating it based on my shunt value

All currents show the wrong values(For example it's supposed to show 7.8mA and it shows 1mA

Following is my 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_ADDRESS1         0x40 
#define INA_ADDRESS2         0x41



int interval = 60;
int i2c_bus = 1;
int i2c_address1 = INA_ADDRESS1;
int i2c_address2 = INA_ADDRESS2;

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 / 10;
    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) );

    }
}


int main( int argc, char *argv[] )
{
    char filename[ 20 ];
    register_write(CALIBRATION_REG, 4096);



    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 );
    }

    if ( ioctl( handle,  I2C_SLAVE, i2c_address1 ) < 0 )
    {
        fprintf( stderr, "Error setting address %02X: %s\n", i2c_address1, strerror( errno ) );
        exit( 1 );
    }

        show_voltage_current();
        sleep(1);


    if ( ioctl( handle,  I2C_SLAVE, i2c_address2 ) < 0 )
    {
        fprintf( stderr, "Error setting address %02X: %s\n", i2c_address2, strerror( errno ) );
        exit( 1 );


        show_voltage_current();
        sleep(1);
    }
    return 0;
}

Look at https://github.com/flav1972/ArduinoINA219 as a reference.

You should set status and calibration registers before Current/Power values will be reliable

Try change expected current to be at least 1/4 of max current and remember to set valid shunt voltage.

On my test board if I define expected current as 1.6A and max_current 16A I have wrong result, but if I change it to 4A result seems ok

Worked for me: Rshunt=0.1R, Vbus=16V, Imax=1.6A, Iexp=1.6A, Rshunt=0.01R,Vbus=16V,Imax=16A,Iexp=4..16A

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM