Crashing Photon (fast blinking green after a while)

I’ve been trying to get the openEnergyMonitor project running on my Photon.

I’m using the following code and it seems to work quite good for a while but then it hard crashes (requiring a power toggle) or just reboots.

What can be the source of error? My Particle is connected to two CT sensors, an AC/AC adapter and one pulse counter via a modified emonTXv2 (where changed the burden resistors to the CTs to 18ohm to comply with 3.3V).

I get quite good readings so there is nothing wrong with the hardware, but it is really annoying that the Photon restarts and crashes. (It is currently powered by a 2A 5V adapter).

#define APIKEY ""
#define emonTxV3

#include "EmonLib/EmonLib.h"

TCPClient myTCP;
EnergyMonitor ct1,ct2,ct3,ct4;  // Create  instances for each CT channel

#define FILTERSETTLETIME 5000         //  Time (ms) to allow the filters to settle before sending data

//http://openenergymonitor.org/emon/buildingblocks/calibration
const float Ical1 = 111.1; // (2000 turns / 18 Ohm burden) = 111.1
const float Ical2 = 111.1; // (2000 turns / 18 Ohm burden) = 111.1
const float Ical3 = 111.1; // (2000 turns / 18 Ohm burden) = 111.1
const float Ical4 = 111.1; // (2000 turns / 18 Ohm burden) = 111.1

//const float Vcal = 268.97; // (230V x 13) / (9V x 1.2) = 276.9 Calibration for UK AC-AC adapter 77DB-06-09 
const float Vcal  =   260; //  Calibration for EU AC-AC adapter 77DE-06-09 
const int ppwh = 1;                                                   // 1000 pulses/kwh = 1 pulse per wh - Number of pulses per wh - found or set on the meter.

const byte Vrms=                  230;                               // Vrms for apparent power readings (when no AC-AC voltage sample is present)
const byte TIME_BETWEEN_READINGS= 10;            //Time between readings   
const float phase_shift=          1.7;
const int no_of_samples=          1480; 
const int no_of_half_wavelengths= 20;
const int timeout=                2000;                               //emonLib timeout 
const int ACAC_DETECTION_LEVEL=   3000;
const byte min_pulsewidth=        110;                                // minimum width of interrupt pulse (default pulse output meters = 100ms)
const int pulse_count_ppwh=       10;
const int TEMPERATURE_PRECISION=  11;                          //9 (93.8ms),10 (187.5ms) ,11 (375ms) or 12 (750ms) bits equal to resplution of 0.5C, 0.25C, 0.125C and 0.0625C
const byte MaxOnewire=            6;                            
const byte pulse_countINT=        D3;
const byte LEDpin=                D7;
const byte inPinV=                A0;

boolean CT1=1, CT2=1, CT3=1, CT4=1, ACAC=1, debug=1, DS18B20_STATUS=0;
byte CT_count=0;
volatile unsigned int pulseCount = 0;
volatile unsigned int pulsePower = 0;
unsigned long pulsetime = 0;                                      // Record time of interrupt pulse        

typedef struct { 
  int power1, power2, power3, power4, Vrms, temp[MaxOnewire]; 
  unsigned int pulseCount; int pulsePower;
} PayloadTX;     // create structure - a neat way of packaging data for RF comms
  PayloadTX emontx; 


//*********************************************************************************************************************
double calc_rms(int pin, int samples) {
  unsigned long sum = 0;
  for (int i=0; i<samples; i++) // 178 samples takes about 20ms
  {
    int raw = (analogRead(0)-512);
    sum += (unsigned long)raw * raw;
  }
  double rms = sqrt((double)sum / samples);
  return rms;
}

// The interrupt routine - runs each time a falling edge of a pulse is detected
void onPulse() {
  if ( (millis() - pulsetime) > min_pulsewidth) {
    pulseCount++;					//calculate wh elapsed from time between pulses
    pulsePower = int((3600000000.0 / (micros() - pulsetime))/ppwh);
    pulsetime = millis();
  }

}

