Photon hang with constant cyan

Hi,

I have a photon that open and closes irrigation using relay.
it all works sometimes for weeks without any issue but then it stuck.
led in on without blink on cyan, and loop is stuck no trace or anything else…
the only thing to do is restart.

I’m using latest firmware and about to give up, please help

Code?

1 Like
// This #include statement was automatically added by the Particle IDE.
#include <SparkIntervalTimer.h>

SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(AUTOMATIC);
ApplicationWatchdog wd(300000, System.reset);
#include "timing.h"

// This #include statement was automatically added by the Particle IDE.
#include <Ubidots.h>
/*
 * Project IOD
 * Description: open close
 * Author:Mor yegerman
 * Date:25/5/2017
 */

#define UBI_TOKEN "xxxxxxxxxxxxxxxxxxxxx"
#define TRANSMIT_INTEVAL 60000

#define DEVICE_ID "iod_garden" //(iod 1) api label
#define SENSOR_ID "iod_sensor"
#define OPEN_SET_POINT "open_setpoint"
#define CLOSE_SET_POINT "close_setpoint"
#define OpenCloseBit_Device "openclosebit"
#define DURATION "duration"
#define VALVE_PIN D5
#define DEBUG_MODE true

Ubidots ubidots(UBI_TOKEN);  //set my token
float sensorValue=100;
float openSetpoint=0;
float closeSetpoint=0;
float valveState = 0;
float irrigation_duration = 0;
unsigned long irrgtionTime=0;
timing IrrigstionTimer;
timing * myTimer = new timing();
int failCount=0;
Logger appLog("app");
SerialLogHandler logHandler( LOG_LEVEL_TRACE, {
  { "app", LOG_LEVEL_TRACE }
});



 void setup() {
   pinMode(VALVE_PIN, OUTPUT); //Set CW as an output//
   openValve(0);
   WiFi.selectAntenna(ANT_EXTERNAL); // selects the u.FL antenna
  waitFor(Particle.connected, 30000);
  getAllUbiData();

 }

 void loop() {
   delay(150);
   wd.checkin(); // resets the AWDT count
   if(sensorValue <= openSetpoint && valveState==0)
  {
    appLog.info("Openin irrigation on min threshhold");
    openValve(1);
    }
    else
    {
     if(sensorValue >= closeSetpoint && valveState==1) // high threshhold
      {
        appLog.info("closing irrigation Openin irrigation on max threshhold");
        openValve(0);
      }
      else
      if(irrigation_duration>0 && IrrigstionTimer.isEnded() && valveState==1) //only timer
          {
            appLog.info("closing on intreval");
            openValve(0);
          }
    }

   transmitData();

 }

bool openValve(int bOpen)
{

  if(bOpen==1){
     digitalWrite(VALVE_PIN,LOW);

     appLog.info("irrigation duration is now open");
     IrrigstionTimer.start(irrigation_duration*60000);
     irrgtionTime = 0;
     valveState = 1;
  }
  else{
    digitalWrite(VALVE_PIN,HIGH);
    appLog.info("closing the irrigation");
    irrgtionTime = IrrigstionTimer.getRunTime()/60000;
    IrrigstionTimer.stop();
    valveState = 0;
  }

}

 float getUbiVal(char* device, char* variable)
 {
    float tmp = ubidots.getValueWithDatasource(device, variable);

    if(tmp!=ERROR_VALUE){
  //    appLog.info(("getting data from ubi:" + String(tmp));
      return tmp;
    }
    else
    {
//      appLog.info(("Error getting Ubi data");
      return ERROR_VALUE;
    }



 }


 /*****************************************************
 transmitData: sends data to cloud
*****************************************************/

