Publishing not following sleep interval

Hi so i am using a boron device, it will be installed in the field to run on a battery, so i am trying to make use of the system.sleep function. using a interval of 10minutes
my issue is the length of the sleep isnt constistant some time i get multiple publish events within a few seconds of each other, other times its 4mins other times work no problem.
Here is my published data to the cloud.
image
my code

SYSTEM_MODE(SEMI_AUTOMATIC);
SystemSleepConfiguration config; 
MCP342X myADC;

int duration = 10*60*1000-3000; //default duration 10 minutes - 2 sec fo delay function in loop 

//created json object size number of inputs plus number or nested arrays by inputs
const int capacity = 255;
char output[capacity];//output string of same length

//ADC outputs
double ap0, ap1;

//mV per bit
const float mV = 0.0000625;

void setup() {
  //Cellular Setup
  Cellular.on(); //enable Cellular chip 
  Cellular.setActiveSim(INTERNAL_SIM); // set to internal or external simcard
  Cellular.connect(); // connect to network
  //Fetch Values on holding registers
  Particle.variable("Input1", ap0);
  Particle.variable("Input2", ap1);
  //Publish function to change duration
  Particle.function("Duration Minutes",assignduration);
  //configure i2c Bus and Devices
  Wire.begin(); // connect to i2c bus   
  myADC.configure(  MCP342X_MODE_ONESHOT | //low power mode
                    MCP342X_SIZE_16BIT |     //16bit resolution
                    MCP342X_GAIN_1X          //minimum gain to allow for 2.048V range
                  );
  Particle.connect();
}

void adc() {
  static int16_t adc0;
  static int16_t adc1; 

  //update variables
  // count out of 2.048V
  myADC.startConversion(MCP342X_CHANNEL_1);
  myADC.getResult(&adc0);
  myADC.startConversion(MCP342X_CHANNEL_2);
  myADC.getResult(&adc1);

  //convert viarbles into % of 4-20 ma range
  ap0 = ((((adc0 *mV)-.4)/1.6)*100);
  ap1 = ((((adc1 *mV)-.4)/1.6)*100);
}

void dataJson() {
  //create Json Data
  StaticJsonDocument<capacity> data;
  //Assign data in json characters
  data["input1"] = ap0;
  data["input2"] = ap1;
  serializeJson(data, output);
}

int assignduration(String command) {
  int temp1 = command.toInt();
  if (temp1 < 1){
    return 0;
  }
  duration = temp1*1000*60-3000;  //convert to milliseconds
  return duration;
}

void loop(void) {
  //update the ADC and generate JSON
  adc();
  dataJson();
  //publish data 
  Particle.publish("data", output,60, PRIVATE);
  //Particle.publishVitals();
  // needed 3 sec delay else sleep mode doesnt activate
  delay(3000);
  config.mode(SystemSleepMode::STOP)
        .network(NETWORK_INTERFACE_CELLULAR)
        .duration(duration);
  System.sleep(config);   
}

Can you check the wake reason after waking up?
Is your device even during your tests running on battery only or do you have other power sources connected too?

Instead of using delay(3000) you could also make use of SystemSleepFlag::WAIT_CLOUD to potentially save energy by going to sleep as soon the publish has been ACKed.

BTW, Cellular.setActiveSim() is a sticky setting so you’d not need to do that on each setup() and INTERNAL_SIM is the default anyhow.

And as a side note: Instead of having a fixed sleep duration I prefer to calculate the time needed in order to wake up at “cardinal times” (e.g. every full 10 minutes hh:00, hh:10, hh:20, …). That also makes it easier to catch an expected wake cycle as it won’t continually move through the day.

Im not sure how to check the reason after waking up.
I was using USB cable for power. seemed to be getting issues, but once i connected a battery wroked alot better.
i seem to be getting consistant sleep durations now, but upon commenting out delay(3000) and using .flag(systemsleepflag::wait_cloud)
im now geting upto a dozen publishes everytime it wakes up.it got so bad i had to impliment a 1 second wait after each publish.
see image

bool meterParticlePublish(void) 
{ 
  // Initialize and store value here
  static unsigned long lastPublish=0; 
  // Particle rate limits at 1 publish per second
  if(millis() - lastPublish >= 1000) {                                             
    lastPublish = millis();
    return 1;
  }
  else return 0;
}

void loop(void) 
{
    //update the ADC and generate JSON
  adc();
  dataJson();
  //publish data 
  Particle.publish("data", output,60, PRIVATE);
  //Particle.publishVitals();
  waitUntil(meterParticlePublish);
  //delay(3000);
  SystemSleepConfiguration config; 
  //SystemSleepResult result =System.sleepResult();
  config.mode(SystemSleepMode::STOP)
      .network(NETWORK_INTERFACE_CELLULAR)
      .flag(SystemSleepFlag::WAIT_CLOUD)
      .duration(duration); 
  SystemSleepResult result = System.sleep(config);   
}

This would suggest that SystemSleepFlag::WAIT_CLOUD does not work as expected. @rickkas7, can you help out here?

This might help :wink:
https://docs.particle.io/reference/device-os/firmware/boron/#wakeupreason-

Yeah I’ve seen that, in the examples.

if (result.wakeupReason() == SystemSleepWakeupReason::BY_GPIO) {
// Waken by pin
pin_t whichPin = result.wakeupPin();
}

Does this mean i essentially have to write a case statement and checking each possible wake up result

  • SystemSleepWakeupReason::UNKNOWN
  • SystemSleepWakeupReason::BY_GPIO (pin wakeup)
  • SystemSleepWakeupReason::BY_RTC (time wakeup)

That depends on whether you want your device to act differently according to the reason why it was woken up. If you don’t care you won’t need to.

But back in your original post you seemed to indicate your puzzlement as of why the device may be waking prematurely and hence my suggestion to investigate the wake reason :wink: