Battery Charge doesn't work if starting when EN grounded

I need help on how to debug this and the settings I need.

When I try and charge through the vusb pin, it works if I start charging when on. However if I disable the chip by grounding the EN pin, and then try and charge, it will not charge. I have to fully disconnect all power from the chip before it will charge again. I can turn it on and off multiple times and it will keep charging as long as it was on when I started the charging.

Is there something I can read when I have it in this state that can tell me why it isn’t charging?

Here are my settings startup settings:
conf.powerSourceMaxCurrent(2000)
.powerSourceMinVoltage(5080)
.batteryChargeCurrent(1024)
.batteryChargeVoltage(4208)
.feature(SystemPowerFeature::PMIC_DETECTION)
.feature(SystemPowerFeature::USE_VIN_SETTINGS_WITH_USB_HOST) ;
System.setPowerConfiguration(conf);

What firmware version are you running?

This post by @avtolstoy might be a good starting point for you:

[Edit] - This may not help in your case, but for Solar Recharged Boron's I use the USB connector for the input source.
I get the same results as you when using Vin(Vusb) pin, but charging will resume during/after an EN Pin Shutdown when using the USB connector. I have no idea why :man_facepalming:

@no1089,

Chris is the the same issue I am seeing. My devices work correctly until I put them to sleep using the Enable pin. I use the RTC to wake them and, when I do, they stop accepting a charge.

Like @rftop, if I start charging the device using the USB port, it will begin charging even after I remove the USB cable and start charing via the DC-In pin. Somehow the PMIC is getting locked up with Enable-sleep and the USB port will “reset” or “re-enable” charing.

Thanks,

Chip

Using version 1.5.0.
Any settings to fix this?
We already have some boards made up so USB charging would not work.

@runfastman,

For now, I am using STOP mode sleep but I am hoping that this issue gets resolved quickly.

Chip

We are using an ATTiny for power control, so that we don’t get battery drain issues during the “Off Season”

How do we get this on the list for next firmware release?

I removed the line from Vusb pin and changed it to charge through the USB port and I get the same results. It won’t charge if I start it charging with EN pin grounded. Not what you did different.

@runfastman,

I have opened a service ticket for this and have been assured that this issue is getting the full attention of the Particle engineering staff. Until then, I am looking for workarounds such as changing sleep modes or seeing if there is a way to reset the PMIC via software. I will let you know if I come up with a temporary fix while we wait for a fix from Particle.

Have you tried updating to deviceOS@1.5.1?

Thanks, Chip

@runfastman, Are you using a DC power supply or Solar Panel?
Either way, the 5.08 V minimum supply setting might be why temporarily switching to the USB port didn't give better results.
Your Power Supply will need to be able to meet All the current demands (+ a minimum charging current) while maintaining 5.08V for charging to be enabled. Can you test with a better power supply, variable supply, shorter cables, a lower powerSourceMinVoltage, remove any external current demands, etc. It might not be the answer for your situation, but might provide more insight on the reasons. I assume that you also re-enable charging after the EN Pin Shutdown ?

If you want to share a simplified code example that represents the problem, I'll give it a test drive and try to reproduce.

Do you have a small example app that reliably does this? I have not been able to replicate the issue so far. My Boron keeps charging when powered back on after releasing EN.

This is the simplified test code that I’ve been using:

SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(MANUAL);

//////////////////////////////////////////////
int myTestMode = 2;   //  1 = API  2 = PMIC //
//////////////////////////////////////////////

SystemPowerConfiguration conf;
PMIC pmic;

STARTUP( selectMode() );


void selectMode()  {
  // (1) API MODE

  System.setPowerConfiguration(SystemPowerConfiguration());

  if (myTestMode == 1) {
    conf.powerSourceMaxCurrent(900)
    .powerSourceMinVoltage(5080)
    .batteryChargeCurrent(1024)
    .batteryChargeVoltage(4208)
    .feature(SystemPowerFeature::PMIC_DETECTION);

    System.setPowerConfiguration(conf);
  }

  //  (2) PMIC Mode
  if (myTestMode == 2) {
    {

      conf.feature(SystemPowerFeature::DISABLE);
      System.setPowerConfiguration(conf);

      pmic.begin();
      pmic.setInputVoltageLimit(5080);
      pmic.setInputCurrentLimit(900) ;
      pmic.setChargeVoltage(4208);
      pmic.setChargeCurrent(0, 0, 1, 0, 0, 0);
      pmic.enableDPDM();
      pmic.enableBuck();
      pmic.enableCharging();

    }

  }

}


void setup() {
}

void loop() {
}

/*
  Results for 3.78V Li-Po, LED Test Stand, 2W Voltaic Panel, Boron LTE on 1.5.1, 05/13/2020:

  MODE 1 (API) using USB Connector
  Charging works fine during and after an EN Pin Shutdown.

  MODE 1 (API) using Vin/Vusb Pin
  Charging wont resume if Vin cycles during EN Pin Shutdown (Clouds)

  MODE 2 (PMIC) using USB Connector
  Charging works fine during and after an EN Pin Shutdown.

  MODE 2 (PMIC) using Vin/Vusb Pin
  Charging works during and after an EN Pin Shutdown, but it wont resume charging during EN Shutdown if it wasn't charging when EN Pin was pulled low (Cloud).
  Slightly different than Mode 1 Vin/Vusb.  The important condition occurs AT the time of Shutdown verses during Shutdown
*/

Change myTestMode, (1) for API, or (2) for PMIC.

Thanks for this - On scenario two I’m not seeing the issue, but when I use SystemPowerConfiguration, I can reliably get it to stop charging.

@Rftop I built your test code against 1.5.1, but I cannot produce the issue on my Boron 2G/3G. Below is my test steps, correct me if I was wrong:

  1. Build the test code against 1.5.1 for Boron
  2. DFU the system part and user part
  3. Detach all power sources (Li battery, USB connector, VIN)
  4. Attach Li battery and VIN(draw current from another boron’s VIN pin), charging LED stayed on
  5. Attach EN pin to ground, charging LED stayed on
  6. Detach VIN pin, charging LED stayed off
  7. Attach VIN pin, charging LED stayed on
  8. Repeat 6 ~ 7, it can always resume charging

Tried with attaching/detaching USB connector, it can resume charging as well.

Before I tested against 1.5.1, I did play with the test code against a local branch with untagged version and I did see weird behavior of the charging LED on power cycle the VIN pin during EN pin is grounded. But after I checkout 1.5.1, I cannot produce this issue, no matter what test mode it was. I will try older version and see if I can reproduce this issue reliably.

Kind regards

@ielec, As you saw, I didn’t use a 2G/3G.
I recently unboxed a 2G/3G Boron, so I’ll repeat the test to see if there is a difference in LTE vs 3G hardware in regards to li-po charging when using the EN pin

[Edit] I got essentially the same results for my 2G/3G Boron as my LTE.

Boron 2G/3G

Results for 3.99V Li-Po, LED Test Stand, 2W Voltaic Panel, Boron 2G/3G on 1.5.1, 05/26/2020:
  
  MODE 1 (API) using USB Connector
  Charging works fine during and after an EN Pin Shutdown.

  MODE 1 (API) using Vin/Vusb Pin
  Wont re-enable charging after EN Pin Shutdown.  

  MODE 2 (PMIC) using USB Connector
  Charging works fine during and after an EN Pin Shutdown.

  MODE 2 (PMIC) using Vin/Vusb Pin
  Charging will remain on if 3G Boron was charging at the time of EN pin shutdown.  It will not resume charing after a Vin Cycle (Clouds)

One difference between our tests is that I’m using Solar Panels as the Power Source. You appear to be testing with a DC Power Supply “(draw current from another boron’s VIN pin)”.
That could be the reason for the difference in our results, as a Solar Panel is a current producing device. The PMIC must manage it’s charging current to maintain the Panel Voltage, so we’re not performing the same tests.

It’s odd that we are seeing such different results though, since my LED Light Test Rig & Solar Panel can easily meet the Voltage & Current requirements as the PMIC settings in the test Code.

Could you also try drawing current from a DC power supply to verify if it is something related to Solar Panels specifically, cos I don't have Solar Panels in hand to produce the issue. That would also help identify the root cause.

Thanks

I used a battery pack from my Arduino kit and connected to the VIN to reproduce without the solar panel.

