ina228 0.0.2__tar.gz

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-0.0.2/LICENSE ADDED
@@ -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.
ina228-0.0.2/PKG-INFO ADDED
@@ -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
+ ```
ina228-0.0.2/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # INA228
2
+ Driver for TI INA228 with SMBUS
3
+
4
+ ## Building
5
+
6
+ Just run:
7
+
8
+ ```
9
+ python3 -m build
10
+ ```
11
+
12
+ ## Requirements
13
+
14
+ For now, it relies on `smbus2` module.
15
+
16
+ ## Testing
17
+
18
+ After building the package, create venv:
19
+
20
+ ```
21
+ python3 -m venv .venv
22
+ ```
23
+
24
+ Install the module:
25
+
26
+ ```
27
+ .venv/bin/pip install dist/ina228-*.whl --force-reinstall
28
+ ```
29
+
30
+ Run the test:
31
+
32
+ ```
33
+ .venv/bin/python tests/test.py
34
+ ```
35
+
36
+ Test will use supplied `stub_regmap.py`, not the real INA228.
37
+ If you want your own one, generate it by running `./map.sh > stub_regmap.py` on the system with live INA228.
38
+ You may need to edit bus number and slave address in `map.sh` though.
39
+ And remember to install `i2cget` with something like `apt install i2c-tools` prior to running this.
40
+
41
+ If you want to use pytest, install it into venv:
42
+
43
+ ```
44
+ .venv/bin/pip install pytest
45
+ ```
46
+
47
+ And then run:
48
+
49
+ ```
50
+ .venv/bin/python -m pytest
51
+ ```
@@ -0,0 +1,46 @@
1
+ [build-system]
2
+ requires = ["setuptools==75.8.0"]
3
+
4
+ [project]
5
+ name = "ina228"
6
+ version = "0.0.2"
7
+ authors = [
8
+ { name="Andrey Zaostrovnykh", email="megalloid@gmail.com" },
9
+ { name="Igor Molchanov", email="akemi_homura@kurisa.ch" },
10
+ ]
11
+ maintainers = [
12
+ { name="Igor Molchanov", email="akemi_homura@kurisa.ch" },
13
+ ]
14
+ description = "Driver for TI INA228 with SMBUS"
15
+ readme = "README.md"
16
+ requires-python = ">=3.7"
17
+ keywords = ["electronics", "sensing", "TI", "home automation", "smbus", "ina2xx"]
18
+ classifiers = [
19
+ "Development Status :: 4 - Beta",
20
+ "Intended Audience :: Developers",
21
+ "Topic :: Home Automation",
22
+ "Programming Language :: Python :: 3",
23
+ "Programming Language :: Python :: 3.7",
24
+ "Programming Language :: Python :: 3.8",
25
+ "Programming Language :: Python :: 3.9",
26
+ "Programming Language :: Python :: 3.10",
27
+ "Programming Language :: Python :: 3.11",
28
+ "Programming Language :: Python :: 3.12",
29
+ "Programming Language :: Python :: 3.13",
30
+ "Programming Language :: Python :: 3.14",
31
+ "Programming Language :: Python :: 3.15",
32
+ "Operating System :: OS Independent",
33
+ ]
34
+ license = {file = "LICENSE*"}
35
+ dynamic = ["dependencies"]
36
+
37
+ [tool.setuptools.dynamic]
38
+ dependencies = {file = ["requirements.txt"]}
39
+
40
+ [project.urls]
41
+ Repository = "https://github.com/makise-homura/INA228/"
42
+ Issues = "https://github.com/makise-homura/INA228/issues/"
43
+
44
+ [tool.pytest]
45
+ minversion = "9.0"
46
+ testpaths = ["tests/test.py"]
@@ -0,0 +1 @@
1
+ smbus2
ina228-0.0.2/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1 @@
1
+ from .api import INA228
@@ -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
+
@@ -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,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,13 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ requirements.txt
5
+ src/ina228/__init__.py
6
+ src/ina228/api.py
7
+ src/ina228/testing.py
8
+ src/ina228.egg-info/PKG-INFO
9
+ src/ina228.egg-info/SOURCES.txt
10
+ src/ina228.egg-info/dependency_links.txt
11
+ src/ina228.egg-info/requires.txt
12
+ src/ina228.egg-info/top_level.txt
13
+ tests/test.py
@@ -0,0 +1 @@
1
+ smbus2
@@ -0,0 +1 @@
1
+ ina228
@@ -0,0 +1,43 @@
1
+ def test_main():
2
+ from ina228 import INA228
3
+ from datetime import datetime, UTC
4
+
5
+ from stub_regmap import stub_regmap
6
+
7
+ ina228 = INA228(stub_regmap=stub_regmap)
8
+
9
+ ina228.configure()
10
+
11
+ i = 0
12
+
13
+ print('Manufacturer ID (HEX): {}, (CHAR): {}'.format(*ina228.get_manufacturer_id()))
14
+
15
+ print('Device ID: {}, Revision: {}'.format(*ina228.get_deviceid()))
16
+
17
+ while True:
18
+
19
+ print('VBUS voltage: ', ina228.get_vbus_voltage())
20
+
21
+ print('Current: ', ina228.get_current())
22
+
23
+ print('Power: ', ina228.get_power())
24
+
25
+ print('Shunt voltage: ', ina228.get_shunt_voltage())
26
+
27
+ print('Die temp: ', ina228.get_temp())
28
+
29
+ print('Energy: ', ina228.get_energy())
30
+
31
+ print('Charge: ', ina228.get_charge())
32
+
33
+ if i < 1000:
34
+
35
+ i = i +1
36
+ print(i, datetime.now(UTC).strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
37
+
38
+ else:
39
+
40
+ break
41
+
42
+ if __name__ =="__main__":
43
+ test_main()