void getAllUbiData()
{
    
    if (waitFor(WiFi.ready, 60000)) {
            float tmp_Duration = getUbiVal(DEVICE_ID,DURATION);
          if(tmp_Duration!=ERROR_VALUE)
          {
            irrigation_duration = tmp_Duration;
            appLog.info("Interval:%.1f", irrigation_duration);
          }
        
        
          float tmpsensor = getUbiVal(DEVICE_ID,SENSOR_ID);
          if(tmpsensor!=ERROR_VALUE)
          {
            sensorValue = tmpsensor;
            appLog.info("got sensor val:%.2f" ,sensorValue );
          }
          tmpsensor= getUbiVal(DEVICE_ID,OPEN_SET_POINT);
          if(tmpsensor!=ERROR_VALUE)
          {
            openSetpoint = tmpsensor;
            appLog.info("got OPEN_SET_POINT:" + String(openSetpoint) );
          }
        
          tmpsensor= getUbiVal(DEVICE_ID,CLOSE_SET_POINT);
          if(tmpsensor!=ERROR_VALUE)
          {
            closeSetpoint = tmpsensor;
            appLog.info("got CLOSE_SET_POINT:" + String(closeSetpoint) );
          }
    }
    else
    {
        appLog.error("no wifi");
        System.reset(1);
    }
    

  

}
void transmitData()
{
      myTimer->start(TRANSMIT_INTEVAL);
      if(!myTimer->isEnded())
        return;
      else
          myTimer->stop();
          
      if (waitFor(WiFi.ready, 60000)) {
        appLog.info("openclosebit sending:" + String(valveState));
          if(irrgtionTime>0)
          {
              ubidots.add("IrrigaitonTime", irrgtionTime);
              irrgtionTime=0;
          }
    
          ubidots.add("openclosebit",valveState);
          ubidots.add( "rssi", (100 + WiFi.RSSI()));
    //sendind
            ubidots.setDeviceLabel(DEVICE_ID);
            if(ubidots.sendAll() && Particle.connected())
            {
              failCount = 0;
              appLog.info("Sucess Trasmiting data");
            }
            else
            {
               appLog.error("Error Trasmiting data");
               if(failCount++ > 10)
                System.reset();
            }
            
            getAllUbiData();
            myTimer->stop();
    }
    else
    {
        appLog.error("no wifi");
        System.reset(1);
    }
}

Just a few notes:

  • to assess the whole code, we’d also need to see the implementation of the timing class
  • if you are not using SparkIntervalTimer remove them from the project
  • what version are you targeting? With 0.7.0 you would run into issues with this ApplicationWatchdog wd(300000, System.reset);
  • change instructions like appLog.info("got OPEN_SET_POINT:" + String(openSetpoint) ); the same way as you’ve already written appLog.info("got sensor val:%.2f" ,sensorValue ) - String objects may (over time) lead to issues
3 Likes

Thanks, i will make the changes you sugested
im using v8 /10,
what does constant cyon indicates?

adding timing code

#include "timing.h"
#include "Particle.h"



timing::timing()
{
    isStarted = false;
    startTime = 0;
    interval=0;
}

void timing::start (long intvl)
{
    interval = intvl;
     if(!isStarted)
     {
         startTime =  millis();
         isStarted = true;
         endTime = 0;
     }


}
void timing::start (void)
{
    //interval = intvl;
     if(!isStarted)
     {
         startTime =  millis();
         isStarted = true;
         endTime = 0;
      //   Serial.println("starting timer");
     }

}

void timing::stop (void)
{
    if(isStarted)
      endTime =  millis() - startTime;

    isStarted = false;
    startTime=0;

}

bool timing::isEnded(void)
{
    if(startTime==0 || interval==0)//no start
        return false;

    endTime =  millis() - startTime;
    if( endTime > interval)
     {
         return true;
     }
    else
        return false;
}

unsigned long timing::getRunTime(void)
{
  return millis() - startTime;
}

Any "constant" or static colour - if not controlled by user code - indicates a Device OS deadlock of some sort.

Since we can't see the declaration of the class (timing.h) I'm going to assume your timing variables are uint32_t or unsigned long, right? Anyway long intvl should also be unsigned.

BTW, is this intended, that when you only ask isEnded() that the endTime is actually set? Seems somewhat counterintuitive.

1 Like

@moryegerman here is my take:

  1. Don’t use delay(150); in loop(). Instead replace it with a non-blocking millis() timer set for 150ms. You can then move the wd.checkin() after the delay if you wish.
  2. Your ‘timing’ class is essentially a millis() timer. Personally, I would use a Software Timer set to the desired interval. The timer callback can set a “done” flag that you can read and reset in your code. This will simplify things a lot. This would apply to both IrrigstionTimer and myTimer.
  3. The ubidots library may be blocking. In setup() you wait for Particle.connected but you don’t test if the WiFi is actually connected before calling getAllUbiData().

ALL of @ScruffR suggestions are relevant as well.

2 Likes