Skip to content

Commit 4ae179f

Browse files
authored
Merge pull request #3 from adafruit/refactor
Update adafruit_ina228.py to match arduino changes
2 parents 5e099d3 + 931e253 commit 4ae179f

File tree

1 file changed

+102
-16
lines changed

1 file changed

+102
-16
lines changed

adafruit_ina228.py

Lines changed: 102 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,28 @@ class Mode:
8787
CONTINUOUS_ALL = 0x0F
8888

8989

90+
class AlertType:
91+
"""Constants for alert type settings"""
92+
93+
NONE = 0x00
94+
CONVERSION_READY = 0x01
95+
OVERPOWER = 0x02
96+
UNDERVOLTAGE = 0x04
97+
OVERVOLTAGE = 0x08
98+
UNDERCURRENT = 0x10
99+
OVERCURRENT = 0x20
100+
_VALID_VALUES = [
101+
NONE,
102+
CONVERSION_READY,
103+
OVERPOWER,
104+
UNDERVOLTAGE,
105+
OVERVOLTAGE,
106+
UNDERCURRENT,
107+
OVERCURRENT,
108+
]
109+
_MAX_COMBINED = 0x3F
110+
111+
90112
class INA228: # noqa: PLR0904
91113
"""Driver for the INA228 power and current sensor"""
92114

@@ -95,8 +117,14 @@ class INA228: # noqa: PLR0904
95117
_shunt_cal = UnaryStruct(_SHUNT_CAL, ">H")
96118
_diag_alrt = UnaryStruct(_DIAG_ALRT, ">H")
97119
_adc_range = RWBit(_CONFIG, 4, register_width=2)
120+
_alert_type = RWBits(6, _DIAG_ALRT, 8, register_width=2)
121+
_alert_polarity_bit = RWBit(_DIAG_ALRT, 12, register_width=2)
122+
_alert_latch_bit = RWBit(_DIAG_ALRT, 15, register_width=2)
123+
_reset_bit = RWBit(_CONFIG, 15, register_width=2)
124+
_reset_accumulators_bit = RWBit(_CONFIG, 14, register_width=2)
98125
"""Operating mode"""
99126
mode = RWBits(4, _ADC_CONFIG, 12, register_width=2)
127+
_alert_conv_bit = RWBit(_DIAG_ALRT, 14, register_width=2)
100128
_vbus_ct = RWBits(3, _ADC_CONFIG, 9, register_width=2)
101129
_vshunt_ct = RWBits(3, _ADC_CONFIG, 6, register_width=2)
102130
_temper_ct = RWBits(3, _ADC_CONFIG, 3, register_width=2)
@@ -117,8 +145,13 @@ def __init__(self, i2c_bus, addr=0x40):
117145
self.i2c_device = I2CDevice(i2c_bus, addr)
118146
self.buf3 = bytearray(3) # Buffer for 24-bit registers
119147
self.buf5 = bytearray(5) # Buffer for 40-bit registers
148+
# Verify manufacturer ID (should be 0x5449 for Texas Instruments)
149+
if self.manufacturer_id != 0x5449:
150+
raise RuntimeError(
151+
f"Invalid manufacturer ID: 0x{self.manufacturer_id:04X} (expected 0x5449)"
152+
)
120153
# Verify device ID
121-
dev_id = (self._device_id >> 4) & 0xFFF # Get 12-bit device ID
154+
dev_id = (self._device_id >> 4) & 0xFFF
122155
if dev_id != 0x228:
123156
raise RuntimeError(f"Failed to find INA228 - check your wiring! (Got ID: 0x{dev_id:X})")
124157
self._current_lsb = 0
@@ -131,8 +164,11 @@ def __init__(self, i2c_bus, addr=0x40):
131164
self.averaging_count = 16
132165

133166
def reset(self) -> None:
134-
"""Reset the INA228"""
135-
self._config = 0x8000
167+
"""Reset the INA228 (all registers to default values)"""
168+
self._reset_bit = True
169+
self._alert_conv_bit = True
170+
self.mode = Mode.CONTINUOUS_ALL
171+
time.sleep(0.002)
136172

137173
def _reg24(self, reg):
138174
"""Read 24-bit register"""
@@ -152,7 +188,61 @@ def _reg40(self, reg):
152188

