# setup alternate i2c bus - SDA on gpio 22/SCL on gpio 23 # and INA219 addresses my $i2cDev = '/dev/i2c-3'; my $busMode = 'i2c'; my $i2cAddrT = 0x41; my $i2cAddrB = 0x40; ... # Create two i2c device objects my $objI2cT = HiPi::Device::I2C->new( devicename => $i2cDev, address => $i2cAddrT, busmode => $busMode ); my $objI2cB = HiPi::Device::I2C->new( devicename => $i2cDev, address => $i2cAddrB, busmode => $busMode ); # Now drop back to regular user HiPi::Utils::drop_permissions_name( $user, $group ); ... # ********************************************************* # # initialize both devices # compute configuration bits (2 bytes msb, lsb) my @calcConfigT = Config( $shuntResT ); my @calcConfigB = Config( $shuntResB ); # set write address for configuration register (0x00) $objI2cT->bus_write( $i2cAddrT, 0x00 ); # write configuration register bits as two binary values, msb-lsb order $objI2cT->bus_write( $i2cAddrT, oct( "0b" . $calcConfigT[0] ), oct( "0b" . $calcConfigT[1] ) ); # set write address for configuration register (0x00) $objI2cB->bus_write( $i2cAddrB, 0x00 ); # write configuration register bits as two binary values, msb-lsb order $objI2cB->bus_write( $i2cAddrB, oct( "0b" . $calcConfigB[0] ), oct( "0b" . $calcConfigB[1] ) ); # ********************************************************* # # read & calculate bus voltage sub RcBus { my ($objI2C, @calcConfig) = @_; # read 2 bytes of data from bus voltage register (address 0x02) # as this sometimes creates an error and kills the script, use 'eval' my @bvr; eval{ @bvr = $objI2C->bus_read( 0x02, 2 ); 1; } or do { $bvr[0] = 0; $bvr[1] = 0; }; # result in upper 13 bits - data in msb-lsb (big-endian) order my $busV = pack 'C2', $bvr[0], $bvr[1]; $busV = ( unpack 'S>', $busV ) >> 3; # scale bus voltage register value according to voltage configuration bit my ($bv, $bvScale); if( $calcConfig[3] == 0 ) { $bv = 16; $bvScale = 4000; } else { $bv = 32; $bvScale = 8000; } $busV = $bv / $bvScale * $busV; printf "Bus voltage: %0.02f\n",$busV if $verbose; return $busV ; } # ********************************************************* # # read & calculate shunt current sub RcAmps { my ($objI2C, $shuntRes, @calcConfig) = @_; # read 2 bytes of data from shunt voltage register (address 0x01) # as this sometimes creates an error and kills the script, use 'eval' my @svr; eval{ @svr = $objI2C->bus_read( 0x01, 2 ); 1; } or do { $svr[0] = 0; $svr[1] = 0; }; # result in 14 low-order bits (big-endian & result always +ve) my $shuntV = pack 'C2', $svr[0], $svr[1]; $shuntV = ( unpack 'S>', $shuntV ) & 0b0011111111111111; # use $smv (shunt mV setting for calculation) $shuntV = $calcConfig[2] / ( $calcConfig[2] * 100 ) * $shuntV; printf "Shunt voltage: %0.02fmV\n", $shuntV if $verbose; # calculate current (amps) with specified shunt resistor my $shuntA = $shuntV / $shuntRes / 1000; printf "Shunt current: %0.02f amps\n\n", $shuntA if $verbose; return $shuntA ; }