Sensing AC power failure

I am looking for recommendations on the best way to sense when AC power failures occur.

I have seen specialty circuits available like this one, but shipping from the UAE wouldn’t be my first choice.

Are there other, simpler methods maybe? Perhaps if the Argon was powered from the AC circuit using a USB adapter and when the Argon loses USB power and switches to LiPo it sends an alert?

@docwisdom this may be what you are looking for. I developed this to monitor the AC power in our server room so I could tell if power is lost and we go to UPS. I use a boron since I can’t depend on wifi if there is power loss and I use a lipo battery to keep things running when power is loss. The system checks in every one in a while so i know its health and sends an update when a change in source power is detected. All you have to do is plug the Boron usb into the wall and it will do the rest.

// This #include statement was automatically added by the Particle IDE.
#include <Ubidots.h>
#include "Particle.h"
#include "DiagnosticsHelperRK.h"

#define TOKEN "token here"  // Put here your Ubidots TOKEN 

Ubidots ubidots(TOKEN, UBI_HTTP); // Uncomment this line to use HTTP protocol.
//SerialLogHandler logHandler;

unsigned long lastPublish = 0;
int lastPowerSource = -1;
int linepower;
unsigned long duration = 300000;

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

void loop() {

	int powerSource = DiagnosticsHelper::getValue(DIAG_ID_SYSTEM_POWER_SOURCE);
	//if (powerSource != lastPowerSource) {
		if (millis() - lastPublish >= duration || powerSource != lastPowerSource) {
		//if (millis() - lastPublish >= 2000 && Particle.connected()) {
			lastPublish = millis();
            if(powerSource == 1 || powerSource == 2 || powerSource == 3 || powerSource == 4){
                linepower = 1;
            }
            else{
                linepower = 0;
            }
		    // 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

			lastPowerSource = powerSource;
		    ubidots.add("pwr_source", linepower); // Change for your variable name.
		    ubidots.add("source", powerSource); // Change for your variable name.
            ubidots.send(); // Will send data to a device label that matches the device Id
		}
	//}

}

Thanks! This is awesome.

I tried your code and I am getting a 0 which in the comments says “unknown”
Do you know if the DiagnosticsHelperRK requires a fuel gauge? The Argon does not have one

Just to get a few simple things out of the way, I am assuming you added the diagnosticshelperRK library and also that you are on a more recent device OS? I don’t think that this needs the fuel gauge.

Correct. I have included both the ubidots and diagnosticshelperrk library.
The console doesnt show any compiler errors and I am running 1.4.4

Here is a link straight to the source, lets give this a try.

All you need to do is change add your token where it says “token here”

https://go.particle.io/shared_apps/5e39dff2c1d2bb0016f52296

Same
image

@docwisdom hmm, have you tried resetting the Argon and trying it on battery vs. usb?

power cycled and used battery only, still value 0

@docwisdom mabye @rickkas7 can help us out here. Are we missing something simple?

The Argon doesn’t have a bq24195 PMIC so the power source detection doesn’t work.

I’m pretty sure I can detect whether there’s USB power (either USB connector or VUSB) directly from the nRF52 on the Argon (and Xenon). I’ll try to look into it tomorrow.

1 Like

@rickkas7, sweet thank you very much.

Thank you!
I would use my Boron for this but I dont get any cellular signal where I live.

OK, that was easier than I thought:

#include "Particle.h"

bool hasVUSB();
bool hadVUSB = false;


void setup() {

}

void loop() {
    bool curVUSB = hasVUSB();
    if (curVUSB != hadVUSB) {
        char buf[128];
        snprintf(buf, sizeof(buf), "VUSB=%d", curVUSB);
        Particle.publish("power", buf, PRIVATE);
        hadVUSB = curVUSB;
    }
}

bool hasVUSB() {
    uint32_t *pReg = (uint32_t *)0x40000438; // USBREGSTATUS

    return (*pReg & 1) != 0;
}

Just copy and paste the hasVUSB() function. It returns true if USB or VUSB is powered and false if not (you’re running off battery). This works on all Gen3 devices (Argon, Boron, Xenon, B Series SoM). It does not work on Gen2 (Photon, P1, Electron, E Series).

4 Likes

Works perfectly! thank you