Electron Red Charging Status LED Flashing at 1Hz rate, not charging

I believe I’m having the same issue, a Particle Electron outside using 8W solarpanels going into VIN+GND with a capacitor on and the standard battery. It goes to deep sleep, when the battery charge gets below 5%. It went into deep sleep, discharged completely and now it simply does not boot up - instead, when sun is present, it blinks the PMIC led slowly like shown on the video below (Warning: Loud, as it’s windy on the test location)

Video: https://www.dropbox.com/s/2blysfetntj3rlm/Fil%2014-03-2017%2009.32.36.mov?dl=0

Hope you can use this, it’s critical that we find a solution, as we’re launching an initial 50 solar powered Electrons on our test grounds within the coming months.

@claursen Usually, if the Electron is Dead from low voltage the Blue LED is dimly lit.

What is the temp where the Electron is at? If it’s below 0F then you could be seeing the PMIC stopping charging when the temp is below the 0F minimum charging temp.

The RED LED is blinking at 1 Hz or 1 time per second which is probably Temp out of range fault or maybe the solar input is over voltage? I think the max solar input voltage is 20V.

Secondly, you should be using some code to prevent the Electron from operating below 20% SOC to keep the Electron from ever going completely dead. Here is my example code that shows how I easily put the Electron to Sleep when the battery SOC hit’s 20% where I go into Deep Sleep and wake up every hour to check if the SOC has risen above 20% from solar charging and if it has we go back to our normal loop. Leaving 20% in the battery will allow you to run for weeks in low power deep sleep mode keeping the Electron alive while you wait for better weather to solar charge the battery.

The example code I use to manage the battery on the Electron is below if you want to look it over.

SYSTEM_MODE(SEMI_AUTOMATIC);
//SYSTEM_THREAD(ENABLED);
// This #include statement was automatically added by the Particle IDE.
#include "Ubidots/Ubidots.h"

#define TOKEN "123456789"  // Put here your Ubidots TOKEN
#define DATA_SOURCE_NAME "ElectronSleepNew"

SerialLogHandler logHandler(LOG_LEVEL_ALL);  //This serial prints system process via USB incase you need to debug any problems you may be having with the system.

Ubidots ubidots(TOKEN); // A data source with particle name will be created in your Ubidots account


int button = D0;         // Connect a Button to Pin D0 to Wake the Electron when in System Sleep mode. 
int ledPin = D7;         // LED connected to D1
int sleepInterval = 60;  // This is used below for sleep times and is equal to 60 seconds of time. 

ApplicationWatchdog wd(660000, System.reset); //This Watchdog code will reset the processor if the dog is not kicked every 11 mins which gives time for 2 modem reset's. 

void setup() {
 //Serial.begin(115200);
 pinMode(button, INPUT_PULLDOWN);  // Sets pin as input
 pinMode(ledPin, OUTPUT);          // Sets pin as output

 ubidots.setDatasourceName(DATA_SOURCE_NAME); //This name will automatically show up in Ubidots the first time you post data. 
 
 PMIC pmic; //Initalize the PMIC class so you can call the Power Management functions below. 
 pmic.setChargeCurrent(0,0,1,0,0,0); //Set charging current to 1024mA (512 + 512 offset)
 pmic.setInputVoltageLimit(4840);   //Set the lowest input voltage to 4.84 volts. This keeps my 5v solar panel from operating below 4.84 volts.  
}

