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() {
}