ina228 0.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ina228/__init__.py +1 -0
- ina228/api.py +680 -0
- ina228/testing.py +12 -0
- ina228-0.0.2.dist-info/LICENSE +22 -0
- ina228-0.0.2.dist-info/METADATA +79 -0
- ina228-0.0.2.dist-info/RECORD +8 -0
- ina228-0.0.2.dist-info/WHEEL +5 -0
- ina228-0.0.2.dist-info/top_level.txt +1 -0
ina228/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .api import INA228
|
ina228/api.py
ADDED
|
@@ -0,0 +1,680 @@
|
|
|
1
|
+
"""Driver for TI INA228 with SMBUS.
|
|
2
|
+
|
|
3
|
+
Original code by @megalloid.
|
|
4
|
+
Python module created by @makise_homura.
|
|
5
|
+
|
|
6
|
+
Typical usage:
|
|
7
|
+
|
|
8
|
+
from ina228 import INA228
|
|
9
|
+
ina228 = INA228(bus, addr)
|
|
10
|
+
ina228.configure()
|
|
11
|
+
print('Voltage: ', ina228.get_vbus_voltage())
|
|
12
|
+
print('Current: ', ina228.get_current())
|
|
13
|
+
print('Power: ', ina228.get_power())
|
|
14
|
+
|
|
15
|
+
Need to fix:
|
|
16
|
+
1) Value of VSHUHT is needed to multiply to 10 that get correct value.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import time
|
|
20
|
+
|
|
21
|
+
from smbus2 import SMBus
|
|
22
|
+
|
|
23
|
+
from .testing import mock_SMBus
|
|
24
|
+
|
|
25
|
+
# INA228 Address
|
|
26
|
+
INA228_PORT = 1
|
|
27
|
+
INA228_ADDRESS = 0x45
|
|
28
|
+
INA228_SHUNT_OHMS = 0.025
|
|
29
|
+
INA228_SHUNT_TEMPCO_VALUE = 0
|
|
30
|
+
|
|
31
|
+
#############################################################
|
|
32
|
+
# INA228 Reset bytes for CONFIG [15] / [14]
|
|
33
|
+
# Decription:
|
|
34
|
+
# RST - Generates a system reset that is the same as power-on reset.
|
|
35
|
+
# RSTACC - Resets the contents of accumulation registers ENERGY and CHARGE to 0
|
|
36
|
+
#############################################################
|
|
37
|
+
INA228_RST_NBIT = 15
|
|
38
|
+
INA228_RSTACC_NBIT = 14
|
|
39
|
+
|
|
40
|
+
#############################################################
|
|
41
|
+
# INA228 Initial conversion delay CONFIG [13:6]
|
|
42
|
+
# Description: Delay for initial ADC conversion in steps of 2 ms
|
|
43
|
+
# Values:
|
|
44
|
+
# 0x0 - 0 seconds (default)
|
|
45
|
+
# 0x1 - 2 ms
|
|
46
|
+
# 0xFF - 510ms
|
|
47
|
+
#############################################################
|
|
48
|
+
INA228_CONVERSION_DELAY = 0
|
|
49
|
+
INA228_CONVDLY_NBIT = 6
|
|
50
|
+
|
|
51
|
+
#############################################################
|
|
52
|
+
# INA228 Temperature compensation CONFIG [5]
|
|
53
|
+
# Description: Enables temperature compensation of an external shunt
|
|
54
|
+
# Values:
|
|
55
|
+
# 0x0 - disabled (default)
|
|
56
|
+
# 0x1 - enabled
|
|
57
|
+
#############################################################
|
|
58
|
+
INA228_TEMP_COMP = 0
|
|
59
|
+
INA228_TEMPCOMP_NBIT = 5
|
|
60
|
+
|
|
61
|
+
#############################################################
|
|
62
|
+
# INA228 ADC Shunt full scale range selection CONFIG [4]
|
|
63
|
+
# Description: Shunt full scale range selection across IN+ and IN–.
|
|
64
|
+
# Values:
|
|
65
|
+
# 0x0 - ±163.84 mV (default)
|
|
66
|
+
# 0x1 - ±40.96 mV
|
|
67
|
+
#############################################################
|
|
68
|
+
INA228_ADCRANGE = 0
|
|
69
|
+
INA228_ADCRANGE_NBIT = 4
|
|
70
|
+
|
|
71
|
+
#############################################################
|
|
72
|
+
# INA228 ADC Mode
|
|
73
|
+
# Description: The user can set the MODE bits for continuous or
|
|
74
|
+
# triggered mode on bus voltage, shunt voltage or temperature measurement.
|
|
75
|
+
#
|
|
76
|
+
# Values:
|
|
77
|
+
# 0x0h = Shutdown
|
|
78
|
+
# 0x1h = Triggered bus voltage, single shot
|
|
79
|
+
# 0x2h = Triggered shunt voltage, single shot
|
|
80
|
+
# 0x3h = Triggered shunt voltage and bus voltage, single shot
|
|
81
|
+
# 0x4h = Triggered temperature, single shot
|
|
82
|
+
# 0x5h = Triggered temperature and bus voltage, single shot
|
|
83
|
+
# 0x6h = Triggered temperature and shunt voltage, single shot
|
|
84
|
+
# 0x7h = Triggered bus voltage, shunt voltage and temperature, single shot
|
|
85
|
+
# 0x8h = Shutdown
|
|
86
|
+
# 0x9h = Continuous bus voltage only
|
|
87
|
+
# 0xAh = Continuous shunt voltage only
|
|
88
|
+
# 0xBh = Continuous shunt and bus voltage
|
|
89
|
+
# 0xCh = Continuous temperature only
|
|
90
|
+
# 0xDh = Continuous bus voltage and temperature
|
|
91
|
+
# 0xEh = Continuous temperature and shunt voltage
|
|
92
|
+
# 0xFh = Continuous bus voltage, shunt voltage and temperature (default)
|
|
93
|
+
#############################################################
|
|
94
|
+
INA228_ADC_MODE = 0xB
|
|
95
|
+
INA228_ADC_MODE_NBIT = 12
|
|
96
|
+
|
|
97
|
+
#############################################################
|
|
98
|
+
# INA228 ADC conversion time of bus voltage meas.
|
|
99
|
+
# Description: Sets the conversion time of the bus voltage measurement
|
|
100
|
+
#
|
|
101
|
+
# Values:
|
|
102
|
+
# 0x00h = 50 μs
|
|
103
|
+
# 0x01h = 84 μs
|
|
104
|
+
# 0x02h = 150 μs
|
|
105
|
+
# 0x03h = 280 μs
|
|
106
|
+
# 0x04h = 540 μs
|
|
107
|
+
# 0x05h = 1052 μs
|
|
108
|
+
# 0x06h = 2074 μs
|
|
109
|
+
# 0x07h = 4120 μs
|
|
110
|
+
#############################################################
|
|
111
|
+
INA228_VBUS_CONV_TIME = 0x05
|
|
112
|
+
INA228_VBUS_CONV_TIME_NBIT = 0x09
|
|
113
|
+
|
|
114
|
+
#############################################################
|
|
115
|
+
# INA228 ADC conversion time of shunt voltage meas.
|
|
116
|
+
# Description: Sets the conversion time of the shunt voltage measurement
|
|
117
|
+
#
|
|
118
|
+
# Values:
|
|
119
|
+
# 0x00h = 50 μs
|
|
120
|
+
# 0x01h = 84 μs
|
|
121
|
+
# 0x02h = 150 μs
|
|
122
|
+
# 0x03h = 280 μs
|
|
123
|
+
# 0x04h = 540 μs
|
|
124
|
+
# 0x05h = 1052 μs
|
|
125
|
+
# 0x06h = 2074 μs
|
|
126
|
+
# 0x07h = 4120 μs
|
|
127
|
+
#############################################################
|
|
128
|
+
INA228_VSHCT_CONV_TIME = 0x05
|
|
129
|
+
INA228_VSHCT_CONV_TIME_NBIT = 0x06
|
|
130
|
+
|
|
131
|
+
#############################################################
|
|
132
|
+
# INA228 ADC conversion time of temperatrure meas.
|
|
133
|
+
# Description: Sets the conversion time of the temperatrure measurement
|
|
134
|
+
#
|
|
135
|
+
# Values:
|
|
136
|
+
# 0x00h = 50 μs
|
|
137
|
+
# 0x01h = 84 μs
|
|
138
|
+
# 0x02h = 150 μs
|
|
139
|
+
# 0x03h = 280 μs
|
|
140
|
+
# 0x04h = 540 μs
|
|
141
|
+
# 0x05h = 1052 μs
|
|
142
|
+
# 0x06h = 2074 μs
|
|
143
|
+
# 0x07h = 4120 μs
|
|
144
|
+
#############################################################
|
|
145
|
+
INA228_VTCT_CONV_TIME = 0x05
|
|
146
|
+
INA228_VTCT_CONV_TIME_NBIT = 0x03
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
#############################################################
|
|
150
|
+
# INA228 ADC sample averaging count.
|
|
151
|
+
#
|
|
152
|
+
# Values:
|
|
153
|
+
# 0x0h = 1
|
|
154
|
+
# 0x1h = 4
|
|
155
|
+
# 0x2h = 16
|
|
156
|
+
# 0x3h = 64
|
|
157
|
+
# 0x4h = 128
|
|
158
|
+
# 0x5h = 256
|
|
159
|
+
# 0x6h = 512
|
|
160
|
+
# 0x7h = 1024
|
|
161
|
+
#############################################################
|
|
162
|
+
INA228_ADC_AVG = 3
|
|
163
|
+
INA228_AVG_NBIT = 0
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
#############################################################
|
|
167
|
+
# INA228 ADC alerts signal
|
|
168
|
+
#############################################################
|
|
169
|
+
INA228_ALERT_MEMSTAT = 0
|
|
170
|
+
INA228_ALERT_CNVRF = 1
|
|
171
|
+
INA228_ALERT_POL = 2
|
|
172
|
+
INA228_ALERT_BUSUL = 3
|
|
173
|
+
INA228_ALERT_BUSOL = 4
|
|
174
|
+
INA228_ALERT_SHNTUL = 5
|
|
175
|
+
INA228_ALERT_SHNTOL = 6
|
|
176
|
+
INA228_ALERT_TMPOL = 7
|
|
177
|
+
INA228_ALERT_MATHOF = 9
|
|
178
|
+
INA228_ALERT_CHARGEOF = 10
|
|
179
|
+
INA228_ALERT_ENERGYOF = 11
|
|
180
|
+
INA228_ALERT_APOL = 12
|
|
181
|
+
INA228_ALERT_SLOWALERT = 13
|
|
182
|
+
INA228_ALERT_CNVR = 14
|
|
183
|
+
INA228_ALERT_ALATCH = 15
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
class INA228:
|
|
187
|
+
"""Main INA228 interface"""
|
|
188
|
+
|
|
189
|
+
__INA228_CONFIG = 0x00
|
|
190
|
+
__INA228_ADC_CONFIG = 0x01
|
|
191
|
+
__INA228_SHUNT_CAL = 0x02
|
|
192
|
+
__INA228_SHUNT_TEMPCO = 0x03
|
|
193
|
+
__INA228_VSHUNT = 0x04
|
|
194
|
+
__INA228_VBUS = 0x05
|
|
195
|
+
__INA228_DIETEMP = 0x06
|
|
196
|
+
__INA228_CURRENT = 0x07
|
|
197
|
+
__INA228_POWER = 0x08
|
|
198
|
+
__INA228_ENERGY = 0x09
|
|
199
|
+
__INA228_CHARGE = 0x0A
|
|
200
|
+
__INA228_DIAG_ALRT = 0x0B
|
|
201
|
+
__INA228_SOVL = 0x0C
|
|
202
|
+
__INA228_SUVL = 0x0D
|
|
203
|
+
__INA228_BOVL = 0x0E
|
|
204
|
+
__INA228_BUVL = 0x0F
|
|
205
|
+
__INA228_TEMP_LIMIT = 0x10
|
|
206
|
+
__INA228_PWR_LIMIT = 0x11
|
|
207
|
+
__INA228_MANUFACTURER_ID = 0x3E
|
|
208
|
+
__INA228_DEVICE_ID = 0x3F
|
|
209
|
+
|
|
210
|
+
def __init__(self, busnum = INA228_PORT, address = INA228_ADDRESS, shunt_ohms = INA228_SHUNT_OHMS, stub_regmap = None):
|
|
211
|
+
"""Creates INA228 instance.
|
|
212
|
+
|
|
213
|
+
Args:
|
|
214
|
+
busnum: SMBus bus number INA228 connected to.
|
|
215
|
+
address: SMBus slave address of INA228.
|
|
216
|
+
shunt_ohms: Shunt value for current measurements.
|
|
217
|
+
stub_regmap: Used in tests to emulate real INA228.
|
|
218
|
+
|
|
219
|
+
Returns:
|
|
220
|
+
Uninitialized INA228 instance linked to specific SMBus location.
|
|
221
|
+
|
|
222
|
+
Raises:
|
|
223
|
+
Any exception smbus2.SMBus() may raise.
|
|
224
|
+
"""
|
|
225
|
+
|
|
226
|
+
self._address = address
|
|
227
|
+
self._i2c = mock_SMBus(stub_regmap) if stub_regmap else SMBus(busnum)
|
|
228
|
+
self._shunt_ohms = shunt_ohms
|
|
229
|
+
self._stub_regmap = stub_regmap
|
|
230
|
+
|
|
231
|
+
def __convert2comp2float(self, twocompdata, nrofbit, factor):
|
|
232
|
+
|
|
233
|
+
isnegative = 1
|
|
234
|
+
isnegative = (isnegative << (nrofbit - 1))
|
|
235
|
+
|
|
236
|
+
dietemp = twocompdata
|
|
237
|
+
|
|
238
|
+
if(dietemp > isnegative):
|
|
239
|
+
dietemp = (dietemp - (2*isnegative)) * factor
|
|
240
|
+
else:
|
|
241
|
+
dietemp = (dietemp * factor)
|
|
242
|
+
|
|
243
|
+
return dietemp
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def __binary_as_string(self, register_value):
|
|
247
|
+
|
|
248
|
+
return bin(register_value)[2:].zfill(16)
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def __to_bytes(self, register_value):
|
|
252
|
+
|
|
253
|
+
return [(register_value >> 8) & 0xFF, register_value & 0xFF]
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def read_register40(self, register):
|
|
257
|
+
|
|
258
|
+
result = self._i2c.read_i2c_block_data(self._address, register, 5)
|
|
259
|
+
|
|
260
|
+
register_value = ((result[0] << 32) & 0xFF00000000) | ((result[1] << 24) & 0xFF000000) | ((result[2] << 16) & 0xFF0000) | ((result[3] << 8) & 0xFF00) | (result[4] & 0xFF)
|
|
261
|
+
|
|
262
|
+
#print("Read register 16 bits - 0x%02X: 0x%05X = 0b%s" %(register, register_value, self.__binary_as_string(register_value)))
|
|
263
|
+
|
|
264
|
+
return register_value
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def read_register24(self, register):
|
|
268
|
+
|
|
269
|
+
result = self._i2c.read_i2c_block_data(self._address, register, 3)
|
|
270
|
+
|
|
271
|
+
register_value = ((result[0] << 16) & 0xFF0000) | ((result[1] << 8) & 0xFF00) | (result[2] & 0xFF)
|
|
272
|
+
|
|
273
|
+
#print("Read register 24 bits - 0x%02X: 0x%05X = 0b%s" %(register, register_value, self.__binary_as_string(register_value)))
|
|
274
|
+
|
|
275
|
+
return register_value
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def read_register16(self, register):
|
|
279
|
+
|
|
280
|
+
result = self._i2c.read_i2c_block_data(self._address, register, 2)
|
|
281
|
+
|
|
282
|
+
register_value = ((result[0] << 8) & 0xFF00) | (result[1] & 0xFF)
|
|
283
|
+
|
|
284
|
+
#print("Read register 16 bits - 0x%02X: 0x%04X = 0b%s" %(register, register_value, self.__binary_as_string(register_value)))
|
|
285
|
+
|
|
286
|
+
return register_value
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
def write_register16(self, register, register_value):
|
|
290
|
+
|
|
291
|
+
register_bytes = self.__to_bytes(register_value)
|
|
292
|
+
|
|
293
|
+
#print("Write register 16 bits 0x%02X: 0x%02X 0b%s" % (register, register_value, self.__binary_as_string(register_value)))
|
|
294
|
+
|
|
295
|
+
self._i2c.write_i2c_block_data(self._address, register, register_bytes)
|
|
296
|
+
|
|
297
|
+
# self._i2c.write_word_data(self._address, register, register_value)
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
def get_current_lsb(self):
|
|
301
|
+
|
|
302
|
+
if(INA228_ADCRANGE == 0):
|
|
303
|
+
temp = 163.84e-3
|
|
304
|
+
else:
|
|
305
|
+
temp = 40.96e-3
|
|
306
|
+
|
|
307
|
+
current_lsb = (temp / INA228_SHUNT_OHMS) / 524288
|
|
308
|
+
|
|
309
|
+
return current_lsb
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
def get_shunt_conv_factor(self):
|
|
313
|
+
|
|
314
|
+
if(INA228_ADCRANGE == 0):
|
|
315
|
+
shunt_conv_factor = 1.25e-6
|
|
316
|
+
else:
|
|
317
|
+
shunt_conv_factor = 5.0e-6
|
|
318
|
+
|
|
319
|
+
return shunt_conv_factor
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def reset_all(self):
|
|
323
|
+
|
|
324
|
+
config = self.read_register16(self.__INA228_CONFIG)
|
|
325
|
+
|
|
326
|
+
data = 1 << INA228_RST_NBIT
|
|
327
|
+
|
|
328
|
+
config = config | data
|
|
329
|
+
|
|
330
|
+
self.write_register16(self.__INA228_CONFIG, config)
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def reset_energy(self):
|
|
334
|
+
|
|
335
|
+
config = self.read_register16(self.__INA228_CONFIG)
|
|
336
|
+
|
|
337
|
+
data = 1 << INA228_RSTACC_NBIT
|
|
338
|
+
|
|
339
|
+
config = config | data
|
|
340
|
+
|
|
341
|
+
self.write_register16(self.__INA228_CONFIG, config)
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
def set_config(self):
|
|
345
|
+
|
|
346
|
+
# Write settings to CONFIG register
|
|
347
|
+
|
|
348
|
+
config = self.read_register16(self. __INA228_CONFIG)
|
|
349
|
+
|
|
350
|
+
config = config | (INA228_CONVERSION_DELAY << INA228_CONVDLY_NBIT) | (INA228_TEMP_COMP << INA228_TEMPCOMP_NBIT) | (INA228_ADCRANGE << INA228_ADCRANGE_NBIT)
|
|
351
|
+
|
|
352
|
+
self.write_register16(self.__INA228_CONFIG, config)
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
def set_adc_config(self):
|
|
356
|
+
|
|
357
|
+
# Write settings to ADC CONFIG register
|
|
358
|
+
|
|
359
|
+
config = self.read_register16(self. __INA228_ADC_CONFIG)
|
|
360
|
+
|
|
361
|
+
config = config | (INA228_ADC_MODE << INA228_ADC_MODE_NBIT) | (INA228_VBUS_CONV_TIME << INA228_VBUS_CONV_TIME_NBIT ) | (INA228_VSHCT_CONV_TIME << INA228_VSHCT_CONV_TIME_NBIT) | (INA228_VTCT_CONV_TIME << INA228_VTCT_CONV_TIME_NBIT) | (INA228_ADC_AVG << INA228_AVG_NBIT)
|
|
362
|
+
|
|
363
|
+
self.write_register16(self.__INA228_ADC_CONFIG, config)
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
def shunt_calib(self):
|
|
367
|
+
|
|
368
|
+
calib_value = int(13107.2e6 * self.get_current_lsb() * INA228_SHUNT_OHMS)
|
|
369
|
+
|
|
370
|
+
self.write_register16(self.__INA228_SHUNT_CAL, calib_value)
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
def shunt_tempco(self):
|
|
374
|
+
|
|
375
|
+
self.write_register16(self.__INA228_SHUNT_TEMPCO, INA228_SHUNT_TEMPCO_VALUE)
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
def configure(self):
|
|
379
|
+
"""Performs initial INA228 configuration.
|
|
380
|
+
|
|
381
|
+
Always call this prior to get any data from INA228.
|
|
382
|
+
"""
|
|
383
|
+
|
|
384
|
+
self.reset_all()
|
|
385
|
+
|
|
386
|
+
self.set_config()
|
|
387
|
+
self.set_adc_config()
|
|
388
|
+
|
|
389
|
+
self.shunt_calib()
|
|
390
|
+
self.shunt_tempco()
|
|
391
|
+
|
|
392
|
+
time.sleep(0.1)
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
def get_shunt_voltage(self):
|
|
396
|
+
"""Read voltage on the shunt resistor.
|
|
397
|
+
|
|
398
|
+
Returns:
|
|
399
|
+
Voltage in volts.
|
|
400
|
+
"""
|
|
401
|
+
|
|
402
|
+
if(INA228_ADCRANGE == 1):
|
|
403
|
+
conversion_factor = 312.5e-9 # nV/LSB
|
|
404
|
+
else:
|
|
405
|
+
conversion_factor = 78.125e-9 # nV/LSB
|
|
406
|
+
|
|
407
|
+
raw = self.read_register24(self.__INA228_VSHUNT)
|
|
408
|
+
|
|
409
|
+
vshunt = (self.__convert2comp2float(raw >> 4, 20, conversion_factor)) * 10 # Find and fix *10
|
|
410
|
+
|
|
411
|
+
return vshunt
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
def get_vbus_voltage(self):
|
|
415
|
+
"""Read voltage on the V+/V- terminals.
|
|
416
|
+
|
|
417
|
+
Returns:
|
|
418
|
+
Voltage in volts.
|
|
419
|
+
"""
|
|
420
|
+
|
|
421
|
+
conversion_factor = 195.3125e-6 # uV/LSB
|
|
422
|
+
|
|
423
|
+
raw = self.read_register24(self.__INA228_VBUS)
|
|
424
|
+
|
|
425
|
+
vbus = self.__convert2comp2float(raw >> 4, 20, conversion_factor)
|
|
426
|
+
|
|
427
|
+
return vbus
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
def get_temp(self):
|
|
431
|
+
"""Read die temperature.
|
|
432
|
+
|
|
433
|
+
Returns:
|
|
434
|
+
Temperature in Celsius.
|
|
435
|
+
"""
|
|
436
|
+
|
|
437
|
+
conversion_factor = 7.8125e-3
|
|
438
|
+
|
|
439
|
+
raw = self.read_register16(self.__INA228_DIETEMP)
|
|
440
|
+
|
|
441
|
+
temp = self.__convert2comp2float(raw, 16, conversion_factor)
|
|
442
|
+
|
|
443
|
+
return temp
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
def get_current(self):
|
|
447
|
+
"""Read current through I+/I- terminals.
|
|
448
|
+
|
|
449
|
+
Returns:
|
|
450
|
+
Current in amperes.
|
|
451
|
+
"""
|
|
452
|
+
|
|
453
|
+
raw = self.read_register24(self.__INA228_CURRENT)
|
|
454
|
+
|
|
455
|
+
current = self.__convert2comp2float(raw >> 4, 20, self.get_current_lsb())
|
|
456
|
+
|
|
457
|
+
return current
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
def get_power(self):
|
|
461
|
+
"""Read calculated power (a product of voltage and current).
|
|
462
|
+
|
|
463
|
+
Returns:
|
|
464
|
+
Power in watts.
|
|
465
|
+
"""
|
|
466
|
+
|
|
467
|
+
current_lsb = self.get_current_lsb()
|
|
468
|
+
|
|
469
|
+
raw = self.read_register24(self.__INA228_POWER)
|
|
470
|
+
|
|
471
|
+
power = (3.2 * raw * current_lsb)
|
|
472
|
+
|
|
473
|
+
return power
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
def get_energy(self):
|
|
477
|
+
"""Read integral energy (a product of power and time).
|
|
478
|
+
|
|
479
|
+
Returns:
|
|
480
|
+
Energy in joules.
|
|
481
|
+
"""
|
|
482
|
+
|
|
483
|
+
raw = self.read_register40(self.__INA228_ENERGY)
|
|
484
|
+
|
|
485
|
+
energy = raw * 3.2 * 16 * self.get_current_lsb()
|
|
486
|
+
|
|
487
|
+
return energy
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
def get_charge(self):
|
|
491
|
+
"""Read charge spent (a product of current and time).
|
|
492
|
+
|
|
493
|
+
Returns:
|
|
494
|
+
Charge in coulombs.
|
|
495
|
+
"""
|
|
496
|
+
|
|
497
|
+
raw = self.read_register40(self.__INA228_CHARGE)
|
|
498
|
+
|
|
499
|
+
return raw
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
def get_diag_alerts(self, alert):
|
|
503
|
+
"""Read current through I+/I- terminals.
|
|
504
|
+
|
|
505
|
+
Args:
|
|
506
|
+
alert: Alert to read (any of INA228_ALERT_* constants).
|
|
507
|
+
|
|
508
|
+
Returns:
|
|
509
|
+
String representation of specific alert, or empty string if nothing to tell (e.g. no chosen alert).
|
|
510
|
+
"""
|
|
511
|
+
|
|
512
|
+
raw = self.read_register16(self.__INA228_DIAG_ALRT)
|
|
513
|
+
|
|
514
|
+
if(alert == INA228_ALERT_ALATCH):
|
|
515
|
+
if (raw & 0x1) == 0x0:
|
|
516
|
+
return 'MEMSTAT: Checksum error is detected in the device trim memory space'
|
|
517
|
+
|
|
518
|
+
elif(alert == INA228_ALERT_CNVRF):
|
|
519
|
+
if (raw & 0x2) == 0x1:
|
|
520
|
+
return 'CNVRF: Conversion is completed'
|
|
521
|
+
|
|
522
|
+
elif(alert == INA228_ALERT_BUSUL):
|
|
523
|
+
if (raw & 0x4) == 0x1:
|
|
524
|
+
return 'BUSUL: Bus voltage measurement falls below the threshold limit in the bus under-limit register'
|
|
525
|
+
|
|
526
|
+
elif(alert == INA228_ALERT_BUSOL):
|
|
527
|
+
if (raw & 0x8) == 0x1:
|
|
528
|
+
return 'BUSOL: Bus voltage measurement exceeds the threshold limit in the bus over-limit register'
|
|
529
|
+
|
|
530
|
+
elif(alert == INA228_ALERT_SHNTUL):
|
|
531
|
+
if (raw & 0x10) == 0x1:
|
|
532
|
+
return 'SHNTUL: Shunt voltage measurement falls below the threshold limit in the shunt under-limit register'
|
|
533
|
+
|
|
534
|
+
elif(alert == INA228_ALERT_SHNTOL):
|
|
535
|
+
if (raw & 0x40) == 0x1:
|
|
536
|
+
return 'SHNTOL: Shunt voltage measurement exceeds the threshold limit in the shunt over-limit register'
|
|
537
|
+
|
|
538
|
+
elif(alert == INA228_ALERT_TMPOL):
|
|
539
|
+
if (raw & 0x80) == 0x1:
|
|
540
|
+
return 'TMPOL: Temperature measurement exceeds the threshold limit in the temperature over-limit register'
|
|
541
|
+
|
|
542
|
+
elif(alert == INA228_ALERT_MATHOF):
|
|
543
|
+
if (raw & 0x100) == 0x1:
|
|
544
|
+
return 'MATHOF: Arithmetic operation resulted in an overflow error'
|
|
545
|
+
|
|
546
|
+
elif(alert == INA228_ALERT_CHARGEOF):
|
|
547
|
+
if (raw & 0x200) == 0x1:
|
|
548
|
+
return 'CHARGEOF: 40 bit CHARGE register has overflowed'
|
|
549
|
+
|
|
550
|
+
elif(alert == INA228_ALERT_ENERGYOF):
|
|
551
|
+
if (raw & 0x400) == 0x1:
|
|
552
|
+
return 'ENERGYOF: 40 bit ENERGY register has overflowed'
|
|
553
|
+
|
|
554
|
+
elif(alert == INA228_ALERT_APOL):
|
|
555
|
+
if (raw & 0x800) == 0x1:
|
|
556
|
+
return 'APOL: Alert pin polarity inverted (active-high, open-drain)'
|
|
557
|
+
else:
|
|
558
|
+
return 'APOL: Alert pin polarity normale (active-low, open-drain)'
|
|
559
|
+
|
|
560
|
+
elif(alert == INA228_ALERT_SLOWALERT):
|
|
561
|
+
if (raw & 0x2000) == 0x1:
|
|
562
|
+
return 'SLOWALERT: ALERT function is asserted on the completed averaged value. ALERT comparison on averaged value'
|
|
563
|
+
else:
|
|
564
|
+
return 'SLOWALERT: ALERT comparison on non-averaged (ADC) value'
|
|
565
|
+
|
|
566
|
+
elif(alert == INA228_ALERT_CNVR):
|
|
567
|
+
if (raw & 0x4000) == 0x1:
|
|
568
|
+
return 'CNVR: Alert pin to be asserted when the Conversion Ready Flag (bit 1) is asserted, indicating that a conversion cycle has completed. Enables conversion ready flag on ALERT pin'
|
|
569
|
+
else:
|
|
570
|
+
return 'CNVR: Disable conversion ready flag on ALERT pin'
|
|
571
|
+
|
|
572
|
+
elif(alert == INA228_ALERT_ALATCH):
|
|
573
|
+
if (raw & 0x8000) == 0x1:
|
|
574
|
+
return 'ALATCH: Latched'
|
|
575
|
+
else:
|
|
576
|
+
return 'ALATCH: Transparent'
|
|
577
|
+
|
|
578
|
+
return ''
|
|
579
|
+
|
|
580
|
+
|
|
581
|
+
def set_shunt_overvoltage(self, value):
|
|
582
|
+
|
|
583
|
+
if (value >= 0):
|
|
584
|
+
|
|
585
|
+
data = (value * INA228_SHUNT_OHMS) / self.get_shunt_conv_factor()
|
|
586
|
+
|
|
587
|
+
else:
|
|
588
|
+
|
|
589
|
+
value_temp = value * (-1);
|
|
590
|
+
|
|
591
|
+
data = (value_temp * INA228_SHUNT_OHMS) / self.get_shunt_conv_factor()
|
|
592
|
+
data = ~data
|
|
593
|
+
data = data + 1
|
|
594
|
+
|
|
595
|
+
self.read_register16(self.__INA228_SOVL)
|
|
596
|
+
|
|
597
|
+
self.write_register16(self.__INA228_SOVL, data)
|
|
598
|
+
|
|
599
|
+
|
|
600
|
+
def set_shunt_undervoltage(self, value):
|
|
601
|
+
|
|
602
|
+
if (value >= 0):
|
|
603
|
+
|
|
604
|
+
data = (value * INA228_SHUNT_OHMS) / self.get_shunt_conv_factor()
|
|
605
|
+
|
|
606
|
+
else:
|
|
607
|
+
|
|
608
|
+
value_temp = value * (-1);
|
|
609
|
+
|
|
610
|
+
data = (value_temp * INA228_SHUNT_OHMS) / self.get_shunt_conv_factor()
|
|
611
|
+
data = ~data
|
|
612
|
+
data = data + 1
|
|
613
|
+
|
|
614
|
+
self.read_register16(self.__INA228_SUVL)
|
|
615
|
+
|
|
616
|
+
self.write_register16(self.__INA228_SUVL, data)
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
def set_bus_overvoltage(self, value):
|
|
620
|
+
|
|
621
|
+
data = value / (16 * 195.3125e-6)
|
|
622
|
+
|
|
623
|
+
self.read_register16(self.__INA228_BOVL)
|
|
624
|
+
|
|
625
|
+
self.write_register16(self.__INA228_BOVL, data)
|
|
626
|
+
|
|
627
|
+
|
|
628
|
+
def set_bus_undervoltage(self, value):
|
|
629
|
+
|
|
630
|
+
data = value / (16 * 195.3125e-6)
|
|
631
|
+
|
|
632
|
+
self.read_register16(self.__INA228_BUVL)
|
|
633
|
+
|
|
634
|
+
self.write_register16(self.__INA228_BUVL, data)
|
|
635
|
+
|
|
636
|
+
|
|
637
|
+
def set_temp_limit(self, value, consta):
|
|
638
|
+
|
|
639
|
+
data = value / (16 * consta)
|
|
640
|
+
|
|
641
|
+
self.read_register16(self.__INA228_TEMP_LIMIT)
|
|
642
|
+
|
|
643
|
+
self.write_register16(self.__INA228_TEMP_LIMIT, data)
|
|
644
|
+
|
|
645
|
+
|
|
646
|
+
def set_power_overlimit(self, value, consta):
|
|
647
|
+
|
|
648
|
+
data = value / (16 * consta)
|
|
649
|
+
|
|
650
|
+
self.read_register16(self.__INA228_PWR_LIMIT)
|
|
651
|
+
|
|
652
|
+
self.write_register16(self.__INA228_PWR_LIMIT, data)
|
|
653
|
+
|
|
654
|
+
|
|
655
|
+
def get_manufacturer_id(self):
|
|
656
|
+
"""Read manufacturer ID.
|
|
657
|
+
|
|
658
|
+
Returns:
|
|
659
|
+
A tuple of (hex, char) manufacturer ID.
|
|
660
|
+
"""
|
|
661
|
+
|
|
662
|
+
raw_id = self.read_register16(self.__INA228_MANUFACTURER_ID)
|
|
663
|
+
|
|
664
|
+
first_byte = (raw_id >> 8) & 0xFF
|
|
665
|
+
second_byte = (raw_id & 0xFF)
|
|
666
|
+
|
|
667
|
+
return (hex(raw_id), chr(first_byte),chr(second_byte))
|
|
668
|
+
|
|
669
|
+
|
|
670
|
+
def get_deviceid(self):
|
|
671
|
+
"""Read device ID.
|
|
672
|
+
|
|
673
|
+
Returns:
|
|
674
|
+
A tuple of (device ID, device revision).
|
|
675
|
+
"""
|
|
676
|
+
|
|
677
|
+
raw_id = self.read_register16(self.__INA228_DEVICE_ID)
|
|
678
|
+
|
|
679
|
+
return (hex(raw_id >> 4), hex(raw_id & 0xF))
|
|
680
|
+
|
ina228/testing.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
class mock_SMBus:
|
|
2
|
+
|
|
3
|
+
def __init__(self, regmap):
|
|
4
|
+
self._regmap = regmap
|
|
5
|
+
|
|
6
|
+
def read_i2c_block_data(self, address, register, length):
|
|
7
|
+
assert(len(self._regmap[register]) == length)
|
|
8
|
+
return self._regmap[register]
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def write_i2c_block_data(self, address, register, bytes):
|
|
12
|
+
pass
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021 Andrey Zaostrovnykh
|
|
4
|
+
Copyright (c) 2026 Igor Molchanov
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: ina228
|
|
3
|
+
Version: 0.0.2
|
|
4
|
+
Summary: Driver for TI INA228 with SMBUS
|
|
5
|
+
Author-email: Andrey Zaostrovnykh <megalloid@gmail.com>, Igor Molchanov <akemi_homura@kurisa.ch>
|
|
6
|
+
Maintainer-email: Igor Molchanov <akemi_homura@kurisa.ch>
|
|
7
|
+
Project-URL: Repository, https://github.com/makise-homura/INA228/
|
|
8
|
+
Project-URL: Issues, https://github.com/makise-homura/INA228/issues/
|
|
9
|
+
Keywords: electronics,sensing,TI,home automation,smbus,ina2xx
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Topic :: Home Automation
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
23
|
+
Classifier: Operating System :: OS Independent
|
|
24
|
+
Requires-Python: >=3.7
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: smbus2
|
|
28
|
+
|
|
29
|
+
# INA228
|
|
30
|
+
Driver for TI INA228 with SMBUS
|
|
31
|
+
|
|
32
|
+
## Building
|
|
33
|
+
|
|
34
|
+
Just run:
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
python3 -m build
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Requirements
|
|
41
|
+
|
|
42
|
+
For now, it relies on `smbus2` module.
|
|
43
|
+
|
|
44
|
+
## Testing
|
|
45
|
+
|
|
46
|
+
After building the package, create venv:
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
python3 -m venv .venv
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Install the module:
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
.venv/bin/pip install dist/ina228-*.whl --force-reinstall
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Run the test:
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
.venv/bin/python tests/test.py
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Test will use supplied `stub_regmap.py`, not the real INA228.
|
|
65
|
+
If you want your own one, generate it by running `./map.sh > stub_regmap.py` on the system with live INA228.
|
|
66
|
+
You may need to edit bus number and slave address in `map.sh` though.
|
|
67
|
+
And remember to install `i2cget` with something like `apt install i2c-tools` prior to running this.
|
|
68
|
+
|
|
69
|
+
If you want to use pytest, install it into venv:
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
.venv/bin/pip install pytest
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
And then run:
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
.venv/bin/python -m pytest
|
|
79
|
+
```
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
ina228/__init__.py,sha256=8JLgIWJkB54nnPLreEUfPYPPks_-AwulLe5go8a09j4,24
|
|
2
|
+
ina228/api.py,sha256=8Lda-3PTBin8inFLw7m56FCwlhTQVQlFva5Owyf-OO8,19457
|
|
3
|
+
ina228/testing.py,sha256=kf_aPoTSo_-371ogILU2K676osttf1dGUr32JgM7bdQ,313
|
|
4
|
+
ina228-0.0.2.dist-info/LICENSE,sha256=ova-szagjnCitj5xXKMqZKu2qP2_5akEGbKJItdkw_w,1110
|
|
5
|
+
ina228-0.0.2.dist-info/METADATA,sha256=QYqm-gBjesh1wiPbQIdU2qXqqsGKmGDR0MuAPwRsmps,2083
|
|
6
|
+
ina228-0.0.2.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
7
|
+
ina228-0.0.2.dist-info/top_level.txt,sha256=g1ytYWUNG8uzFE-bxtmQp8LBYNGILASOvmhdQ_fh6As,7
|
|
8
|
+
ina228-0.0.2.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ina228
|