Open BritishTechGuru opened 2 years ago
I have never tried my library on the pico, can you give me some more details on how you installed it?
Regards, Chris
I presume you have installed the Micropython port for the Pico https://github.com/micropython/micropython/tree/master/ports/rp2 from https://micropython.org/download/?port=rp2?
In any case as this a microcontroller you probably need this version of that library https://github.com/chrisb2/pyb_ina219. The readme includes instructions for installing the logging library. I have never tried this library on the Pico, but I do have a Pico so could have a go at the weekend if you have any problems.
regards, Chris
OK. Got muddled. Thought I was responding to a response to my ticket on the I2C GPS unit. Back on track now. I just tried the code on the Pi Pico and got some very strange results.
With no battery connected to the voltage sensor I get: Voltage: 0.856 V Current: 0.007 A Percent: 0.0 %
Voltage: 0.856 V Current: 0.007 A Percent: 0.0 %
Voltage: 0.856 V Current: 0.006 A Percent: 0.0 %
With a brand new 1.5v battery connected I get... Voltage: 0.700 V Current: 14.768 A Percent: 0.0 %
Voltage: 0.696 V Current: 15.279 A Percent: 0.0 %
Voltage: 0.680 V Current: 16.019 A Percent: 0.0 %
With a brand new 9v battery I get Voltage: 0.800 V Current: 8.878 A Percent: 0.0 %
Voltage: 0.796 V Current: 8.481 A Percent: 0.0 %
Voltage: 0.804 V Current: 8.009 A Percent: 0.0 %
Voltage: 0.804 V Current: 7.563 A Percent: 0.0 %
It just seems to be giving me very random figures and I just can't make sense of them.
With a worn out 9v battery I get: Voltage: 0.708 V Current: 7.740 A Percent: 0.0 %
Voltage: 0.732 V Current: 7.022 A Percent: 0.0 %
Voltage: 0.708 V Current: 6.487 A Percent: 0.0 %
Voltage: 0.704 V Current: 5.864 A Percent: 0.0 %
The code I'm using is... I think I took the logfile out.
rom machine import I2C
import time
# Config Register (R/W)
_REG_CONFIG = 0x00
# SHUNT VOLTAGE REGISTER (R)
_REG_SHUNTVOLTAGE = 0x01
# BUS VOLTAGE REGISTER (R)
_REG_BUSVOLTAGE = 0x02
# POWER REGISTER (R)
_REG_POWER = 0x03
# CURRENT REGISTER (R)
_REG_CURRENT = 0x04
# CALIBRATION REGISTER (R/W)
_REG_CALIBRATION = 0x05
class BusVoltageRange:
"""Constants for ``bus_voltage_range``"""
RANGE_16V = 0x00 # set bus voltage range to 16V
RANGE_32V = 0x01 # set bus voltage range to 32V (default)
class Gain:
"""Constants for ``gain``"""
DIV_1_40MV = 0x00 # shunt prog. gain set to 1, 40 mV range
DIV_2_80MV = 0x01 # shunt prog. gain set to /2, 80 mV range
DIV_4_160MV = 0x02 # shunt prog. gain set to /4, 160 mV range
DIV_8_320MV = 0x03 # shunt prog. gain set to /8, 320 mV range
class ADCResolution:
"""Constants for ``bus_adc_resolution`` or ``shunt_adc_resolution``"""
ADCRES_9BIT_1S = 0x00 # 9bit, 1 sample, 84us
ADCRES_10BIT_1S = 0x01 # 10bit, 1 sample, 148us
ADCRES_11BIT_1S = 0x02 # 11 bit, 1 sample, 276us
ADCRES_12BIT_1S = 0x03 # 12 bit, 1 sample, 532us
ADCRES_12BIT_2S = 0x09 # 12 bit, 2 samples, 1.06ms
ADCRES_12BIT_4S = 0x0A # 12 bit, 4 samples, 2.13ms
ADCRES_12BIT_8S = 0x0B # 12bit, 8 samples, 4.26ms
ADCRES_12BIT_16S = 0x0C # 12bit, 16 samples, 8.51ms
ADCRES_12BIT_32S = 0x0D # 12bit, 32 samples, 17.02ms
ADCRES_12BIT_64S = 0x0E # 12bit, 64 samples, 34.05ms
ADCRES_12BIT_128S = 0x0F # 12bit, 128 samples, 68.10ms
class Mode:
"""Constants for ``mode``"""
POWERDOW = 0x00 # power down
SVOLT_TRIGGERED = 0x01 # shunt voltage triggered
BVOLT_TRIGGERED = 0x02 # bus voltage triggered
SANDBVOLT_TRIGGERED = 0x03 # shunt and bus voltage triggered
ADCOFF = 0x04 # ADC off
SVOLT_CONTINUOUS = 0x05 # shunt voltage continuous
BVOLT_CONTINUOUS = 0x06 # bus voltage continuous
SANDBVOLT_CONTINUOUS = 0x07 # shunt and bus voltage continuous
class INA219:
def __init__(self, i2c_bus=0, addr=0x40, sda=machine.Pin(0),scl=machine.Pin(1)):
self.i2c_bus = i2c_bus
self.sda = sda
self.scl = scl
self.i2c = I2C(i2c_bus,scl=self.scl,sda=self.sda);
self.addr = addr
# Set chip to known config values to start
self._cal_value = 0
self._current_lsb = 0
self._power_lsb = 0
self.set_calibration_32V_2A()
def read(self,address):
data = self.i2c.readfrom_mem(self.addr, address, 2)
return ((data[0] * 256 ) + data[1])
def write(self,address,data):
temp = [0,0]
temp[1] = data & 0xFF
temp[0] =(data & 0xFF00) >> 8
time.sleep_ms(100)
self.i2c.writeto_mem(self.addr,address,bytes(temp))
def set_calibration_32V_2A(self):
"""Configures to INA219 to be able to measure up to 32V and 2A of current. Counter
overflow occurs at 3.2A.
..note :: These calculations assume a 0.1 shunt ohm resistor is present
"""
# By default we use a pretty huge range for the input voltage,
# which probably isn't the most appropriate choice for system
# that don't use a lot of power. But all of the calculations
# are shown below if you want to change the settings. You will
# also need to change any relevant register settings, such as
# setting the VBUS_MAX to 16V instead of 32V, etc.
# VBUS_MAX = 32V (Assumes 32V, can also be set to 16V)
# VSHUNT_MAX = 0.32 (Assumes Gain 8, 320mV, can also be 0.16, 0.08, 0.04)
# RSHUNT = 0.1 (Resistor value in ohms)
# 1. Determine max possible current
# MaxPossible_I = VSHUNT_MAX / RSHUNT
# MaxPossible_I = 3.2A
# 2. Determine max expected current
# MaxExpected_I = 2.0A
# 3. Calculate possible range of LSBs (Min = 15-bit, Max = 12-bit)
# MinimumLSB = MaxExpected_I/32767
# MinimumLSB = 0.000061 (61uA per bit)
# MaximumLSB = MaxExpected_I/4096
# MaximumLSB = 0,000488 (488uA per bit)
# 4. Choose an LSB between the min and max values
# (Preferrably a roundish number close to MinLSB)
# CurrentLSB = 0.0001 (100uA per bit)
self._current_lsb = 1 # Current LSB = 100uA per bit
# 5. Compute the calibration register
# Cal = trunc (0.04096 / (Current_LSB * RSHUNT))
# Cal = 4096 (0x1000)
self._cal_value = 4096
# 6. Calculate the power LSB
# PowerLSB = 20 * CurrentLSB
# PowerLSB = 0.002 (2mW per bit)
self._power_lsb = .002 # Power LSB = 2mW per bit
# 7. Compute the maximum current and shunt voltage values before overflow
#
# Max_Current = Current_LSB * 32767
# Max_Current = 3.2767A before overflow
#
# If Max_Current > Max_Possible_I then
# Max_Current_Before_Overflow = MaxPossible_I
# Else
# Max_Current_Before_Overflow = Max_Current
# End If
#
# Max_ShuntVoltage = Max_Current_Before_Overflow * RSHUNT
# Max_ShuntVoltage = 0.32V
#
# If Max_ShuntVoltage >= VSHUNT_MAX
# Max_ShuntVoltage_Before_Overflow = VSHUNT_MAX
# Else
# Max_ShuntVoltage_Before_Overflow = Max_ShuntVoltage
# End If
# 8. Compute the Maximum Power
# MaximumPower = Max_Current_Before_Overflow * VBUS_MAX
# MaximumPower = 3.2 * 32V
# MaximumPower = 102.4W
# Set Calibration register to 'Cal' calculated above
self.write(_REG_CALIBRATION,self._cal_value)
# Set Config register to take into account the settings above
self.bus_voltage_range = BusVoltageRange.RANGE_32V
self.gain = Gain.DIV_8_320MV
self.bus_adc_resolution = ADCResolution.ADCRES_12BIT_32S
self.shunt_adc_resolution = ADCResolution.ADCRES_12BIT_32S
self.mode = Mode.SANDBVOLT_CONTINUOUS
self.config = self.bus_voltage_range << 13 | \
self.gain << 11 | \
self.bus_adc_resolution << 7 | \
self.shunt_adc_resolution << 3 | \
self.mode
self.write(_REG_CONFIG,self.config)
def getShuntVoltage_mV(self):
value = self.read(_REG_SHUNTVOLTAGE)
if value > 32767:
value -= 65535
return value * 0.01
def getBusVoltage_V(self):
self.read(_REG_BUSVOLTAGE)
return (self.read(_REG_BUSVOLTAGE) >> 3) * 0.004
def getCurrent_mA(self):
value = self.read(_REG_CURRENT)
if value > 32767:
value -= 65535
return value * self._current_lsb
if __name__=='__main__':
# Create an ADS1115 ADC (16-bit) instance.
ina219 = INA219(addr=0x40)
while True:
bus_voltage = ina219.getBusVoltage_V() # voltage on V- (load side)
current = ina219.getCurrent_mA() # current in mA
P = (bus_voltage -3)/1.2*100
if(P<0):P=0
elif(P>100):P=100
# INA219 measure bus voltage on the load side. So PSU voltage = bus_voltage + shunt_voltage
print("Voltage: {:6.3f} V".format(bus_voltage))
print("Current: {:6.3f} A".format(current/1000))
print("Percent: {:6.1f} %".format(P))
print("")
time.sleep(2)`
The weird results sound like you may not have a common ground. A good explanation of required circuit can be found in https://www.rototron.info/raspberry-pi-ina219-tutorial/
Chris
I had an interesting experience with a couple of other addons that I bought for the Pi Pico. One was an LCD display I was having issues with. It transpired that when I squeezed the display, the text appeared. Clearly a faulty display. That had me thinking about the INA219 and wondering if that too was faulty since we never want to believe something we have just purchased is already broken. Here's a photo of the offending INA219. https://photos.app.goo.gl/xAzYiBvqbUcD2HJ86 Looking at the INA219 I see a large shunt resistor labelled R100. I have zero idea what that resistor value is. That might be the problem. It could be that the guy on eBay wasn't entirely informed about the voltages it's supposed to measure.
Given that I've just had a pile of Buck converters that don't work, a broken LCD and now this - all from different suppliers on eBay - it sounds like I'm running into the same kind of situation I've had before. eBay has periods when nothing I buy from there ever works or is ever as described. I quit eBay for a few months and then go back and the stuff I order from then on is never faulty until the next period. I can't explain that as it defies logic what with it always being different suppliers and different products.
So, I'm wondering about the INA219. I have a second INA219 but given that so much from eBay just hasn't been in working condition when it arrived, I might just toss it in the trash untested and go to somewhere like DigiKey or Mouser to buy another.
R100 is 0.1 Ohms, this is the std shunt resistor value. Your INA219 breakout looks pretty much identical to mine. Maybe make a sketch of your circuit and attach a photo of it and I will see if anything comes to mind.
Chris
I tried this on a Pi Pico and this is what came up: