46
46
from micropython import const
47
47
from adafruit_bus_device .i2c_device import I2CDevice
48
48
49
+ from adafruit_register .i2c_struct import ROUnaryStruct , UnaryStruct
50
+ from adafruit_register .i2c_bits import ROBits , RWBits
51
+ from adafruit_register .i2c_bit import ROBit
52
+
49
53
__version__ = "0.0.0-auto.0"
50
54
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_INA219.git"
51
55
52
56
# Bits
53
57
# pylint: disable=bad-whitespace
54
- _READ = const ( 0x01 )
58
+ # pylint: disable=too-few-public-methods
55
59
56
60
# Config Register (R/W)
57
- _REG_CONFIG = const (0x00 )
58
- _CONFIG_RESET = const (0x8000 ) # Reset Bit
59
-
60
- _CONFIG_BVOLTAGERANGE_MASK = const (0x2000 ) # Bus Voltage Range Mask
61
- _CONFIG_BVOLTAGERANGE_16V = const (0x0000 ) # 0-16V Range
62
- _CONFIG_BVOLTAGERANGE_32V = const (0x2000 ) # 0-32V Range
63
-
64
- _CONFIG_GAIN_MASK = const (0x1800 ) # Gain Mask
65
- _CONFIG_GAIN_1_40MV = const (0x0000 ) # Gain 1, 40mV Range
66
- _CONFIG_GAIN_2_80MV = const (0x0800 ) # Gain 2, 80mV Range
67
- _CONFIG_GAIN_4_160MV = const (0x1000 ) # Gain 4, 160mV Range
68
- _CONFIG_GAIN_8_320MV = const (0x1800 ) # Gain 8, 320mV Range
69
-
70
- _CONFIG_BADCRES_MASK = const (0x0780 ) # Bus ADC Resolution Mask
71
- _CONFIG_BADCRES_9BIT = const (0x0080 ) # 9-bit bus res = 0..511
72
- _CONFIG_BADCRES_10BIT = const (0x0100 ) # 10-bit bus res = 0..1023
73
- _CONFIG_BADCRES_11BIT = const (0x0200 ) # 11-bit bus res = 0..2047
74
- _CONFIG_BADCRES_12BIT = const (0x0400 ) # 12-bit bus res = 0..4097
75
-
76
- _CONFIG_SADCRES_MASK = const (0x0078 ) # Shunt ADC Resolution and Averaging Mask
77
- _CONFIG_SADCRES_9BIT_1S_84US = const (0x0000 ) # 1 x 9-bit shunt sample
78
- _CONFIG_SADCRES_10BIT_1S_148US = const (0x0008 ) # 1 x 10-bit shunt sample
79
- _CONFIG_SADCRES_11BIT_1S_276US = const (0x0010 ) # 1 x 11-bit shunt sample
80
- _CONFIG_SADCRES_12BIT_1S_532US = const (0x0018 ) # 1 x 12-bit shunt sample
81
- _CONFIG_SADCRES_12BIT_2S_1060US = const (0x0048 ) # 2 x 12-bit shunt samples averaged together
82
- _CONFIG_SADCRES_12BIT_4S_2130US = const (0x0050 ) # 4 x 12-bit shunt samples averaged together
83
- _CONFIG_SADCRES_12BIT_8S_4260US = const (0x0058 ) # 8 x 12-bit shunt samples averaged together
84
- _CONFIG_SADCRES_12BIT_16S_8510US = const (0x0060 ) # 16 x 12-bit shunt samples averaged together
85
- _CONFIG_SADCRES_12BIT_32S_17MS = const (0x0068 ) # 32 x 12-bit shunt samples averaged together
86
- _CONFIG_SADCRES_12BIT_64S_34MS = const (0x0070 ) # 64 x 12-bit shunt samples averaged together
87
- _CONFIG_SADCRES_12BIT_128S_69MS = const (0x0078 ) # 128 x 12-bit shunt samples averaged together
88
-
89
- _CONFIG_MODE_MASK = const (0x0007 ) # Operating Mode Mask
90
- _CONFIG_MODE_POWERDOWN = const (0x0000 )
91
- _CONFIG_MODE_SVOLT_TRIGGERED = const (0x0001 )
92
- _CONFIG_MODE_BVOLT_TRIGGERED = const (0x0002 )
93
- _CONFIG_MODE_SANDBVOLT_TRIGGERED = const (0x0003 )
94
- _CONFIG_MODE_ADCOFF = const (0x0004 )
95
- _CONFIG_MODE_SVOLT_CONTINUOUS = const (0x0005 )
96
- _CONFIG_MODE_BVOLT_CONTINUOUS = const (0x0006 )
97
- _CONFIG_MODE_SANDBVOLT_CONTINUOUS = const (0x0007 )
61
+ _REG_CONFIG = const (0x00 )
62
+
63
+ class BusVoltageRange :
64
+ """Constants for ``bus_voltage_range``"""
65
+ RANGE_16V = 0x00 # set bus voltage range to 16V
66
+ RANGE_32V = 0x01 # set bus voltage range to 32V (default)
67
+
68
+ class Gain :
69
+ """Constants for ``gain``"""
70
+ DIV_1_40MV = 0x00 # shunt prog. gain set to 1, 40 mV range
71
+ DIV_2_80MV = 0x01 # shunt prog. gain set to /2, 80 mV range
72
+ DIV_4_160MV = 0x02 # shunt prog. gain set to /4, 160 mV range
73
+ DIV_8_320MV = 0x03 # shunt prog. gain set to /8, 320 mV range
74
+
75
+ class ADCResolution :
76
+ """Constants for ``bus_adc_resolution`` or ``shunt_adc_resolution``"""
77
+ ADCRES_9BIT_1S = 0x00 # 9bit, 1 sample, 84us
78
+ ADCRES_10BIT_1S = 0x01 # 10bit, 1 sample, 148us
79
+ ADCRES_11BIT_1S = 0x02 # 11 bit, 1 sample, 276us
80
+ ADCRES_12BIT_1S = 0x03 # 12 bit, 1 sample, 532us
81
+ ADCRES_12BIT_2S = 0x09 # 12 bit, 2 samples, 1.06ms
82
+ ADCRES_12BIT_4S = 0x0A # 12 bit, 4 samples, 2.13ms
83
+ ADCRES_12BIT_8S = 0x0B # 12bit, 8 samples, 4.26ms
84
+ ADCRES_12BIT_16S = 0x0C # 12bit, 16 samples, 8.51ms
85
+ ADCRES_12BIT_32S = 0x0D # 12bit, 32 samples, 17.02ms
86
+ ADCRES_12BIT_64S = 0x0E # 12bit, 64 samples, 34.05ms
87
+ ADCRES_12BIT_128S = 0x0F # 12bit, 128 samples, 68.10ms
88
+
89
+ class Mode :
90
+ """Constants for ``mode``"""
91
+ POWERDOW = 0x00 # power down
92
+ SVOLT_TRIGGERED = 0x01 # shunt voltage triggered
93
+ BVOLT_TRIGGERED = 0x02 # bus voltage triggered
94
+ SANDBVOLT_TRIGGERED = 0x03 # shunt and bus voltage triggered
95
+ ADCOFF = 0x04 # ADC off
96
+ SVOLT_CONTINUOUS = 0x05 # shunt voltage continuous
97
+ BVOLT_CONTINUOUS = 0x06 # bus voltage continuous
98
+ SANDBVOLT_CONTINUOUS = 0x07 # shunt and bus voltage continuous
98
99
99
100
# SHUNT VOLTAGE REGISTER (R)
100
- _REG_SHUNTVOLTAGE = const (0x01 )
101
+ _REG_SHUNTVOLTAGE = const (0x01 )
101
102
102
103
# BUS VOLTAGE REGISTER (R)
103
- _REG_BUSVOLTAGE = const (0x02 )
104
+ _REG_BUSVOLTAGE = const (0x02 )
104
105
105
106
# POWER REGISTER (R)
106
- _REG_POWER = const (0x03 )
107
+ _REG_POWER = const (0x03 )
107
108
108
109
# CURRENT REGISTER (R)
109
- _REG_CURRENT = const (0x04 )
110
+ _REG_CURRENT = const (0x04 )
110
111
111
112
# CALIBRATION REGISTER (R/W)
112
- _REG_CALIBRATION = const (0x05 )
113
- # pylint: enable=bad-whitespace
113
+ _REG_CALIBRATION = const (0x05 )
114
+ # pylint: enable=too-few-public-methods
115
+
114
116
115
117
def _to_signed (num ):
116
118
if num > 0x7FFF :
@@ -119,63 +121,115 @@ def _to_signed(num):
119
121
120
122
class INA219 :
121
123
"""Driver for the INA219 current sensor"""
124
+
125
+ # Basic API:
126
+
127
+ # INA219( i2c_bus, i2c_addr) Create instance of INA219 sensor
128
+ # :param i2c_bus The I2C bus the INA219is connected to
129
+ # :param i2c_addr (0x40) Address of the INA219 on the bus (default 0x40)
130
+
131
+ # shunt_voltage RO : shunt voltage scaled to Volts
132
+ # bus_voltage RO : bus voltage (V- to GND) scaled to volts (==load voltage)
133
+ # current RO : current through shunt, scaled to mA
134
+ # power RO : power consumption of the load, scaled to Watt
135
+ # set_calibration_32V_2A() Initialize chip for 32V max and up to 2A (default)
136
+ # set_calibration_32V_1A() Initialize chip for 32V max and up to 1A
137
+ # set_calibration_16V_400mA() Initialize chip for 16V max and up to 400mA
138
+
139
+ # Advanced API:
140
+ # config register break-up
141
+ # reset WO : Write Reset.RESET to reset the chip (must recalibrate)
142
+ # bus_voltage_range RW : Bus Voltage Range field (use BusVoltageRange.XXX constants)
143
+ # gain RW : Programmable Gain field (use Gain.XXX constants)
144
+ # bus_adc_resolution RW : Bus ADC resolution and averaging modes (ADCResolution.XXX)
145
+ # shunt_adc_resolution RW : Shunt ADC resolution and averaging modes (ADCResolution.XXX)
146
+ # mode RW : operating modes in config register (use Mode.XXX constants)
147
+
148
+ # raw_shunt_voltage RO : Shunt Voltage register (not scaled)
149
+ # raw_bus_voltage RO : Bus Voltage field in Bus Voltage register (not scaled)
150
+ # conversion_ready RO : Conversion Ready bit in Bus Voltage register
151
+ # overflow RO : Math Overflow bit in Bus Voltage register
152
+ # raw_power RO : Power register (not scaled)
153
+ # raw_current RO : Current register (not scaled)
154
+ # calibration RW : calibration register (note: value is cached)
155
+
122
156
def __init__ (self , i2c_bus , addr = 0x40 ):
123
157
self .i2c_device = I2CDevice (i2c_bus , addr )
124
-
125
158
self .i2c_addr = addr
126
- # Multiplier in mA used to determine current from raw reading
127
- self ._current_lsb = 0
128
- # Multiplier in W used to determine power from raw reading
129
- self ._power_lsb = 0
130
159
131
160
# Set chip to known config values to start
132
- self ._cal_value = 4096
161
+ self ._cal_value = 0
162
+ self ._current_lsb = 0
163
+ self ._power_lsb = 0
133
164
self .set_calibration_32V_2A ()
134
165
135
- def _write_register (self , reg , value ):
136
- seq = bytearray ([reg , (value >> 8 ) & 0xFF , value & 0xFF ])
137
- with self .i2c_device as i2c :
138
- i2c .write (seq )
166
+ # config register break-up
167
+ reset = RWBits ( 1 , _REG_CONFIG , 15 , 2 , False )
168
+ bus_voltage_range = RWBits ( 1 , _REG_CONFIG , 13 , 2 , False )
169
+ gain = RWBits ( 2 , _REG_CONFIG , 11 , 2 , False )
170
+ bus_adc_resolution = RWBits ( 4 , _REG_CONFIG , 7 , 2 , False )
171
+ shunt_adc_resolution = RWBits ( 4 , _REG_CONFIG , 3 , 2 , False )
172
+ mode = RWBits ( 3 , _REG_CONFIG , 0 , 2 , False )
173
+
174
+ # shunt voltage register
175
+ raw_shunt_voltage = ROUnaryStruct (_REG_SHUNTVOLTAGE , ">h" )
139
176
140
- def _read_register (self , reg ):
141
- buf = bytearray (3 )
142
- buf [0 ] = reg
143
- with self .i2c_device as i2c :
144
- i2c .write (buf , end = 1 , stop = False )
145
- i2c .readinto (buf , start = 1 )
177
+ #bus voltage register
178
+ raw_bus_voltage = ROBits ( 12 , _REG_BUSVOLTAGE , 3 , 2 , False )
179
+ conversion_ready = ROBit ( _REG_BUSVOLTAGE , 1 , 2 , False )
180
+ overflow = ROBit ( _REG_BUSVOLTAGE , 0 , 2 , False )
146
181
147
- value = (buf [1 ] << 8 ) | (buf [2 ])
148
- return value
182
+ # power and current registers
183
+ raw_power = ROUnaryStruct (_REG_POWER , ">H" )
184
+ raw_current = ROUnaryStruct (_REG_CURRENT , ">h" )
185
+
186
+ # calibration register
187
+ _raw_calibration = UnaryStruct (_REG_CALIBRATION , ">H" )
188
+
189
+ @property
190
+ def calibration (self ):
191
+ """Calibration register (cached value)"""
192
+ return self ._cal_value # return cached value
193
+
194
+ @calibration .setter
195
+ def calibration (self , cal_value ):
196
+ self ._cal_value = cal_value # value is cached for ``current`` and ``power`` properties
197
+ self ._raw_calibration = self ._cal_value
149
198
150
199
@property
151
200
def shunt_voltage (self ):
152
201
"""The shunt voltage (between V+ and V-) in Volts (so +-.327V)"""
153
- value = _to_signed (self ._read_register (_REG_SHUNTVOLTAGE ))
154
202
# The least signficant bit is 10uV which is 0.00001 volts
155
- return value * 0.00001
203
+ return self . raw_shunt_voltage * 0.00001
156
204
157
205
@property
158
206
def bus_voltage (self ):
159
207
"""The bus voltage (between V- and GND) in Volts"""
160
- raw_voltage = self ._read_register (_REG_BUSVOLTAGE )
161
-
162
208
# Shift to the right 3 to drop CNVR and OVF and multiply by LSB
163
209
# Each least signficant bit is 4mV
164
- voltage_mv = _to_signed (raw_voltage >> 3 ) * 4
165
- return voltage_mv * 0.001
210
+ return self .raw_bus_voltage * 0.004
166
211
167
212
@property
168
213
def current (self ):
169
214
"""The current through the shunt resistor in milliamps."""
170
215
# Sometimes a sharp load will reset the INA219, which will
171
216
# reset the cal register, meaning CURRENT and POWER will
172
- # not be available ... athis by always setting a cal
217
+ # not be available ... always setting a cal
173
218
# value even if it's an unfortunate extra step
174
- self ._write_register (_REG_CALIBRATION , self ._cal_value )
219
+ self ._raw_calibration = self ._cal_value
220
+ # Now we can safely read the CURRENT register!
221
+ return self .raw_current * self ._current_lsb
175
222
223
+ @property
224
+ def power (self ):
225
+ """The power through the load in Watt."""
226
+ # Sometimes a sharp load will reset the INA219, which will
227
+ # reset the cal register, meaning CURRENT and POWER will
228
+ # not be available ... always setting a cal
229
+ # value even if it's an unfortunate extra step
230
+ self ._raw_calibration = self ._cal_value
176
231
# Now we can safely read the CURRENT register!
177
- raw_current = _to_signed (self ._read_register (_REG_CURRENT ))
178
- return raw_current * self ._current_lsb
232
+ return self .raw_power * self ._power_lsb
179
233
180
234
def set_calibration_32V_2A (self ): # pylint: disable=invalid-name
181
235
"""Configures to INA219 to be able to measure up to 32V and 2A of current. Counter
@@ -249,15 +303,14 @@ def set_calibration_32V_2A(self): # pylint: disable=invalid-name
249
303
# MaximumPower = 102.4W
250
304
251
305
# Set Calibration register to 'Cal' calculated above
252
- self ._write_register ( _REG_CALIBRATION , self ._cal_value )
306
+ self ._raw_calibration = self ._cal_value
253
307
254
308
# Set Config register to take into account the settings above
255
- config = _CONFIG_BVOLTAGERANGE_32V | \
256
- _CONFIG_GAIN_8_320MV | \
257
- _CONFIG_BADCRES_12BIT | \
258
- _CONFIG_SADCRES_12BIT_1S_532US | \
259
- _CONFIG_MODE_SANDBVOLT_CONTINUOUS
260
- self ._write_register (_REG_CONFIG , config )
309
+ self .bus_voltage_range = BusVoltageRange .RANGE_32V
310
+ self .gain = Gain .DIV_8_320MV
311
+ self .bus_adc_resolution = ADCResolution .ADCRES_12BIT_1S
312
+ self .shunt_adc_resolution = ADCResolution .ADCRES_12BIT_1S
313
+ self .mode = Mode .SANDBVOLT_CONTINUOUS
261
314
262
315
def set_calibration_32V_1A (self ): # pylint: disable=invalid-name
263
316
"""Configures to INA219 to be able to measure up to 32V and 1A of current. Counter overflow
@@ -332,15 +385,14 @@ def set_calibration_32V_1A(self): # pylint: disable=invalid-name
332
385
# MaximumPower = 41.94176W
333
386
334
387
# Set Calibration register to 'Cal' calculated above
335
- self ._write_register ( _REG_CALIBRATION , self ._cal_value )
388
+ self ._raw_calibration = self ._cal_value
336
389
337
390
# Set Config register to take into account the settings above
338
- config = (_CONFIG_BVOLTAGERANGE_32V |
339
- _CONFIG_GAIN_8_320MV |
340
- _CONFIG_BADCRES_12BIT |
341
- _CONFIG_SADCRES_12BIT_1S_532US |
342
- _CONFIG_MODE_SANDBVOLT_CONTINUOUS )
343
- self ._write_register (_REG_CONFIG , config )
391
+ self .bus_voltage_range = BusVoltageRange .RANGE_32V
392
+ self .gain = Gain .DIV_8_320MV
393
+ self .bus_adc_resolution = ADCResolution .ADCRES_12BIT_1S
394
+ self .shunt_adc_resolution = ADCResolution .ADCRES_12BIT_1S
395
+ self .mode = Mode .SANDBVOLT_CONTINUOUS
344
396
345
397
def set_calibration_16V_400mA (self ): # pylint: disable=invalid-name
346
398
"""Configures to INA219 to be able to measure up to 16V and 400mA of current. Counter
@@ -416,12 +468,11 @@ def set_calibration_16V_400mA(self): # pylint: disable=invalid-name
416
468
# MaximumPower = 6.4W
417
469
418
470
# Set Calibration register to 'Cal' calculated above
419
- self ._write_register ( _REG_CALIBRATION , self ._cal_value )
471
+ self ._raw_calibration = self ._cal_value
420
472
421
473
# Set Config register to take into account the settings above
422
- config = (_CONFIG_BVOLTAGERANGE_16V |
423
- _CONFIG_GAIN_1_40MV |
424
- _CONFIG_BADCRES_12BIT |
425
- _CONFIG_SADCRES_12BIT_1S_532US |
426
- _CONFIG_MODE_SANDBVOLT_CONTINUOUS )
427
- self ._write_register (_REG_CONFIG , config )
474
+ self .bus_voltage_range = BusVoltageRange .RANGE_16V
475
+ self .gain = Gain .DIV_1_40MV
476
+ self .bus_adc_resolution = ADCResolution .ADCRES_12BIT_1S
477
+ self .shunt_adc_resolution = ADCResolution .ADCRES_12BIT_1S
478
+ self .mode = Mode .SANDBVOLT_CONTINUOUS
0 commit comments