Skip to content

Commit fcc92cd

Browse files
committed
add basic INA228 support
1 parent d89299d commit fcc92cd

File tree

2 files changed

+86
-25
lines changed

2 files changed

+86
-25
lines changed

src/INA.cpp

Lines changed: 74 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,12 @@ inaDet::inaDet(inaEEPROM &inaEE) {
4545
break;
4646

4747
case INA228:
48-
power_LSB = 0; // TODO
4948
busVoltageRegister = INA228_BUS_VOLTAGE_REGISTER;
50-
busVoltage_LSB = INA228_BUS_VOLTAGE_LSB;
5149
shuntVoltageRegister = INA228_SHUNT_VOLTAGE_REGISTER;
52-
53-
currentRegister = INA226_CURRENT_REGISTER;
54-
shuntVoltage_LSB = INA226_SHUNT_VOLTAGE_LSB;
50+
shuntVoltage_LSB = INA228_SHUNT_VOLTAGE_LSB;
51+
currentRegister = INA228_CURRENT_REGISTER;
52+
current_LSB = ((uint64_t)maxBusAmps * 1000000000ULL) / 524288ULL;
53+
power_LSB = 34 * current_LSB;
5554
break;
5655

5756
case INA260:
@@ -366,6 +365,11 @@ void INA_Class::initDevice(const uint8_t deviceNumber) {
366365
bitSet(tempRegister, INA219_BRNG_BIT); // set to 1 for 0-32 volts
367366
writeWord(INA_CONFIGURATION_REGISTER, tempRegister, ina.address); // Write to config register
368367
break;
368+
case INA228:
369+
// Compute calibration register
370+
calibration = (131072ULL * (int64_t)ina.current_LSB * (int64_t)ina.microOhmR) / 10000000000ULL;
371+
writeWord(INA228_CALIBRATION_REGISTER, calibration, ina.address); // Write calibration
372+
break;
369373
case INA226:
370374
case INA230:
371375
case INA231:
@@ -377,7 +381,8 @@ void INA_Class::initDevice(const uint8_t deviceNumber) {
377381
case INA260:
378382
case INA3221_0:
379383
case INA3221_1:
380-
case INA3221_2: break;
384+
case INA3221_2:
385+
break;
381386
} // of switch type
382387
} // of method initDevice()
383388
void INA_Class::setBusConversion(const uint32_t convTime, const uint8_t deviceNumber) {
@@ -580,7 +585,7 @@ uint16_t INA_Class::getBusMilliVolts(const uint8_t deviceNumber) {
580585
uint32_t busVoltage = getBusRaw(deviceNumber); // Get raw voltage from device
581586
if (ina.type == INA228) {
582587
// The accuracy is 20bits and 195.3125uv is the LSB
583-
busVoltage = (uint64_t)busVoltage * 1953125 / 10000000; // conversion to get mV
588+
busVoltage = ((uint64_t)busVoltage * (uint64_t)INA228_BUS_VOLTAGE_LSB) / 10000000ULL; // conversion to get mV
584589
} else {
585590
busVoltage = busVoltage * ina.busVoltage_LSB / 100; // conversion to get mV
586591
} // if-then-else an INA228
@@ -626,7 +631,7 @@ int32_t INA_Class::getShuntMicroVolts(const uint8_t deviceNumber) {
626631
shuntVoltage = busMicroAmps / 200; // 2mOhm resistor, convert with Ohm's law
627632
} else {
628633
if (ina.type == INA228) {
629-
shuntVoltage = shuntVoltage * ina.shuntVoltage_LSB / 10; // Convert to microvolts
634+
shuntVoltage = ((uint32_t)shuntVoltage * (uint32_t)ina.shuntVoltage_LSB) / 10000UL; // Convert to microvolts
630635
} else {
631636
shuntVoltage = shuntVoltage * ina.shuntVoltage_LSB / 10; // Convert to microvolts
632637
} // if-then a INA228 with 20 bit accuracy
@@ -679,15 +684,31 @@ int32_t INA_Class::getBusMicroAmps(const uint8_t deviceNumber) {
679684
@return int32_t signed integer for computed microamps on the bus */
680685
readInafromEEPROM(deviceNumber); // Load EEPROM to ina structure
681686
int32_t microAmps = 0;
682-
if (ina.type == INA3221_0 || ina.type == INA3221_1 ||
683-
ina.type == INA3221_2) // Doesn't compute Amps
684-
{
687+
int32_t raw = 0;
688+
switch (ina.type) {
689+
case INA3221_0: // Doesn't compute Amps
690+
case INA3221_1:
691+
case INA3221_2:
685692
microAmps =
686693
(int64_t)getShuntMicroVolts(deviceNumber) * ((int64_t)1000000 / (int64_t)ina.microOhmR);
687-
} else {
694+
break;
695+
case INA228:
696+
raw = read3Bytes(ina.currentRegister, ina.address);
697+
// The number is two's complement, so if negative we need to pad when shifting //
698+
if (raw & 0x800000) {
699+
raw = (raw >> 4) | 0xFFF00000; // first 12 bits are "1"
700+
} else {
701+
raw = raw >> 4;
702+
} // if-then negative
703+
704+
microAmps = ((int64_t)raw * (int64_t)ina.current_LSB) / 1000ULL;
705+
break;
706+
default:
688707
microAmps = (int64_t)readWord(ina.currentRegister, ina.address) * (int64_t)ina.current_LSB /
689708
(int64_t)1000;
690-
} // of if-then-else an INA3221
709+
break;
710+
}
711+
691712
return (microAmps);
692713
} // of method getBusMicroAmps()
693714
int64_t INA_Class::getBusMicroWatts(const uint8_t deviceNumber) {
@@ -699,17 +720,27 @@ int64_t INA_Class::getBusMicroWatts(const uint8_t deviceNumber) {
699720
@return int64_t signed integer for computed microwatts on the bus
700721
*/
701722
int64_t microWatts = 0;
723+
int32_t raw = 0;
724+
702725
readInafromEEPROM(deviceNumber); // Load EEPROM to ina structure
703-
if (ina.type == INA3221_0 || ina.type == INA3221_1 ||
704-
ina.type == INA3221_2) // Doesn't compute Amps
705-
{
726+
switch (ina.type) {
727+
case INA3221_0: // Doesn't compute Amps
728+
case INA3221_1:
729+
case INA3221_2:
706730
microWatts =
707731
((int64_t)getShuntMicroVolts(deviceNumber) * (int64_t)1000000 / (int64_t)ina.microOhmR) *
708732
(int64_t)getBusMilliVolts(deviceNumber) / (int64_t)1000;
709-
} else {
733+
break;
734+
case INA228:
735+
raw = read3Bytes(INA228_POWER_REGISTER, ina.address);
736+
737+
microWatts = ((int64_t)raw * (int64_t)ina.power_LSB) / 10000ULL;
738+
break;
739+
default:
710740
microWatts =
711741
(int64_t)readWord(INA_POWER_REGISTER, ina.address) * (int64_t)ina.power_LSB / (int64_t)1000;
712742
if (getShuntRaw(deviceNumber) < 0) microWatts *= -1; // Invert if negative voltage
743+
break;
713744
} // of if-then-else an INA3221
714745
return (microWatts);
715746
} // of method getBusMicroWatts()
@@ -1068,9 +1099,9 @@ void INA_Class::setAveraging(const uint16_t averages, const uint8_t deviceNumber
10681099
deviceNumber % _DeviceCount == i) // If this device needs setting
10691100
{
10701101
readInafromEEPROM(i); // Load EEPROM to struct
1071-
configRegister = readWord(INA_CONFIGURATION_REGISTER, ina.address); // Get current register
10721102
switch (ina.type) {
10731103
case INA219:
1104+
configRegister = readWord(INA_CONFIGURATION_REGISTER, ina.address); // Get current register
10741105
if (averages >= 128)
10751106
averageIndex = 15;
10761107
else if (averages >= 64)
@@ -1090,6 +1121,7 @@ void INA_Class::setAveraging(const uint16_t averages, const uint8_t deviceNumber
10901121
configRegister &= ~INA219_CONFIG_AVG_MASK; // zero out the averages part
10911122
configRegister |= averageIndex << 3; // shift in the SADC averages
10921123
configRegister |= averageIndex << 7; // shift in the BADC averages
1124+
writeWord(INA_CONFIGURATION_REGISTER, configRegister, ina.address); // Save new value
10931125
break;
10941126
case INA226:
10951127
case INA230:
@@ -1098,6 +1130,7 @@ void INA_Class::setAveraging(const uint16_t averages, const uint8_t deviceNumber
10981130
case INA3221_1:
10991131
case INA3221_2:
11001132
case INA260:
1133+
configRegister = readWord(INA_CONFIGURATION_REGISTER, ina.address); // Get current register
11011134
if (averages >= 1024)
11021135
averageIndex = 7;
11031136
else if (averages >= 512)
@@ -1116,9 +1149,31 @@ void INA_Class::setAveraging(const uint16_t averages, const uint8_t deviceNumber
11161149
averageIndex = 0;
11171150
configRegister &= ~INA226_CONFIG_AVG_MASK; // zero out the averages part
11181151
configRegister |= averageIndex << 9; // shift in the averages to reg
1152+
writeWord(INA_CONFIGURATION_REGISTER, configRegister, ina.address); // Save new value
1153+
break;
1154+
case INA228:
1155+
configRegister = readWord(INA228_CONFIGURATION_REGISTER, ina.address); // Get current register
1156+
if (averages >= 1024)
1157+
averageIndex = 7;
1158+
else if (averages >= 512)
1159+
averageIndex = 6;
1160+
else if (averages >= 256)
1161+
averageIndex = 5;
1162+
else if (averages >= 128)
1163+
averageIndex = 4;
1164+
else if (averages >= 64)
1165+
averageIndex = 3;
1166+
else if (averages >= 16)
1167+
averageIndex = 2;
1168+
else if (averages >= 4)
1169+
averageIndex = 1;
1170+
else
1171+
averageIndex = 0;
1172+
configRegister &= ~INA228_CONFIG_AVG_MASK; // zero out the averages part
1173+
configRegister |= averageIndex; // shift in the averages to reg
1174+
writeWord(INA228_CONFIGURATION_REGISTER, configRegister, ina.address); // Save new value
11191175
break;
11201176
} // of switch type
1121-
writeWord(INA_CONFIGURATION_REGISTER, configRegister, ina.address); // Save new value
11221177
} // of if this device needs to be set
11231178
} // for-next each device loop
11241179
} // of method setAveraging()

src/INA.h

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -259,13 +259,19 @@ const uint16_t INA226_CONFIG_SADC_MASK{0x0038}; ///< INA226 Bits 3-4
259259

260260
const uint8_t INA228_DIE_ID_REGISTER{0x3F}; ///< INA228 Device_ID Register
261261
const uint16_t INA228_DIE_ID_VALUE{0x2280}; ///< INA228 Hard-coded Die ID for INA228
262+
const uint8_t INA228_CALIBRATION_REGISTER{0x2}; ///< INA228 Calibration Register
262263
const uint8_t INA228_BUS_VOLTAGE_REGISTER{0x5}; ///< INA228 Bus Voltage Register
263-
const uint16_t INA228_BUS_VOLTAGE_LSB{195}; ///< INA228 LSB in uV *100 1953125uV, extra code
264-
const uint8_t INA228_SHUNT_VOLTAGE_REGISTER{4}; ///< INA228 Shunt Voltage Register
265-
const uint8_t xINA228_CURRENT_REGISTER{4}; ///< INA228 Current Register
266-
const uint16_t xINA228_CONFIG_AVG_MASK{0x0E00}; ///< INA228 Bits 9-11
267-
const uint16_t xINA228_CONFIG_BADC_MASK{0x01C0}; ///< INA228 Bits 6-8 masked
268-
const uint16_t xINA228_CONFIG_SADC_MASK{0x0038}; ///< INA228 Bits 3-4
264+
const uint32_t INA228_BUS_VOLTAGE_LSB{1953125}; ///< INA228 LSB in pV * 100 195.3125uV
265+
const uint8_t INA228_SHUNT_VOLTAGE_REGISTER{0x4}; ///< INA228 Shunt Voltage Register
266+
const uint16_t INA228_SHUNT_VOLTAGE_LSB{3125}; ///< INA228 LSB in nV * 10 312.5nV
267+
const uint8_t INA228_CURRENT_REGISTER{0x7}; ///< INA228 Current Register
268+
const uint8_t INA228_POWER_REGISTER{0x8}; ///< INA228 Power Register
269+
const uint8_t INA228_CONFIGURATION_REGISTER{0x1}; ///< INA228 Configuration Register address
270+
const uint16_t INA228_CONFIG_MODE_MASK{0xF000}; ///< INA228 Bits 12-15
271+
const uint16_t INA228_CONFIG_BADC_MASK{0x0E00}; ///< INA228 Bits 9-11
272+
const uint16_t INA228_CONFIG_SADC_MASK{0x01C0}; ///< INA228 Bits 6-8
273+
const uint16_t INA228_CONFIG_TADC_MASK{0x0038}; ///< INA228 Bits 3-5
274+
const uint16_t INA228_CONFIG_AVG_MASK{0x0007}; ///< INA228 Bits 0-2
269275

270276
const uint8_t INA260_SHUNT_VOLTAGE_REGISTER{0}; ///< INA260 Register doesn't exist
271277
const uint8_t INA260_CURRENT_REGISTER{1}; ///< INA260 Current Register

0 commit comments

Comments
 (0)