PMIC (only sometimes) not charging when battery voltage is below 3.5V

Like the title says, I am having an issue where on some electrons the battery is drained below 3.5V and when this happens the PMIC does not charge at all. chargeStatus() returns 2 and 3 for working batteries (above 3.5v) but when the battery is below 3.5V it returns 0 and does not charge. I am not sure what to do since the issue appears to not affect every battery. Any clues or help would be greatly appreciated!

PMIC pmic;
FuelGauge fuel;

void setup(){
	Serial.begin(115200);
}

void loop(){
	pmic.begin();
        pmic.setChargeCurrent(0,0,1,0,0,0);//set charging current to 1024mA (512 + 512 offset)
	pmic.setMinimumSystemVoltage(3000);
	pmic.setChargeVoltage(4208);
        pmic.setInputCurrentLimit(1200); //set input current limit to 1.2A//only options are 100,150,500,900,1200,1500,2000,3000

	delay(500);

	uint32_t bat = fuel.getSoC()*100;
	Serial.print("Battery: ");Serial.println(bat/100);

	uint32_t volt = fuel.getVCell()*1000;
	Serial.print("Voltage: ");Serial.println(volt);
	
	uint32_t charge = chargeStatus();
	Serial.print("Charge: ");Serial.println(charge);

	CellularSignal sig = Cellular.RSSI();
		
	Serial.print("Power ON Register: ");Serial.println(pmic.readPowerONRegister());
	Serial.print("Minimum System Voltage: ");Serial.println(pmic.getMinimumSystemVoltage());
	Serial.print("Low Battery: ");Serial.println(isBatLow());
	Serial.print("Charge Status: ");Serial.println(chargeStatus());
	Serial.print("Charge Source: ");Serial.println(chargePort());
	Serial.print("Power Good: ");Serial.println(pmic.isPowerGood());
	Serial.print("Fault: ");Serial.println(pmic.getFault());
	Serial.print("PMIC version: ");Serial.println(pmic.getVersion());
	
        //Publish to my server
	//cloud_update(bat, volt, charge*100, 0, 0, (int)pmic.getFault(), sig);
	Serial.println("sending");

	delay(60*1000);
        //Sleep goes here
}

bool isBatLow(void) {
    byte DATA = 0;
	PMIC p;
    DATA = p.getSystemStatus();
    if(DATA & 0b00000001) return 1;//BAT < VSYSMIN
    else return 0;//BAT > VSYSMIN
}

int chargeStatus(void) {
    byte DATA = 0;
	PMIC p;
    DATA = p.getSystemStatus();
    if(DATA & 0b00100000 && DATA & 0b00010000) return 3;//done charging
    if(DATA & 0b00100000) return 2;//fast charging
    if(DATA & 0b00010000) return 1;//pre charging
    else return 0;//no charging
}

int chargePort(void) {
    byte DATA = 0;
	PMIC p;
    DATA = p.getSystemStatus();
    if(DATA & 0b10000000 && DATA & 0b01000000) return 3;//OTG ?
    if(DATA & 0b10000000) return 2;//Adapter Port
    if(DATA & 0b01000000) return 1;//USB host
    else return 0;//Unknown
}


1 Like

The bug goes away by swapping to a battery above 3.5v and swapping back to original battery. But I can’t do that remotely.

Hello calebatch,

That’s strange. I’m glad you found a quick fix, but let me see if I can ping someone that might be able to help- @mohit .

Nice Fuel gauge + PMIC code layout. I’m going to borrow some of it :smiley:

I’ve never had a problem with it, but then again I’m using code to keep the Electron from operating below a 20% SOC level and then just waiting for solar charging above 20% before running my standard code again. This keeps the Electron from becoming unresponsive from a low battery.

I figured the PMIC would charge in Pre-Charge mode when the voltage gets below a certain point.

I’m short on time but can you pull the current Precharge voltage settings and see where they are set. Maybe PreCharge has been disabled somehow.

Also, it could be disabling charging if the temps are too high or low, so are you operating at either end of the extream?

What is your charging source?

I’ve actually followed some of your code for staying abover 20% but outside issues still let it drain down sometimes.

Above 3v the pmic should be in fast charge, which I have observed after battery swapping. Here is exactly what I am seeing:
Battery voltage of under 3.5v.
Plugged into usb 3.0.
Red charging light is on.
Running the code above returns a 0 for chargeStatus.

