Boron Battery Connected

I would like to know a command/method to determine if the battery is connected to a Boron.

If you disconnect the battery the cloud seems to figure it out by not displaying the battery voltage.

If I use the command fuel.getSoC(), I get a voltage weather the battery is connected or not. I considered detecting the charging current but thought I would get into trouble when the battery is fully charged.

Thoughts or possible methods?

Have you tried searching the forums for similar topics?

2 Likes

Yes but narrowed my search to Boron. I have had issues with trying to use commands/methods for other devices. I understand the power monitoring on Boron (hardware) is different than Electron and Argon. But will give that a try. And also look at your code.

Thanks!

getVCell() may work for this, but I have not tried it on a Boron with no battery connected.

https://docs.particle.io/reference/device-os/firmware/boron/#getvcell-

2 Likes

For the Boron I haven’t fully figured out all the different power management states, it’s a little bit tricky. Some friends are fuel.getVCell(), fuel.getSoC(), and pmic.getSystemStatus(). Here’s some code of mine that runs in loop() and displays some info. Not pretty or polished, but a starting point. The PMIC datahseet is your friend. Uhh, maybe “friend” is too optimistic, what the bits really mean is a bit obscure…

float batVolt = 0;
float batSoC = 0;
bool batChg = false;

void batLoop() {
    batVolt = fuel.getVCell();
    batSoC = fuel.getSoC();

    uint8_t status = pmic.getSystemStatus();
    Serial.printf("PMIC: 0x%x ", status);
    if ((status & 0xF0) == 0) {
        Serial.println("on battery");
        batChg = false;
    } else {
        Serial.print("on power, ");
        uint8_t s = (status & 0x30)>>4;
        static const char *chg[4] = {"not charging", "pre-charge", "charging", "full"};
        Serial.println(chg[s]);
        batChg = s == 1 || s == 2;
        if (s == 0) {
            // got no battery
            batVolt = 0;
            batSoC = 0;
        }
    }
    Serial.printf("Battery: %.2fV %.1f%%\n", batVolt, batSoC);

    // If the battery is charging and the source is unknown for a while then trigger DPDM detection
    static uint16_t batDPDM = 10; // start with 10 second time-out
    if ((status & 0xf0) == 0x20 || (status & 0xf0) == 0x10) {
        uint8_t opctrl = pmic.readOpControlRegister();
        if ((opctrl & 0x80) == 0 && --batDPDM == 0) {
            pmic.enableDPDM(); // trigger DPDM detection
            batDPDM = 120; // next time wait longer...
        }
    } else {
        batDPDM = 10;
    }
}
2 Likes

This code for the Electron will also work on the Boron for determining if a battery is connected:

1 Like

This method installs an interrupt handler that ends up firing 30x per second, I’m not sure that’s so cool…

Update: I tried it out and it’s not working. My Boron does not rapidly switch between fast charge and charge done when there is no battery (the charge LED also does not flicker). My code properly shows whether there is a battery while the PowerCheck class claims that there is a battery when in fact there is none.

Update 2: weird, a few minutes after posting the above the (untouched) Boron started to flicker the charging LED, i.e. rapidly switching between charging and charge-done.

Update 3: there seems to be some timer in that charging stuff (surprise, surprise). When I apply power to the Boron the charging circuit does not oscillate. At some point it flips to oscillating. The output I see on my sketch (loops every 2 seconds) changes in that the fuel gauge sees a battery voltage jump:

PMIC: 0x45 on power, not charging
Battery: 0.07V 72.2%
PowerCheck starting
hasPower=1
hasBattery=1
getIsCharging=0
**********
PMIC: 0x45 on power, not charging
Battery: 0.07V 71.6%
PowerCheck starting
hasPower=1
hasBattery=1
getIsCharging=0
**********
PMIC: 0x64 on power, charging
Battery: 4.08V 71.3%
PowerCheck starting
hasPower=1
hasBattery=0
getIsCharging=0
**********
PMIC: 0x74 on power, full
Battery: 4.09V 71.3%
PowerCheck starting
hasPower=1
hasBattery=0
getIsCharging=0