1 Like

I tried a few of the test profiles with a DC Power Supply @ 5.3V, with the same results.

For me (LTE & 2G/3G), using the USB connector on the Boron is the only reliable way to recharge a Li-Po....and then only under certain conditions as noted previously.

Now I can reliably produce the issue using my own app:

#include "Particle.h"

Serial1LogHandler log(115200, LOG_LEVEL_ALL);

SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(MANUAL);

//////////////////////////////////////////////
int myTestMode = 1;   //  1 = API  2 = PMIC //
//////////////////////////////////////////////

void selectMode();
STARTUP( selectMode() );

void selectMode()  {
    if (myTestMode == 2) {
        System.setPowerConfiguration(SystemPowerConfiguration().feature(SystemPowerFeature::DISABLE));
    }
}

void setup() {
    LOG(TRACE, "Application started.");

    if (myTestMode == 1) {
        LOG(TRACE, "Using system power manager API to configure PMIC.");
        SystemPowerConfiguration conf;
        conf.powerSourceMaxCurrent(900)
            .powerSourceMinVoltage(5080)
            .batteryChargeCurrent(1024)
            .batteryChargeVoltage(4208)
            .feature(SystemPowerFeature::PMIC_DETECTION);
        System.setPowerConfiguration(conf);
    }

    if (myTestMode == 2) {
        LOG(TRACE, "Using PMIC APIs to configure PMIC.");
        PMIC pmic;
        pmic.begin();
        pmic.setInputVoltageLimit(5080);
        pmic.setInputCurrentLimit(900) ;
        pmic.setChargeVoltage(4208);
        pmic.setChargeCurrent(0, 0, 1, 0, 0, 0);
        pmic.enableDPDM();
        pmic.enableBuck();
        pmic.enableCharging();
    }

    PMIC pmic;
    pmic.getVersion();
}

void loop() {
    {
        PMIC power(true);
        LOG(TRACE, "Current PMIC settings:");
        LOG(TRACE, "VIN Vmin: %u", power.getInputVoltageLimit());
        LOG(TRACE, "VIN Imax: %u", power.getInputCurrentLimit());
        LOG(TRACE, "Ichg: %u", power.getChargeCurrentValue());
        LOG(TRACE, "Iterm: %u", power.getChargeVoltageValue());

        int powerSource = System.powerSource();
        int batteryState = System.batteryState();
        float batterySoc = System.batteryCharge();
        
        constexpr char const* batteryStates[] = {
            "unknown", "not charging", "charging",
            "charged", "discharging", "fault", "disconnected"
        };
        constexpr char const* powerSources[] = {
            "unknown", "vin", "usb host", "usb adapter",
            "usb otg", "battery"
        };

        LOG(TRACE, "Power source: %s", powerSources[std::max(0, powerSource)]);
        LOG(TRACE, "Battery state: %s", batteryStates[std::max(0, batteryState)]);
        LOG(TRACE, "Battery charge: %f", batterySoc);
        LOG(TRACE, "");
    }
    delay(5000);
}

Both of the test modes using my app can produce the issue. But for test mode 2, charging can be resumed after released the EN pin.

The reason why I cannot reliably produce the issue is that I was connecting the Boron's UART TX/RX to my computer over a USB-UART bridge for debug purpose. There is power leakage on the RX pin, which may affect the MCU somehow even if the EN pin is pulled down.

Using the app that @Rftop provided above, I can produce the issue sometimes, and sometimes the charging LED just gave a shot and then kept off even if the EN pin is never pulled down after startup.

The log running my app for test mode 1:

