I am using these three cool items in concert:
3.7V 2500 mAh LiPo - Product ID: 328
Adafruit Universal USB / DC / Solar Lithium Ion/Polymer charger - bq24074 - Product ID: 4755
Adafruit MAX17048 LiPoly / LiIon Fuel Gauge and Battery Monitor - STEMMA JST PH & QT / Qwiic - Product ID: 5580
As usual, everything works well, but in this case there's a little quirk I'm trying to understand with the "Fuel Gauge".
The charge level reads apparently fine, and when I plug in the USB-C connector, the charge level increases as you would expect. But it doesn't stop at "100%" as I would expect. It continues until the Fuel Gauge reads ~ 124%.
If I unplug the USB-C cable, it remains at ~ 124% and discharges very slowly (my project runs about 18 hours on a charge), *BUT* - and here's the weird part - if, while the fuel gauge is reading that high, I switch the project off, and back on, it immediately shows the charge level as being ~ 86%, and discharges normally from there.
Is there some calibration/setup thing I missed somewhere?
MAX17048 Question on charge level percentage readings
Moderators: adafruit_support_bill, adafruit
Please be positive and constructive with your questions and comments.
- xanatos
- Posts: 110
- Joined: Thu Jun 18, 2009 3:09 pm
- mikeysklar
- Posts: 14182
- Joined: Mon Aug 01, 2016 8:10 pm
Re: MAX17048 Question on charge level percentage readings
What else are you powering through the battery (controller board, CO2 sensor, TFT model, etc)? The model of processor on your controller board could be related to the skewed readings.
The CO2 sensor is likely turning on a significant load on reset (turn on heating element).
The CO2 sensor is likely turning on a significant load on reset (turn on heating element).
- xanatos
- Posts: 110
- Joined: Thu Jun 18, 2009 3:09 pm
Re: MAX17048 Question on charge level percentage readings
I'm using the CircuitBrains Deluxe (SAMD51 I believe).
As you state I'm using the CO2 sensor, the temp/humidity/pressure sensor, a hi-precision RTC, and the display. For now - about to add an O2 sensor, VOC, H2, H2SO4 and other sensors
The CO2 sensor draws a relatively higher current, but not enough to take the battery from 124% to 83% in ten seconds. The project runs normally at least 18 hours with everything running. If the CO2 sensor was drawing that much current, it would die in 50 seconds :)
It is notable that my "power trio" itself, with only the display and RTC hooked up, exhibited the same behavior before the rest of the I2C chain was ever hooked up.
It's an odd one...
Dave
As you state I'm using the CO2 sensor, the temp/humidity/pressure sensor, a hi-precision RTC, and the display. For now - about to add an O2 sensor, VOC, H2, H2SO4 and other sensors
The CO2 sensor draws a relatively higher current, but not enough to take the battery from 124% to 83% in ten seconds. The project runs normally at least 18 hours with everything running. If the CO2 sensor was drawing that much current, it would die in 50 seconds :)
It is notable that my "power trio" itself, with only the display and RTC hooked up, exhibited the same behavior before the rest of the I2C chain was ever hooked up.
It's an odd one...
Dave
- mikeysklar
- Posts: 14182
- Joined: Mon Aug 01, 2016 8:10 pm
Re: MAX17048 Question on charge level percentage readings
Interesting project with so many gas sensors.
Can you post some of the MAX17048 related code you are running?
Can you post some of the MAX17048 related code you are running?
- xanatos
- Posts: 110
- Joined: Thu Jun 18, 2009 3:09 pm
Re: MAX17048 Question on charge level percentage readings
Sure - here's the complete code I'm running now:
Code: Select all
# Environmental Monitor Display & Control, updated 2022-11-15, Time, Date, CO2, Humidity, Temperature, Pressure; Bar Graph for radiation level data eventually, etc.
# Adafruit CircuitBrains PID 4802 https://www.adafruit.com/product/4802
# Adafruit 1.9" 240x135 Color TFT Display ST7789 PID 5394 https://www.adafruit.com/product/5394
# Adafruit SCD-41 - True CO2 Temperature and Humidity Sensor PID: 5190 https://www.adafruit.com/product/5190
# Adafruit LPS22 Pressure Sensor PID: 4633 https://www.adafruit.com/product/4633
# I2C addresses found: ['0x36', '0x5d', '0x62', '0x68', '0x73'] includes O2 Sensor
import board
import terminalio
import displayio
from adafruit_display_text import label
from adafruit_st7789 import ST7789
import adafruit_imageload
from digitalio import DigitalInOut, Direction, Pull
from analogio import AnalogOut, AnalogIn
import sdcardio
import storage
import pwmio
import time
import adafruit_ds3231 # RTC, Hi Precision I2C 0x68
import adafruit_scd4x # Temp, Humid, True CO2 ppm I2C 0x62 (12 bit DAC?)
import adafruit_lps2x # Pressure (hPa), Temp I2C 0x5d
import gc # For memory space checks
import microcontroller # for uP temp measurements
import adafruit_max1704x #Battery Fuel Gauge
import sys
import math
sys.path.append("../..")
from DFRobot_Oxygen import *
COLLECT_NUMBER = 10 # O2: collect number, the collection range is 1-100
IIC_MODE = 0x01 # O2: default use IIC1
oxygen = DFRobot_Oxygen_IIC(IIC_MODE ,ADDRESS_3)
def setBright(lvl): # 0 to 100
bgLevel = min(max(lvl, 0), 100)
backlight.duty_cycle = int(bgLevel * 65535 / 100) # Up
i2c = board.I2C()
ds3231 = adafruit_ds3231.DS3231(i2c)
scd4x = adafruit_scd4x.SCD4X(i2c)
#print("SCD4x Serial numbers:", [hex(i) for i in scd4x.serial_number])
lps = adafruit_lps2x.LPS22(i2c)
max17 = adafruit_max1704x.MAX17048(i2c) # Battery must be connected else I2C addr will not show up
days = ("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")
#ds3231.datetime = time.struct_time((2022, 8, 3, 13, 39, 00, 2, 1, -1))
current = ds3231.datetime
#print('The current time is: {}/{}/{} {:02}:{:02}:{:02}'.format(current.tm_mon, current.tm_mday, current.tm_year, current.tm_hour, current.tm_min, current.tm_sec))
# Release any resources currently in use for the displays
displayio.release_displays()
spi = board.SPI()
tft_cs = board.D11
tft_dc = board.D13
tft_rst = board.D12
sd_cs = board.D14
sdcard = sdcardio.SDCard(spi, sd_cs)
vfs = storage.VfsFat(sdcard)
storage.mount(vfs, "/sd")
#Light Level Sensing via CDS cell on A1
lightlevel = AnalogIn(board.A0)
# Analog input on A1-3
analog1in = AnalogIn(board.A1) #
analog2in = AnalogIn(board.A2) #
analog3in = AnalogIn(board.A3) #
backlight = pwmio.PWMOut(board.D10, frequency=5000, duty_cycle=0)
display_bus = displayio.FourWire(spi, command=tft_dc, chip_select=tft_cs, reset=tft_rst)
display = ST7789(display_bus, width=320, height=170, colstart=35, rotation=270)
BORDER = 2
FONTSCALE = 2
BACKGROUND_COLOR = 0x550000 # Red
FOREGROUND_COLOR = 0x000055 # Blue
TEXT_COLOR = 0xCCCCFF
# Settings are adjusted for specific CdS Cell used
minBright = 10 #Minimum display brightness in dark conditions
maxBright = 99 #Maximum display brightness in light conditions
group = displayio.Group(scale=1)
# Add the Group to the Display
display.show(group)
#Start of Reading Table
initPos = 10
lineSpace = 27
screenPage = 1
pageLeft = 5
# Draw a label
text_area = label.Label(
terminalio.FONT,
text="Init",
color=TEXT_COLOR,
scale=1,
x = pageLeft, # x = Horizontal, y = Vertical
y = 158,
#anchor_point=(0.5, 0.5),
#anchored_position=(display.width // 2, display.height // 2),
) # Use x & Y for left-aligned text, use anchor_point=(0.5, 0.5) for centered text
group.append(text_area)
# Draw a label
text_area2 = label.Label(
terminalio.FONT,
text=" ",
color=0xffffff,
scale=1,
x = pageLeft + 90, # x = Horizontal, y = Vertical
y = 158,
#anchor_point=(0.5, 0.5),
#anchored_position=(display.width // 2, display.height // 2),
) # Use x & Y for left-aligned text, use anchor_point=(0.5, 0.5) for centered text
group.append(text_area2)
# Draw a label for PAGE ID (data field only here)
text_pageID = label.Label(
terminalio.FONT,
text="01",
color=0xff0000,
scale=1,
x = 310, # x = Horizontal, y = Vertical
y = 158,
#anchor_point=(0.5, 0.5),
#anchored_position=(display.width // 2, display.height // 2),
) # Use x & Y for left-aligned text, use anchor_point=(0.5, 0.5) for centered text
group.append(text_pageID)
# Draw a label for Time, Date & Environmental Conditions
text_time = label.Label(
terminalio.FONT,
text="XXXX/XX/XX XX:XX:XX",
color=0xffffff,
scale=2,
x = pageLeft,
y = initPos,
) # Use x & Y for left-aligned text, use anchor_point for centered text
group.append(text_time)
text_THP = label.Label(
terminalio.FONT,
text="00F 00% 00.00 InHg",
color=TEXT_COLOR,
scale=2,
x = pageLeft, # x = Horizontal, y = Vertical
y = initPos + lineSpace,
#anchor_point=(0.5, 0.5),
#anchored_position=(display.width // 2, display.height // 2),
) # Use x & Y for left-aligned text, use anchor_point=(0.5, 0.5) for centered text
group.append(text_THP)
# Draw a label for CO2 & CO
text_CO2CO = label.Label(
terminalio.FONT,
text="CO2: ",
color=TEXT_COLOR,
scale=3,
x = pageLeft, # x = Horizontal, y = Vertical
y = initPos + (lineSpace*2),
#anchor_point=(0.5, 0.5),
#anchored_position=(display.width // 2, display.height // 2),
) # Use x & Y for left-aligned text, use anchor_point=(0.5, 0.5) for centered text
group.append(text_CO2CO)
bar_bitmap = dict()
bar_palette = dict()
bar_sprite = dict()
numBars = 10
def drawPowerBar():
xpos = pageLeft
xspace = 10
ypos = 128
barx = 6
bary = 20
for b in range(1, 21):
bar_bitmap[b] = displayio.Bitmap(barx, bary, 1)
bar_palette[b] = displayio.Palette(1)
if (b<5):
bcolor = 0x00CC00 # Green
elif ((b>=5) and (b<9)):
bcolor=0x40FF00 # Yellow-Green
elif ((b>=9) and (b<13)):
bcolor = 0xFFFF00 # Yellow
elif ((b>=13) and (b<17)):
bcolor = 0xFF7700 # Yellow
elif (b>=16):
bcolor = 0xFF0000 # Red
bar_palette[b][0] = bcolor
bar_sprite[b] = displayio.TileGrid(bar_bitmap[b], pixel_shader=bar_palette[b], x=xpos, y=ypos)
group.append(bar_sprite[b])
xpos = xpos + xspace
def adjustPowerBar(numBars):
for b in range(1, 21):
if (b<=numBars):
if (b<5):
bcolor = 0x00CC00 # Green
elif ((b>=5) and (b<9)):
bcolor=0x40FF00 # Yellow-Green
elif ((b>=9) and (b<13)):
bcolor = 0xFFFF00 # Yellow
elif ((b>=13) and (b<17)):
bcolor = 0xFF7700 # Yellow
elif (b>=16):
bcolor = 0xFF0000 # Red
else:
bcolor = 0x000044
bar_palette[b][0] = bcolor
drawPowerBar()
# Add the Group to the Display
display.show(group)
# Set sprite location
group.x = 0
group.y = 0
scd4x.start_periodic_measurement()
Count = 0
subCount = 0
setBright(100)
currentPage = 1
scd41TempF = "0"
scd41RHpct = "0"
lpsPressInHg = "0"
scd41TempCs = "0"
lpsPressmBar = "0"
lpsPressPSI = "0"
scd41CO2ppm = "0"
while True:
if (currentPage == 1):
text_pageID.text = "01"
text_area.text = ("Scanning " + str(Count))
Count = Count + 1
if (Count % 10 == 0):
t = ds3231.datetime
DateText = "{} {}/{:02}/{:02}".format(days[int(t.tm_wday)], t.tm_year, t.tm_mon, t.tm_mday)
TimeText = "{}:{:02}:{:02}".format(t.tm_hour, t.tm_min, t.tm_sec)
text_time.text = DateText + " " + TimeText
Bv = str(round(max17.cell_voltage,1))
Bs = str(round(max17.cell_percent,1))
gc.collect()
uCT = str(round(microcontroller.cpu.temperature, 1))
freeS = str(gc.mem_free())
text_area2.text = "uCT: " + uCT + " " + Bv + "V " + Bs + "% FS: " + freeS
if scd4x.data_ready: #These will update 1x/second: Temp, Humid, Press:
scd41CO2ppm = scd4x.CO2
scd41TempC = scd4x.temperature #23.81 #TESTING ONLY
scd41RHpct = scd4x.relative_humidity #"34" #TESTING ONLY
scd41TempF = (scd41TempC*1.8)+32
scd41TempF = str(round(scd41TempF,1))
scd41TempCs = str(round(scd41TempC,1))
scd41RHpct = str(round(scd41RHpct)) #TESTING ONLY
lpsPresshPa = lps.pressure
lpsPressInHg = lpsPresshPa/33.864
lpsPressInHg = str(round(lpsPressInHg,2))
lpsPressmBar = str(round(lpsPresshPa))
lpsPressPSI = lpsPresshPa * 0.0145
lpsPressPSI = str(round(lpsPressPSI,2))
#Display Sensor Data:
if (subCount == 0):
text_THP.text = scd41TempF + "F " + scd41RHpct + "% " + lpsPressInHg + " InHg"
elif (subCount == 1):
text_THP.text = scd41TempCs + "C " + scd41RHpct + "% " + lpsPressmBar + " mBar"
elif (subCount == 2):
text_THP.text = scd41TempF + "F " + scd41RHpct + "% " + lpsPressInHg + " InHg"
elif (subCount == 3):
text_THP.text = scd41TempCs + "C " + scd41RHpct + "% " + lpsPressPSI + " PSI"
if (len(str(scd41CO2ppm)) == 3):
if (int(scd41CO2ppm) > 999):
text_CO2CO.color = 0xFFFF00
elif (int(scd41CO2ppm) > 1999):
text_CO2CO.color = 0xFF0000
else:
text_CO2CO.color = TEXT_COLOR
text_CO2CO.text = "CO2: " + str(scd41CO2ppm)
else:
if (int(scd41CO2ppm) > 999):
text_CO2CO.color = 0xFFFF00
elif (int(scd41CO2ppm) > 1999):
text_CO2CO.color = 0xFF0000
else:
text_CO2CO.color = TEXT_COLOR
text_CO2CO.text = "CO2: " + str(scd41CO2ppm)
subCount = subCount + 1
if (subCount > 3):
subCount = 0
#oxygen_data = oxygen.get_oxygen_data(COLLECT_NUMBER)
#print("oxygen concentration is %4.2f %%vol"%oxygen_data)
elif(currentPage == 2):
text_pageID.text = "02"
time.sleep(.1)
- mikeysklar
- Posts: 14182
- Joined: Mon Aug 01, 2016 8:10 pm
Re: MAX17048 Question on charge level percentage readings
Thank you for sharing the code. It is clear how you are gathering the data and displaying the sensor / battery stats. Nice code.
Can you post a photo of how you are using the BQ24074 with the MAX17048 and LiPo?
It would be a good idea to setup a voltage_alert_max value of 4.2v to prevent overcharging. Then scan the active_alert for when you hit it. Since this could be a false value you have the ability to reset() the MAX17048 when you hit the charge limit and you could see if it comes with the "real" voltage.
I know the above is a hack, but the idea is to better understand what is going on.
Can you post a photo of how you are using the BQ24074 with the MAX17048 and LiPo?
It would be a good idea to setup a voltage_alert_max value of 4.2v to prevent overcharging. Then scan the active_alert for when you hit it. Since this could be a false value you have the ability to reset() the MAX17048 when you hit the charge limit and you could see if it comes with the "real" voltage.
I know the above is a hack, but the idea is to better understand what is going on.
- xanatos
- Posts: 110
- Joined: Thu Jun 18, 2009 3:09 pm
Re: MAX17048 Question on charge level percentage readings
Here's a shot of the layout:
Battery ---> Charge Module ---> Fuel Gauge ---> rest of circuitry
Power switch located on positive rail between Charge Module and Fuel Gauge.
The white-striped wires coming from just behind the USB-C connector are the data lines that go to the Microcontroller for programming, etc.
All data with the exception of the display is I2C. Display is SPI.
Battery ---> Charge Module ---> Fuel Gauge ---> rest of circuitry
Power switch located on positive rail between Charge Module and Fuel Gauge.
The white-striped wires coming from just behind the USB-C connector are the data lines that go to the Microcontroller for programming, etc.
All data with the exception of the display is I2C. Display is SPI.
- mikeysklar
- Posts: 14182
- Joined: Mon Aug 01, 2016 8:10 pm
Re: MAX17048 Question on charge level percentage readings
Are you using two LiPo packs?
The Max17048 guide has the battery connected directly to either JST. Have you tried that scenario?
The Max17048 guide has the battery connected directly to either JST. Have you tried that scenario?
- xanatos
- Posts: 110
- Joined: Thu Jun 18, 2009 3:09 pm
Re: MAX17048 Question on charge level percentage readings
Single LiPo.
Do you mean try reversing which jack the battery is going into?
Do you mean try reversing which jack the battery is going into?
- mikeysklar
- Posts: 14182
- Joined: Mon Aug 01, 2016 8:10 pm
Re: MAX17048 Question on charge level percentage readings
Taking the BQ24074 out of the equation (disconnect the JSTs) and check the battery readings. Does the MAX17048 report the correct values?
Please be positive and constructive with your questions and comments.