void sendGetRequest(const char * server, const char * url) {
    if (myTCP.connect(server, 80)) {
        Serial.print("Connected to Server");
        myTCP.print("GET ");
        myTCP.print(url);
        myTCP.println(" HTTP/1.1");
        myTCP.println("Connection: close");
        myTCP.print("Host: ");
        myTCP.println(server);
        myTCP.println();
        myTCP.println();
        myTCP.flush();
        myTCP.stop();
    } 
}

void send_data() {
    digitalWrite(D7, HIGH);
    String data = "";
    data += "power1:" + String(emontx.power1);
    data += ",power2:" + String(emontx.power2);
    data += ",power3:" + String(emontx.power3);
    data += ",power4:" + String(emontx.power3);
    data += ",Vrms:" + String(emontx.Vrms);
    data += ",temp:" + String(emontx.temp[0]);
    data += ",pulseCount:" + String(emontx.pulseCount);
    data += ",pulsePower:" + String(emontx.pulsePower);
    data += ",uptime:" + String(millis()/1000);

    String path = "/input/post.json?node=test&json={" + data + "}&apikey=" + APIKEY;
    sendGetRequest("emoncms.org", path);
    digitalWrite(D7, LOW);
}

void setup() {

  pinMode(A0, INPUT); pinMode(A1, INPUT); pinMode(A2, INPUT); pinMode(A3, INPUT); pinMode(A4, INPUT);
  pinMode(pulse_countINT, INPUT);
  
  RGB.control(true);

  Serial.begin(9600);
  Serial.println(F(""));
  Serial.println(F("OpenEnergyMonitor.org"));
  Spark.publish("init", "OpenEnergyMonitor.org");
  
  attachInterrupt(pulse_countINT, onPulse, FALLING);     // Attach pulse counting interrupt   CT1=1;CT2=1;CT3=1;CT4=1;CT_count=4;

  // Calculate if there is an ACAC adapter on analog input 0
  //double vrms = calc_rms(0,1780) * (Vcal * (3.3/1024) );
  double vrms = calc_rms(A0, 1780) * 0.87;
  if (vrms>90) ACAC = 1; else ACAC=0;

  if (CT1) ct1.current(A1, Ical1);
  if (CT2) ct2.current(A2, Ical2);
  if (CT3) ct3.current(A3, Ical3);
  if (CT4) ct4.current(A4, Ical4);
  
  if (ACAC) {
    if (CT1) ct1.voltage(A0, Vcal, phase_shift);          // ADC pin, Calibration, phase_shift
    if (CT2) ct2.voltage(A0, Vcal, phase_shift);          // ADC pin, Calibration, phase_shift
    if (CT3) ct3.voltage(A0, Vcal, phase_shift);          // ADC pin, Calibration, phase_shift
    if (CT4) ct4.voltage(A0, Vcal, phase_shift);          // ADC pin, Calibration, phase_shift
  }
  RGB.control(false);
}

void loop() {
  if (ACAC) {
    delay(200);                         //if powering from AC-AC allow time for power supply to settle    
    emontx.Vrms=0;                      //Set Vrms to zero, this will be overwirtten by CT 1-4
  }
  
  if (CT1) {
    if (ACAC) {
     ct1.calcVI(no_of_half_wavelengths,timeout); emontx.power1=ct1.realPower;
     emontx.Vrms=ct1.Vrms*100;
   } else
     emontx.power1 = ct1.calcIrms(no_of_samples)*Vrms;                               // Calculate Apparent Power 1  1480 is  number of sample
  }
  
  if (CT2) {
    if (ACAC) {
      ct2.calcVI(no_of_half_wavelengths,timeout); emontx.power2=ct2.realPower;
      emontx.Vrms=ct2.Vrms*100;
   } else
      emontx.power2 = ct2.calcIrms(no_of_samples)*Vrms;                               // Calculate Apparent Power 1  1480 is  number of samples
  }


  if (CT3) {
    if (ACAC) {
      ct3.calcVI(no_of_half_wavelengths,timeout); emontx.power3=ct3.realPower;
      emontx.Vrms=ct3.Vrms*100;
   } else
      emontx.power3 = ct3.calcIrms(no_of_samples)*Vrms;                               // Calculate Apparent Power 1  1480 is  number of samples
  }

  if (CT4) {
   if (ACAC) {
      ct4.calcVI(no_of_half_wavelengths,timeout); emontx.power4=ct4.realPower;
      emontx.Vrms=ct4.Vrms*100;
   } else
      emontx.power4 = ct4.calcIrms(no_of_samples)*Vrms;                               // Calculate Apparent Power 1  1480 is  number of samples
  }

  if (pulseCount)                    // if the ISR has counted some pulses, update the total count
  {
    emontx.pulseCount += pulseCount;
    pulseCount = 0;
    emontx.pulsePower = pulsePower;
  }

  send_data();

  delay(TIME_BETWEEN_READINGS*1000);
}

Flashing green is an issue connecting to your router. Is it in a place with good wifi reception?

How often has this error been happening? I tend to get this error when I first set up a sensor but then after a few hours it stops.

Thank you!

It actually is a fast blinking blue+green (whatever that color is). I’ve added an old PS3 antenna I had laying around with hopes that it is just a WiFi connection issue.

I have same issue and my Photon is right next the the router. I can not yet determine why this happens for my case but trying to keep logs. If I find something I will let you know!

I’m considering adding a test of WiFi and Cloud connectivity into the loop() something like this:

if (!WiFi.ready()) 
  WiFi.connect();
if (!Spark.connected()) 
  Spark.connect();

I tested a basic “send a GET request every 10s” and my (other) Photon and now it is reported offline (while still “breathing” blue/green).

What is wrong? Do I need to close the TCPClient in a more sophisticated way?

#define MaxOnewire 6
#define APIKEY ""

TCPClient myTCP;

typedef struct { 
  int power1, power2, power3, power4, Vrms, temp[MaxOnewire]; 
  unsigned int pulseCount; int pulsePower;
} PayloadTX;
  PayloadTX emontx; 


void sendGetRequest(const char * server, const char * url) {
    if (myTCP.connect(server, 80)) {
        Serial.print("Connected to Server");
        myTCP.print("GET ");
        myTCP.print(url);
        myTCP.println(" HTTP/1.1");
        myTCP.println("Connection: close");
        myTCP.print("Host: ");
        myTCP.println(server);
        myTCP.println();
        myTCP.println();
        myTCP.flush();
        myTCP.stop();
    } 
}

void send_data() {
    digitalWrite(D7, HIGH);
    String data = "";
    data += "power1:" + String(emontx.power1);
    data += ",power2:" + String(emontx.power2);
    data += ",power3:" + String(emontx.power3);
    data += ",power4:" + String(emontx.power3);
    data += ",Vrms:" + String(emontx.Vrms);
    data += ",temp:" + String(emontx.temp[0]);
    data += ",pulseCount:" + String(emontx.pulseCount);
    data += ",pulsePower:" + String(emontx.pulsePower);
    data += ",uptime:" + String(millis()/1000);
    Spark.publish("data", data);
    
    String path = "/input/post.json?node=13&json={" + data + "}&apikey=" + APIKEY;
    sendGetRequest("emoncms.org", path.c_str());
    digitalWrite(D7, LOW);
}


void setup() {

}

void loop() {
  send_data();
  delay(1000*10);
}

Try updating your system firmware to the latest release on the github releases page of the firmware repo. It has many stability fixes including WiFi.

Thank you @mdma, where can I find more information of DFU upgrade, the link on this page seems to be dead: https://docs.particle.io/guide/getting-started/modes/photon/#dfu-mode-device-firmware-upgrade-?

The download link in the docs - https://s3.amazonaws.com/spark-assets/dfu-util-0.8-binaries.tar.xz - works for me, it’s downloading the zipped DFU files.

Thank you @mdma, upgraded according to https://github.com/spark/firmware/releases (unfortunatly I got the 4.4-rc5 and not final) stability is much better now.

I’ve had some glitches running this code for the last few hours. Where updates stalled for up to 60 seconds, but without reboots or hangs of the particle.