0000000416 [app] application.cpp:64, setup(): TRACE: Application started.
0000000417 [app] application.cpp:67, setup(): TRACE: Using system power manager API to configure PMIC.
0000000438 [app] application.cpp:97, loop(): TRACE: Current PMIC settings:
0000000440 [app] application.cpp:98, loop(): TRACE: VIN Vmin: 4360
0000000446 [app] application.cpp:99, loop(): TRACE: VIN Imax: 3000
0000000449 [app] application.cpp:100, loop(): TRACE: Ichg: 1024
0000000457 [app] application.cpp:101, loop(): TRACE: Iterm: 4208
0000000461 [app] application.cpp:116, loop(): TRACE: Power source: battery
0000000468 [app] application.cpp:117, loop(): TRACE: Battery state: discharging
0000000479 [app] application.cpp:118, loop(): TRACE: Battery charge: 96.960938
0000005480 [app] application.cpp:97, loop(): TRACE: Current PMIC settings:
0000005481 [app] application.cpp:98, loop(): TRACE: VIN Vmin: 4360
0000005484 [app] application.cpp:99, loop(): TRACE: VIN Imax: 3000
0000005493 [app] application.cpp:100, loop(): TRACE: Ichg: 1024
0000005495 [app] application.cpp:101, loop(): TRACE: Iterm: 4208
0000005505 [app] application.cpp:116, loop(): TRACE: Power source: battery
0000005506 [app] application.cpp:117, loop(): TRACE: Battery state: discharging
0000005515 [app] application.cpp:118, loop(): TRACE: Battery charge: 96.960938
0000010525 [app] application.cpp:97, loop(): TRACE: Current PMIC settings:
0000010527 [app] application.cpp:98, loop(): TRACE: VIN Vmin: 5080
0000010533 [app] application.cpp:99, loop(): TRACE: VIN Imax: 900
0000010535 [app] application.cpp:100, loop(): TRACE: Ichg: 1024
0000010544 [app] application.cpp:101, loop(): TRACE: Iterm: 4208

Attach power supply on VUSB

0000010547 [app] application.cpp:116, loop(): TRACE: Power source: vin
0000010555 [app] application.cpp:117, loop(): TRACE: Battery state: charging
0000010566 [app] application.cpp:118, loop(): TRACE: Battery charge: 96.960938
0000015567 [app] application.cpp:97, loop(): TRACE: Current PMIC settings:
0000015568 [app] application.cpp:98, loop(): TRACE: VIN Vmin: 5080
0000015571 [app] application.cpp:99, loop(): TRACE: VIN Imax: 900
0000015580 [app] application.cpp:100, loop(): TRACE: Ichg: 1024
0000015582 [app] application.cpp:101, loop(): TRACE: Iterm: 4208
0000015591 [app] application.cpp:116, loop(): TRACE: Power source: vin
0000015593 [app] application.cpp:117, loop(): TRACE: Battery state: charging
0000015602 [app] application.cpp:118, loop(): TRACE: Battery charge: 96.960938

Pulled down the EN pin and power cycle the VUSB and then release EN:

0000000377 [net.pppncp] INFO: Creating PppNcpNetif LwIP interface
0000000378 [net.ppp.client] TRACE: PPP client initializing
0000000379 [net.ppp.client] TRACE: PPP phase -> 0
0000000389 [net.ppp.client] TRACE: PPP thread started
0000000393 [ncp.client] TRACE: Modem low level initialization OK
0000000398 [hal] TRACE: Heap: 48/166 Kbytes used
0000000415 [app] application.cpp:64, setup(): TRACE: Application started.
0000000416 [app] application.cpp:67, setup(): TRACE: Using system power manager API to configure PMIC.
0000000438 [app] application.cpp:97, loop(): TRACE: Current PMIC settings:
0000000440 [app] application.cpp:98, loop(): TRACE: VIN Vmin: 5080
0000000446 [app] application.cpp:99, loop(): TRACE: VIN Imax: 900
0000000449 [app] application.cpp:100, loop(): TRACE: Ichg: 1024
0000000457 [app] application.cpp:101, loop(): TRACE: Iterm: 4208
0000000461 [app] application.cpp:116, loop(): TRACE: Power source: vin
0000000468 [app] application.cpp:117, loop(): TRACE: Battery state: not charging
0000000471 [app] application.cpp:118, loop(): TRACE: Battery charge: 100.000000
0000005479 [app] application.cpp:97, loop(): TRACE: Current PMIC settings:
0000005480 [app] application.cpp:98, loop(): TRACE: VIN Vmin: 5080
0000005484 [app] application.cpp:99, loop(): TRACE: VIN Imax: 900
0000005492 [app] application.cpp:100, loop(): TRACE: Ichg: 1024
0000005495 [app] application.cpp:101, loop(): TRACE: Iterm: 4208
0000005504 [app] application.cpp:116, loop(): TRACE: Power source: vin
0000005506 [app] application.cpp:117, loop(): TRACE: Battery state: not charging
0000005514 [app] application.cpp:118, loop(): TRACE: Battery charge: 100.000000
0000010525 [app] application.cpp:97, loop(): TRACE: Current PMIC settings:
0000010526 [app] application.cpp:98, loop(): TRACE: VIN Vmin: 5080
0000010532 [app] application.cpp:99, loop(): TRACE: VIN Imax: 900
0000010535 [app] application.cpp:100, loop(): TRACE: Ichg: 1024
0000010544 [app] application.cpp:101, loop(): TRACE: Iterm: 4208
0000010547 [app] application.cpp:116, loop(): TRACE: Power source: vin
0000010554 [app] application.cpp:117, loop(): TRACE: Battery state: not charging
0000010565 [app] application.cpp:118, loop(): TRACE: Battery charge: 100.000000
0000398794 [app] application.cpp:97, loop(): TRACE: Current PMIC settings:
0000398795 [app] application.cpp:98, loop(): TRACE: VIN Vmin: 5080
0000398802 [app] application.cpp:99, loop(): TRACE: VIN Imax: 900
0000398803 [app] application.cpp:100, loop(): TRACE: Ichg: 1024
0000398813 [app] application.cpp:101, loop(): TRACE: Iterm: 4208
0000398815 [app] application.cpp:116, loop(): TRACE: Power source: vin
0000398824 [app] application.cpp:117, loop(): TRACE: Battery state: not charging
0000398835 [app] application.cpp:118, loop(): TRACE: Battery charge: 100.000000