153189
def reset_accumulators(self) -> None:
154190
"""Reset the energy and charge accumulators"""
155-
self._config = 1 << 14
191+
self._reset_accumulators_bit = True
192+
193+
@property
194+
def adc_range(self) -> int:
195+
"""
196+
ADC range.
197+
0 = ±163.84 mV
198+
1 = ±40.96 mV
199+
200+
When using the ±40.96 mV range, the shunt calibration value is automatically scaled by 4.
201+
"""
202+
return self._adc_range
203+
204+
@adc_range.setter
205+
def adc_range(self, value: int):
206+
if value not in {0, 1}:
207+
raise ValueError("ADC range must be 0 (±163.84 mV) or 1 (±40.96 mV)")
208+
self._adc_range = value
209+
self._update_calibration()
210+
211+
@property
212+
def alert_type(self) -> int:
213+
"""
214+
The alert trigger type. Use AlertType constants.
215+
Can be OR'd together for multiple triggers.
216+
217+
Example:
218+
# Single alert type
219+
sensor.alert_type = AlertType.OVERPOWER
220+
221+
# Multiple alert types
222+
sensor.alert_type = AlertType.OVERPOWER | AlertType.OVERVOLTAGE
223+
"""
224+
return self._alert_type
225+
226+
@alert_type.setter
227+
def alert_type(self, value: int):
228+
# Check if it's a valid combination of alert types
229+
if value < 0 or value > AlertType._MAX_COMBINED:
230+
raise ValueError(f"Invalid alert type value: {value}. Must be 0-0x3F")
231+
232+
# Optional: Validate that only valid bits are set
233+
valid_mask = (
234+
AlertType.CONVERSION_READY
235+
| AlertType.OVERPOWER
236+
| AlertType.UNDERVOLTAGE
237+
| AlertType.OVERVOLTAGE
238+
| AlertType.UNDERCURRENT
239+
| AlertType.OVERCURRENT
240+
)
241+
242+
if value & ~valid_mask:
243+
raise ValueError(f"Invalid alert type bits set: 0x{value:02X}")
244+
245+
self._alert_type = value
156246

157247
@property
158248
def conversion_time_bus(self) -> int:
@@ -233,7 +323,7 @@ def set_calibration_32V_2A(self) -> None:
233323
"""Configure for 32V and up to 2A measurements"""
234324
self._mode = Mode.CONTINUOUS_ALL
235325
time.sleep(0.001)
236-
self.set_shunt(0.1, 2.0)
326+
self.set_shunt(0.015, 10.0)
237327
self._vbus_ct = 5
238328
self._vshunt_ct = 5
239329
self._temper_ct = 5
@@ -295,6 +385,8 @@ def current(self) -> float:
295385
def charge(self) -> float:
296386
"""Accumulated charge in coulombs"""
297387
raw = self._reg40(_CHARGE)
388+
if raw & (1 << 39):
389+
raw |= -1 << 40
298390
return raw * self._current_lsb
299391

300392
@property
@@ -332,26 +424,20 @@ def conversion_time_temperature(self, usec: int):
332424
@property
333425
def alert_latch(self) -> bool:
334426
"""Alert latch setting. True=latched, False=transparent"""
335-
return bool(self._diag_alrt & (1 << 15))
427+
return bool(self._alert_latch_bit)
336428

337429
@alert_latch.setter
338430
def alert_latch(self, value: bool):
339-
if value:
340-
self._diag_alrt |= 1 << 15
341-
else:
342-
self._diag_alrt &= ~(1 << 15)
431+
self._alert_latch_bit = value
343432

344433
@property
345434
def alert_polarity(self) -> bool:
346435
"""Alert polarity. True=inverted, False=normal"""
347-
return bool(self._diag_alrt & (1 << 12))
436+
return bool(self._alert_polarity_bit)
348437

349438
@alert_polarity.setter
350439
def alert_polarity(self, value: bool):
351-
if value:
352-
self._diag_alrt |= 1 << 12
353-
else:
354-
self._diag_alrt &= ~(1 << 12)
440+
self._alert_polarity_bit = value
355441

356442
@property
357443
def shunt_voltage_overlimit(self) -> float:
@@ -366,7 +452,7 @@ def shunt_voltage_overlimit(self, value: float):
366452
@property
367453
def alert_flags(self) -> dict:
368454
"""
369-
Get all diagnostic and alert flags
455+
All diagnostic and alert flags
370456
371457
Returns a dictionary with the status of each flag:
372458

0 commit comments

Comments
 (0)