I am thinking there’s a fault or watchdog timer I might be missing but it’s weird that I can swap batteries to sort of “trick” the pmic? Certainly gives false high readings on the fuel gauge when I do so.

Also, I’ll have to pull the precharge settings in a few days. I was trying to fix a device remotely and accidentally got it stuck in a loop. So now I have to go fetch it. :confused:

You’re certain it’s not charging when the charging LED is RED but the charge setting returns 0?

Make sure you jiggle the JST battery connector in the jack since that can provide a better connection and cause quicker charging.

You could try wiring the battery directly to the Li+ pins and see if anything different happens.

Hi @calebatch, I was curious how you are measuring the battery voltage, and it looks like you might be using these two functions to do it:

pmic.setMinimumSystemVoltage(3000);
Serial.print("Low Battery: ");Serial.println(isBatLow());

There is a clever PMIC status indicator that let’s you know if the battery is above or below V_SYS_MIN. However setting this to 3000 would give you 3.0V instead of the default 3.5V when not using this function.

A couple things to know:

  1. We have a Fuel Gauge on the Electron which is better suited for Battery Voltage measurements
Serial.println( FuelGauge().getVCell() );
  1. setMinimumSystemVoltage() default settings should not be altered. By default this is 3.5V. This sets the system minimum voltage which is the voltage on the 3V8 node of the Electron. This is an internal voltage rail that supplies power to the u-blox module, and also a 3.3V buck regulator for the STM32. When the battery is below the minimum system voltage setting, the BATFET in the PMIC operates in linear mode (LDO mode), and 3V8 is 150 mV above the minimum system voltage setting. As the battery voltage rises above the minimum system voltage, BATFET is fully on and the voltage difference between the system and battery is the VDS of BATFET (so essentially the same as the battery).

  2. Minimum SYS (3V8) voltage should be allowed to be is 3.3V for the u-blox module and probably the same for the 3.3V buck regulator that supplies power to the STM32. Ideally these will stay above those minimums, which is why we leave the minimum system voltage setting defaulted at 3.5V.

  3. The LiPo battery has a protection circuit in it that will open circuit (with high impedance) the battery terminals when the battery voltage goes below 3.0V. It will look like the battery has 0V on it if you measured it. It will close the protection circuit once a charging voltage is applied to the battery. This can usually be done by plugging the Electron into a USB power source.

  4. By altering the minimum system voltage to 3.0V, this may be causing some confusion between the PMIC and the batteries protection circuit. All the while the modem and STM32 are experiencing brown outs.

If after setting setMinimumSystemVoltage() back to 3.5V (i.e. comment it out, and power cycle) you are still experiencing the battery not charging, does the problem stay with one electron or does it follow to wherever you use that particular battery? These are the batteries that came with the Electron?

3 Likes

I started with the minimum system voltage set to 3.5V and added that line of code after the issue started. I noticed on the pmic sheet there is a state where if vBatt<vSys then the charging changes, and I was trying to eliminate any possible reasons for not charging.
We have used both the golden lipos that come with the electrons and also have used the 6600mah li-on batteries from adafruit. We have observed the same results with both. Both batteries are above 3.0v and below 3.5v when the issue occurs.

We have 2 cases where the batteries fail to charge. The first is after some time of operation the battery drains to 3.5V and because of some extra stuff I have plugged in the battery is able to drain below 3.5V. The second is on a new battery being plugged in for the first time. (Second scenario usually is the adafruit battery but has happened a few times with the li-po).

When trying to charge from vIN or vUSB the pmic shows red charging led but when we record charge status its sends a 0, no change in mV on the fuelgauge either. Measuring with a multi-meter we have observed 50mA and 0mA but charging status is still 0.

Once we either swap with a fully charged battery or unplug and plug back in the original battery (takes a few times) the fuel gauge will still send the previous batteries charge and the pmic will show fast charging (return 2). The fuel gauge takes about an hour or two for it to show the correct mV and soc.

Charging current at or below 50ma will show as 0, not charging.

You need to add a circuit to cut loads off at 3.5v or the battery will keep draining to the point that the protection circuit will cut the battery output off and this will age the batteries quicker.

The 1Hz red LED flash is probably from low temps if it’s outside but could also be that your solar panel is putting out 20v + under no load.