Log when running test mode 2:

0000000283 [app] application.cpp:64, setup(): TRACE: Application started.
0000000283 [app] application.cpp:78, setup(): TRACE: Using PMIC APIs to configure PMIC.
0000000294 [app] application.cpp:97, loop(): TRACE: Current PMIC settings:
0000000296 [app] application.cpp:98, loop(): TRACE: VIN Vmin: 5080
0000000307 [app] application.cpp:99, loop(): TRACE: VIN Imax: 100
0000000308 [app] application.cpp:100, loop(): TRACE: Ichg: 1024
0000000318 [app] application.cpp:101, loop(): TRACE: Iterm: 4208
0000000319 [app] application.cpp:116, loop(): TRACE: Power source: unknown
0000000329 [app] application.cpp:117, loop(): TRACE: Battery state: unknown
0000000331 [app] application.cpp:118, loop(): TRACE: Battery charge: -1.000000
0000000340 [app] application.cpp:119, loop(): TRACE:
0000005343 [app] application.cpp:97, loop(): TRACE: Current PMIC settings:
0000005344 [app] application.cpp:98, loop(): TRACE: VIN Vmin: 5080
0000005345 [app] application.cpp:99, loop(): TRACE: VIN Imax: 500
0000005356 [app] application.cpp:100, loop(): TRACE: Ichg: 1024
0000005357 [app] application.cpp:101, loop(): TRACE: Iterm: 4208
0000005367 [app] application.cpp:116, loop(): TRACE: Power source: unknown
0000005372 [app] application.cpp:117, loop(): TRACE: Battery state: unknown
0000005378 [app] application.cpp:118, loop(): TRACE: Battery charge: -1.000000
0000005384 [app] application.cpp:119, loop(): TRACE:

I'll keep digging and post any finding here later.

Kind regards

@ielec , I have a few observations from your results, and comments:

Your Li-Po being tested appears to be mostly charged. You might want to try one at a lower voltage. Maybe even log the VCell Voltage instead of SOC, since SOC is an assumption where as Voltage is a direct measurement ?

Looking at your log, it takes ~10 seconds before the Min Input Voltage is established after EN Pin Shutdown for the API.

I assume that's because System Power manager waits for the PMIC to perform it's startup duties, including Datasheet Section 8.3.1.3 Power Up from DC Source: , (Link)
The linked post mentions the Data Lines (D+/D-) which may be playing a factor in my USB Connector Vs Vin results. But this gets tricky because (at that time), tying the Data lines together had different results based on Vin or USB Connector.

The diode that @tve mentions later on in the thread might also be the reason for the different results between Vin and USB,

It also mentions pmic.enableBuck(). I started using it for an EN Pin Low Powered Solar Boron after a test way back in 2018 (Link). I never understood why this had an impact based on the datasheet. I never did find any clarity on the subject.

Trial #1 required a modification to the Code during the experiment. Originally, the PMIC would not resume recharging the Li-Po if the input (solar) voltage dropped out completely. This means that charging would not resume after severe cloudy conditions, or night time. My solution was to add pmic.enableBuck(); inside the Setup() routine which runs each time the Boron Starts-up from the external Timer.


While not specific to the EN Pin charging for @runfastman's (this) thread, these are most of the "issues/unknowns/variables/etc" that I'm aware of relating to the topic.

  • Vin verses USB Connector
  • D+/D- wires,
  • Timing of PMIC's Power Up routine checks
  • Diode on USB connector’s power pin to Vin
  • enableBuck()'s influence on charging

For me, the answer is using the USB connector and the new API. I haven't personally discovered issues with that combination......but that can obviously change as the firmware matures.

Looking at your log, it takes ~10 seconds before the Min Input Voltage is established

The charging limit parameters are updated only when PMIC state changed, like USB attached/detached or an interrupt occurs on the PMIC INT pin, if using System.setPowerConfiguration(conf).

After digging deeper and doing more test cases, I found that enableBuck() does matters. I dumped the registers' value of the PMIC under variant conditions. Here is my finding:

  1. Device starts with battery attached only:
    0x7b, 0x1b, 0x20, 0x11, 0xb2, 0x8a, 0x03, 0x4b, 0x00, 0x00, 0x23
  2. Attach VUSB:
    0x7b, 0x1b, 0x20, 0x11, 0xb2, 0x8a, 0x03, 0x4b, 0x6c, 0x00, 0x23
  3. Pull down EN and release to simulate a reset without powering cycle the VUSB for several times:
    0x7b, 0x1b, 0x20, 0x11, 0xb2, 0x8a, 0x03, 0xcb, 0x6c, 0x00, 0x23
    0x7b, 0x1b, 0x20, 0x11, 0xb2, 0x8a, 0x03, 0xcb, 0x6c, 0x00, 0x23
    0x7b, 0x1b, 0x20, 0x11, 0xb2, 0x8a, 0x03, 0xcb, 0x6c, 0x00, 0x23
  4. Pull down EN and power cycle the VUSB and then release EN:
    0xfb, 0x1b, 0x20, 0x11, 0xb2, 0x8a, 0x03, 0x4b, 0x44, 0x00, 0x23

Despite the 9th register that indicating PMIC status only, the most significant of the first register is modified by powering cycle the VUSB while EN is pulled down. This bit is actually controlled by enableBuck() and disableBuck();

By adding enableBuck() in setup(), every time the EN is released no matter powering cycle EN happened while EN is pulled down or not:
0x7b, 0x1b, 0x20, 0x11, 0xb2, 0x8a, 0x03, 0x4b, 0x6c, 0x00, 0x23
, then charging can always resume. But charging cannot resumed still while EN is pulling down if powering cycle the VUSB. The reason is obviously that the buck converter is turned off once powering cycle the VUSB.

This explains why charging can resume when EN is released, since the MCU is running and it will update the PMIC settings once detected VUSB state changed. And this also explains why the test mode 2 (using PMIC methods) can resume charging only when EN is released, as enableBuck() is called.

This seams to be a hardware limitation, as we cannot control the PMIC during EN is pulled down. What we can do in software is to always enable the buck converter during initializing the PMIC at startup.

BTW, @Rftop since you are using Solar Panels as the power supply on VUSB, the supply voltage is unstable, I also found that frequent attaching/detaching VUSB during charging will block the user application for a while. But this is another story.

In conclusion, we need to investigate three things in Device OS, Cc. @avtolstoy

  1. Enable buck converter by default during PMIC initialization sequence.
  2. Figure out why frequent toggling VUSB blocks the user application.
  3. Evaluate when the charging limitation parameters should take effect.

In addition, I also tried disabling the charging termination feature, it didn't help.

Kind regards,

2 Likes