Oh, wait, do you have a Boron LTE? That code probably won’t work right because the Boron LTE has other code to turn off charging when there is no battery so the LED doesn’t flicker all the time. That’s done because the battery is not required on the Boron LTE. The two things are probably interfering with each other.

I think the value is stored in the device diagnostics data, it can probably be retrieved from there instead.

Yes, it’s a Boron LTE.

OK, this is a much better way to do it, using the DiagnosticsHelperRK library. I added a new example to the library for power source:

#include "Particle.h"

#include "DiagnosticsHelperRK.h"

SerialLogHandler logHandler;

unsigned long lastPublish = 0;
int lastPowerSource = -1;

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

void loop() {

	int powerSource = DiagnosticsHelper::getValue(DIAG_ID_SYSTEM_POWER_SOURCE);
	if (powerSource != lastPowerSource) {
		if (millis() - lastPublish >= 1000 && Particle.connected()) {
			lastPublish = millis();

		    // POWER_SOURCE_UNKNOWN = 0,
			// POWER_SOURCE_VIN = 1,
			// POWER_SOURCE_USB_HOST = 2,
			// POWER_SOURCE_USB_ADAPTER = 3,
			// POWER_SOURCE_USB_OTG = 4,
			// POWER_SOURCE_BATTERY = 5

			char buf[128];
			snprintf(buf, sizeof(buf), "powerSource=%d", powerSource);

			Particle.publish("powerSource", buf, PRIVATE);
			Log.info(buf);

			lastPowerSource = powerSource;
		}
	}

}

powerSource

4 Likes

Sorry for the delay.

The best solution I found was a combination of using getVCell() to determine if the battery is connected and DiagnosticsHelperRK.h for detecting the power source.

I found that with the battery disconnected on a Boron LTE the value returned was close to zero, (0.06 disconnected and 4.X volts connected). So that works for me!

I also found DiagnosticsHelperRK.h works very well for determining the power source for the Boron LTE. My project will be located in remote Alaska and knowing the current power source and level will be essential.

Thank You for everyones help!

Albert

How long did you wait with your battery disconnected, 'cause that's not what I see. See my post above: Boron Battery Connected - #7 by tve

It is in a routine that is only checked once every 10 minutes to save cellular data. It also runs on boot-up so I would say 30-45 seconds when I got the first reading.

Albert

Thanks for this library and the others you have shared - they have really helped our projects.

I am having some challenges with power monitoring on the Xenon. DiagnosticsHelper::getValue(DIAG_ID_SYSTEM_POWER_SOURCE) returns 0 on the Xenon even when it has USB and battery. The exact same code on a Boron with the same peripherals and state returns 3.

I don’t know if it is related, but when I tried to read the power state with PMIC, it works fine on Boron but the exact same code throws this error when compiled for Xenon error: 'PMIC' does not name a type.

Have you encountered this difference? Is there a way to check power status on Xenon? Can the same power code work on both Xenon and Boron?

The Argon and Xenon don't sport a PMIC chip.
Here is the block diagram for the Boron
https://docs.particle.io/datasheets/cellular/boron-datasheet/#block-diagram

And here for the Xenon
https://docs.particle.io/datasheets/mesh/xenon-datasheet/#block-diagram

To know whether or not the LiPo is charging you can have a look at this discussion

i tried the diagnostichelperRK this morning on my boron and i was swapping between battery power and usb connection power and my reported readings were 5 for battery source (which was correct) whenever running on battery and 1 for VIN source (is this correct?) when i connected the usb cable to a usb powered hub. if i plugged the usb cable into my laptop the reading was 2 which is usb host, that seems correct. if i plug the usb cable directly into a usb wall power supply i get a 1 for VIN (is this correct?) i guess i should add that prior to reading this whole thread i had flashed the electron example rickkas7 linked to and that crashed my boron. so i came back and finished the whole thread and saw ricks, “oh, wait, are you using the LTE.?..” then use this… so i the flashed the new suggested routine and that’s what is giving me the results. question i have is did the electron routine flash mess up my current power source numbering system? anyway, here’s console report,