You can keep the Electron battery from going below 3.5v by using my code but you will still need to keep the other devices connected to that battery from draining it dead all the time with some sort of voltage based switch or use a MOSFET and the Electron to control when the sensors are powered and when they are not.

1 Like

I am out of town for a few days, once I am back I will try adding enableCharging () to see if forcing the charging cycle to reset will make any difference.

If VUSB/VIN power goes away and returns while asleep, the PMIC will change it’s charging rate to the default of 50mA. If you wake back up and power doesn’t cycle again, I could see where it might get stuck at 50mA. There is an interrupt routine that refreshes the settings when the power cycles, but only if the unit is awake or booting up from reset. These are the commands that are refreshed.

PMIC power;
power.begin();
power.setInputCurrentLimit(900);     // 900mA
power.setChargeCurrent(0,0,0,0,0,0); // 512mA

If you use Sleep stop mode which just halts the STM32, I suppose these commands would not be run on waking. I wonder if that’s your issue. And if the rate is 50mA, the system will not stay charged as there is more current drain on the system than 50mA typically, even without any extra loads for sensors.

This is due to the digital filter on the Fuel Gauge. It doesn’t do well with battery swaps or abrupt changes in battery SoC while the Fuel Gauge is sleeping. Upon wake, or battery swap, you can run this command to reset the filter:

FuelGauge().quickStart();

The Fuel Gauge readings do not currently affect the way the PMIC operates, but it might in the future. We have talked about building in user configurable support for Soft Power Down when system battery capacity is < 10 or 20%.

Perhaps it would be interesting to see more of the stats output for your situation as well. You can take a look at some code that spits out all of the STATs and FAULTs here:

1 Like

Finally got another dead battery that isn’t charging. The voltage has been at 3429-3443mV for 4 hours now even though it says it is charging state 2. If I charge from Vusb instead of Vin the default 500mA does charge it. So currently we are looking to either always use a usb cord that we cut and wire to a solar panel, or if we can, use the Vusb pin to charge. Our loop resets the charging to 1mA every time at the beginning of loop(), before we call network sleep, and once we come out of network sleep.

CURR-FAULTCURR -

  • WATCHDOG:0
  • CHRG:0
  • BAT:0
  • NTC:0
  • March 24th at 12:03:02 pm

PREV-FAULTPREV -

  • WATCHDOG:0
  • CHRG:0
  • BAT:0
  • NTC:0
  • March 24th at 12:03:01 pm

STAT

  • VBUS:0
  • CHRG:2
  • DPM:1
  • PG:1
  • THERM:0
  • VSYS:0
  • March 24th at 12:03:01 pm

FC-0019
"coreid":“3e0025000a51343334363138”

You can’t keep running the batteries down to empty unless you like these types of problems.

Use code that prevents the Electron from running normally when SOC drops below 20%, add a bigger battery if you need longer run times.

Add a circuit to prevent your other sensors from draining the battery below 20% also. This will eliminate the problems your having now.

Hi @calebatch

Can you explain the above please? Is the 1mA a typo?

Yes, sorry. 1A, 1000mA.

1 Like

It is a common issue with the electron that I need solved. I can avoid the problems, which I am, but I still have failures of electrons due to the same low battery issues.

Done, the device still can die and not recover. Which is what happened with this latest electron. Sometimes I will even plug in a new larger battery, which was shipped at 3.3v. The battery isn’t bad but the electron won’t charge it off of the Vin pin.

This should be easily possible.

We should be able to get the Electron setup, so it will go into low power mode for weeks or a month waiting for enough sunlight to eventually recharge the battery above 20% again.

Can you draw up a schematic of how you have the setup wired up? It would give us a better idea of what you’re working with.

2 Likes

I don’t have the schematic, I am just working on battery recovery from failure. For whatever reason the pmic continues to default to 50mA or less when charging from Vin when battery is below 3.5v. So the current solution is to use usb with a wire spliced to attach to the solar panel since the default charging is 500mA. I haven’t looked but I will (hopefully) be able to use the Vusb pin as an input so I don’t have to cut 100+ usb cords.

1 Like

The schematic shows the Vin & Vbus pins feeding into the same charging input pin as shown below so charging via USB or Vin will be exactly the same unless it detects data on the USB data pins and adjust the charging current based on that.

1 Like