2 * INA219 util - part of PowerCape by AndiceLabs
4 * Copyright (C) 2014 AndiceLabs admin@andicelabs.com http://andicelabs.com
5 * Copyright (C) 2014 Zig Fisher flyrouter@gmail.com http://zftlab.org
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
18 * Example run and output:
20 * OpenWRT:~# ina219 -b 0 -i 60
22 * 22:49 12168mV 134.2mA
23 * 22:50 12168mV 239.9mA
24 * 22:51 12168mV 134.7mA
36 #include <sys/types.h>
38 #include <sys/ioctl.h>
40 #include <linux/i2c-dev.h>
47 #define CALIBRATION_REG 5
49 #define AVR_ADDRESS 0x21
50 #define INA_ADDRESS 0x40
60 op_type operation = OP_DUMP;
64 int i2c_address = INA_ADDRESS;
66 int whole_numbers = 0;
69 void msleep( int msecs )
71 usleep( msecs * 1000 );
75 int i2c_read( void *buf, int len )
79 if ( read( handle, buf, len ) != len )
81 printf( "I2C read failed: %s\n", strerror( errno ) );
89 int i2c_write( void *buf, int len )
93 if ( write( handle, buf, len ) != len )
95 printf( "I2C write failed: %s\n", strerror( errno ) );
103 int register_read( unsigned char reg, unsigned short *data )
106 unsigned char bite[ 4 ];
109 if ( i2c_write( bite, 1 ) == 0 )
111 if ( i2c_read( bite, 2 ) == 0 )
113 *data = ( bite[ 0 ] << 8 ) | bite[ 1 ];
122 int register_write( unsigned char reg, unsigned short data )
125 unsigned char bite[ 4 ];
128 bite[ 1 ] = ( data >> 8 ) & 0xFF;
129 bite[ 2 ] = ( data & 0xFF );
131 if ( i2c_write( bite, 3 ) == 0 )
140 void show_usage( char *progname )
142 fprintf( stderr, "Usage: %s <mode> \n", progname );
143 fprintf( stderr, " Mode (required):\n" );
144 fprintf( stderr, " -h --help Show usage.\n" );
145 fprintf( stderr, " -i --interval Set interval for monitor mode.\n" );
146 fprintf( stderr, " -w --whole Show whole numbers only. Useful for scripts.\n" );
147 fprintf( stderr, " -v --voltage Show battery voltage in mV.\n" );
148 fprintf( stderr, " -c --current Show battery current in mA.\n" );
149 fprintf( stderr, " -a --address <addr> Override I2C address of INA219 from default of 0x%02X.\n", i2c_address );
150 fprintf( stderr, " -b --bus <i2c bus> Override I2C bus from default of %d.\n", i2c_bus );
155 void parse( int argc, char *argv[] )
159 static const struct option lopts[] =
161 { "address", 0, 0, 'a' },
162 { "bus", 0, 0, 'b' },
163 { "current", 0, 0, 'c' },
164 { "help", 0, 0, 'h' },
165 { "interval", 0, 0, 'i' },
166 { "voltage", 0, 0, 'v' },
167 { "whole", 0, 0, 'w' },
172 c = getopt_long( argc, argv, "a:b:chi:vw", lopts, NULL );
182 i2c_address = (int)strtol( optarg, NULL, 0 );
185 fprintf( stderr, "Unknown address parameter %s.\n", optarg );
194 i2c_bus = (int)strtol( optarg, NULL, 0 );
197 fprintf( stderr, "Unknown bus parameter %s.\n", optarg );
205 operation = OP_CURRENT;
213 show_usage( argv[ 0 ] );
219 operation = OP_MONITOR;
220 interval = atoi( optarg );
221 if ( ( interval == 0 ) && ( errno != 0 ) )
223 fprintf( stderr, "Invalid interval value\n" );
231 operation = OP_VOLTAGE;
245 int get_voltage( float *mv )
249 if ( register_read( BUS_REG, (unsigned short*)&bus ) != 0 )
254 *mv = ( float )( ( bus & 0xFFF8 ) >> 1 );
259 int get_current( float *ma )
263 if ( register_read( SHUNT_REG, &shunt ) != 0 )
268 *ma = (float)shunt / 10;
273 void show_current( void )
277 if ( get_current( &ma ) )
279 fprintf( stderr, "Error reading current\n" );
285 printf( "%4.0f\n", ma );
289 printf( "%04.1f\n", ma );
294 void show_voltage( void )
298 if ( get_voltage( &mv ) )
300 fprintf( stderr, "Error reading voltage\n" );
303 printf( "%4.0f\n", mv );
307 void show_voltage_current( void )
311 if ( get_current( &ma ) || get_voltage( &mv ) )
313 fprintf( stderr, "Error reading voltage/current\n" );
319 printf( "%04.0fmV %4.0fmA\n", mv, ma );
323 printf( "%04.0fmV %04.1fmA\n", mv, ma );
335 seconds = time( NULL );
336 tmptr = localtime( &seconds );
337 printf( "%02d:%02d ", tmptr->tm_hour, tmptr->tm_min );
338 show_voltage_current();
344 int main( int argc, char *argv[] )
350 snprintf( filename, 19, "/dev/i2c-%d", i2c_bus );
351 handle = open( filename, O_RDWR );
354 fprintf( stderr, "Error opening bus %d: %s\n", i2c_bus, strerror( errno ) );
358 if ( ioctl( handle, I2C_SLAVE, i2c_address ) < 0 )
360 fprintf( stderr, "Error setting address %02X: %s\n", i2c_address, strerror( errno ) );
368 show_voltage_current();