void loop() {
    
FuelGauge fuel; // Initalize the Fuel Gauge so we can call the fuel gauge functions below. 
 
    
if(fuel.getSoC() > 20) // If the battery SOC is above 20% then we will turn on the modem and then send the sensor data. 
  {
   
   float value1 = fuel.getVCell();
   float value2 = fuel.getSoC();
   
  ubidots.add("Volts", value1);  // Change for your variable name
  ubidots.add("SOC", value2);    

  Cellular.connect();  // This command turns on the Cellular Modem and tells it to connect to the cellular network. 
  
   if (!waitFor(Cellular.ready, 600000)) { //If the cellular modem does not successfuly connect to the cellular network in 10 mins then go back to sleep via the sleep command below. After 5 mins of not successfuly connecting the modem will reset.  
    
    System.sleep(D0, RISING,sleepInterval * 2, SLEEP_NETWORK_STANDBY); //Put the Electron into Sleep Mode for 2 Mins + leave the Modem in Sleep Standby mode so when you wake up the modem is ready to send data vs a full reconnection process.  
    
}  
  
     ubidots.sendAll(); // Send fuel gauge data to your Ubidots account. 

     digitalWrite(ledPin, HIGH);   // Sets the LED on
     delay(250);                   // waits for a second
     digitalWrite(ledPin, LOW);    // Sets the LED off
     delay(250);                   // waits for a second
     digitalWrite(ledPin, HIGH);   // Sets the LED on
     delay(250);                   // waits for a second
     digitalWrite(ledPin, LOW);    // Sets the LED off
  
     System.sleep(D0, RISING,sleepInterval * 2, SLEEP_NETWORK_STANDBY); //Put the Electron into Sleep Mode for 2 Mins + leave the Modem in Sleep Standby mode so when you wake up the modem is ready to send data vs a full reconnection process.  
    
  }
  else //If the battery SOC is below 20% then we will flash the LED 4 times so we know. Then put the device into deep sleep for 1 hour and check SOC again. 
  {
      
  //The 6 lines of code below are needed to turn off the Modem before sleeping if your using SYSTEM_THREAD(ENABLED); with the current 0.6.0 firmware. It's a AT Command problem currently. 
  //Cellular.on();
  //delay(10000);
  //Cellular.command("AT+CPWROFF\r\n");
  //delay(2000);
  //FuelGauge().sleep();
  //delay(2000);
  
  
  digitalWrite(ledPin, HIGH);   // Sets the LED on
  delay(150);                   // Waits for a second
  digitalWrite(ledPin, LOW);    // Sets the LED off
  delay(150);                   // Waits for a second
  digitalWrite(ledPin, HIGH);   // Sets the LED on
  delay(150);                   // Waits for a second
  digitalWrite(ledPin, LOW);    // Sets the LED off
  delay(150);                   // Waits for a second
  digitalWrite(ledPin, HIGH);   // Sets the LED on
  delay(150);                   // Waits for a second
  digitalWrite(ledPin, LOW);    // Sets the LED off
  delay(150);                   // Waits for a second
  digitalWrite(ledPin, HIGH);   // Sets the LED on
  delay(150);                   // Waits for a second
  digitalWrite(ledPin, LOW);    // Sets the LED off
  
  System.sleep(SLEEP_MODE_DEEP, 3600);  //Put the Electron into Deep Sleep for 1 Hour. 
  
  }
}    
    

What is your application for the Electrons? Love to hear how everybody is using them.

1 Like

Hi @claursen This looks like a different issue, so I'm going to break this out into a separate thread.

@RWB beat me to it while I was typing here, thanks!! I'll post mine as well...

When the charging status indicator blinks at a 1Hz rate, it indicates a Charge Suspend due to Charging Fault

Charge suspend (Input over-voltage, TS fault, timer fault, input or system over- voltage)

How high does the output voltage of your solar panels reach, unloaded?
Operating Temperature range?

When a fault occurs, the charger device sends out INT and keeps the fault state in REG09 until the host reads the fault register. Before the host reads REG09 and all the faults are cleared, the charger device would not send any INT upon new faults. In order to read the current fault status, the host has to read REG09 two times consecutively. The 1st reads fault register status from the last read and the 2nd reads the current fault register status.

If you can get your unit up and running by swapping batteries or input voltage sources, you can try this code to see what the fault is:

#include <math.h>
#include "application.h"

int pmicStatus(String args) {
    delay(3000); // build up some time for a 3-Publish burst (super hacky)

    PMIC power;
    power.begin();
    power.disableWatchdog();
    power.disableDPDM();
    // power.setInputVoltageLimit(4360); // default
    power.setInputCurrentLimit(900);     // 900mA
    power.setChargeCurrent(0,0,0,0,0,0); // 512mA
    power.setChargeVoltage(4208);        // 4.208V termination voltage
    FuelGauge fuel;
    bool LOWBATT = fuel.getAlert();
    float SOC = fuel.getSoC();
    if (LOWBATT) {
        fuel.clearAlert(); // Clear the Low Battery Alert flag if set
    }
        
    //https://github.com/spark/firmware/blob/develop/system/src/main.cpp#L287-L325
    uint8_t stat = power.getSystemStatus();
	// Read first time for previous fault
	uint8_t fault = power.getFault();
	uint8_t vbus_stat = stat >> 6; // 0 – Unknown (no input, or DPDM detection incomplete), 1 – USB host, 2 – Adapter port, 3 – OTG
	uint8_t chrg_stat = (stat >> 4) & 0x03; // 0 – Not Charging, 1 – Pre-charge (<VBATLOWV), 2 – Fast Charging, 3 – Charge Termination Done
	bool dpm_stat = stat & 0x08;   // 0 – Not DPM, 1 – VINDPM or IINDPM
	bool pg_stat = stat & 0x04;    // 0 – Not Power Good, 1 – Power Good
	bool therm_stat = stat & 0x02; // 0 – Normal, 1 – In Thermal Regulation
	bool vsys_stat = stat & 0x01;  // 0 – Not in VSYSMIN regulation (BAT > VSYSMIN), 1 – In VSYSMIN regulation (BAT < VSYSMIN)
	bool wd_fault = fault & 0x80;  // 0 – Normal, 1- Watchdog timer expiration
	uint8_t chrg_fault = (fault >> 4) & 0x03; // 0 – Normal, 1 – Input fault (VBUS OVP or VBAT < VBUS < 3.8 V),
											  // 2 - Thermal shutdown, 3 – Charge Safety Timer Expiration
	bool bat_fault = fault & 0x08;    // 0 – Normal, 1 – BATOVP
	uint8_t ntc_fault = fault & 0x07; // 0 – Normal, 5 – Cold, 6 – Hot

    String stat_str = String::format("VBUS:%d CHRG:%d DPM:%d PG:%d THERM:%d VSYS:%d", vbus_stat, chrg_stat, dpm_stat, pg_stat, therm_stat, vsys_stat);
    String fault_str = String::format("PREV - WATCHDOG:%d CHRG:%d BAT:%d NTC:%d", wd_fault, chrg_fault, bat_fault, ntc_fault);
    Particle.publish("STAT", stat_str);
    Particle.publish("PREV-FAULT", fault_str);
    
    // Read a second time for current fault
    fault = power.getFault();
    wd_fault = fault & 0x80;  // 0 – Normal, 1- Watchdog timer expiration
	chrg_fault = (fault >> 4) & 0x03; // 0 – Normal, 1 – Input fault (VBUS OVP or VBAT < VBUS < 3.8 V),
											  // 2 - Thermal shutdown, 3 – Charge Safety Timer Expiration
	bat_fault = fault & 0x08;    // 0 – Normal, 1 – BATOVP
	ntc_fault = fault & 0x07; // 0 – Normal, 5 – Cold, 6 – Hot
    fault_str = String::format("CURR - WATCHDOG:%d CHRG:%d BAT:%d NTC:%d", wd_fault, chrg_fault, bat_fault, ntc_fault);
    
    Particle.publish("CURR-FAULT", fault_str);
    
    return (int)round(SOC);
}

void setup() {
    Particle.function("stat", pmicStatus);
    
    pmicStatus("");
}

void loop() {

}
1 Like

Thank you both for replying and helping me out.

First, we’re using 20% on our other probes, but we wanted to simulate a “cold-start” to make sure it can start from 0%, which could only be a plausible scenario in winter times (in the colder, darker Nordic countries). The weather is partly cloudy with a bit of sun on most days and outside temperature is around 5 - 10 degress celcius. I do, however, believe that our solarpanel supplier might have shipped some solar panels with 12V, instead of our regular 6V ones (6W total) - this i need to test outside today.

My PMIC settings in setup() are as follows:

 // Configure PMIC
 _pmic.begin();

 // Set charging current to 1408mA (512mA + [0+0+512mA+256mA+128mA+0])
_pmic.setChargeCurrent(0, 0, 1, 1, 1, 0);

// Set input current limit to 2A
_pmic.setInputCurrentLimit(2000);

// Set input voltage limit to 4.8V (preventing the solar panels from operating below during charging)
_pmic.setInputVoltageLimit(4840);

I measured the voltage for today on the solarpanels and they were around 5.5 to 7.3V. I’ve added the code you’ve provided @BDub. replaced the battery and it will report the contents of the registers every 20 minutes or so. I’ll just let it run for now and report back with the findings. I’ve only seen the following during testing/programming the probe:

PREV - WATCHDOG:0 CHRG:1 BAT:0 NTC:0

and

PREV - WATCHDOG:1 CHRG:0 BAT:0 NTC:0

Currently it’s reporting 0 for all flags for both CURR and PREV.

These may not relate to the earlier problem though, as the probe was inside and then just put outside.

However, I wonder if it can report the registers after it dies out next time, I’ll be sure to update with any findings i have!

Again, thank you for taking the time to help me solve this.

1 Like

A quick update

I’ve let the probe run throughout the day/night, in which charged and during the night died out. When I checked the probe the next day morning, it was again blinking at 1Hz. I think I can rule out the over-voltage issues, since it can easily charge if the battery has a bit of juice. If I’m not mistaken, it should be able to charge in DEEP_SLEEP mode, correct? The last message before it died out was:

I’ve now plugged it into the USB, after which it immediately went to a solid red color. It charged for approximately an hour or so on USB, then it began blinking at 1Hz again! I believe I can rule out the solarpanels as well.

Now debugging it, I believe I can rule out input over-voltage, system over-voltage, TS fault, which leaves the timer fault?

I am sincerely confused about what it could be.

Again, thank you all for taking your time to help me solve this.

Another update, I’m noticing that the 1hz blink behaviour happens after the battery has been drained (outside using solar panels) and now it doesn’t matter whether i try to recharge via. solar or USB indoors with dedicated power.

Does anyone know what could be the culprit? I’m having difficulties figuring out what is causing it.

What is the voltage of the battery when it’s blinking 1Hz?

Also what’s the temp?

The battery will charge when the Electron is in deep sleep.

I have a Electron running with the 2000mAh battery off a 6v solar panel, and it sits outside for months a time with zero issues using the 20% SOC deep sleep code.

Is the Electron your seeing the 1hz LED flash using the 20% code or is it the units your letting drain to 0% the only ones you seeing the 1hz led flash?

Hi @RWB,

I’m letting these drain to 0% (though with a 5% SOC DEEP_SLEEP, but not enough to prevent them drain out)

I just measured the voltage on the two test batteries, both is 0 - I guess the LiPos are totally flat. How can I prevent them from dying out and becoming “unrechargable”?

I do not know if it’s a “real” problem yet, since we’re using 10.000 mAh batteries in our current test probes with a 20% SoC DEEP_SLEEP code to prevent it from going into a heavy slumber like this. However, I’d wish we could prevent a plausible scenario like this.

To the batteries are dead or the PCB that protects them is preventing a direct connection due to the low voltage disconnect feature which should reset as soon as 4v is applied to the battery terminals. Are your other sensors pulling power from this same battery also causing it to drain to empty?

The only way to prevent the total power loss is the 20% deep sleep feature. You can always upgrade to a bigger battery if you want longer run times or more bad weather run time before the 20% deep sleep code kicks in.

2 Likes

Sorry for the late reply, but I’ve done some more testing. It seems like the sensors are draining the battery empty, preventing it from charging. Now we’ve added a cut-off circuit for the sensors, so when capacity decreases below 20%, sensors are cut-off and Electron is put to sleep (as before) until the sun charges it again. I’ve programmed a small dashboard for the project that reports particle pollution on the roof of the Computer Science department since Feb. It has been out in snow, rain, hail and fog. It can be seen here: http://api.healthcity.io/dev
It has a 10.000 mAh battery and 8W solar panel.
It’s in Danish, but top graph is battery and the two lower ones are particles per cubic meter (for two different sizes of particles)

Screenshot of the battery levels since Feb 2017:

3 Likes

Beauty. :slight_smile: