Electron stop sending data after working for a while

Hi,

So I have a electron waking to count rain when a rain gauge send the signal and also wake up every 15th minute to send data to Particle Cloud. For some reasons, when I deploy it, it would work for a while and just stop.

I have the SYSTEM_MODE(SEMI_AUTOMATIC) and SYSTEM_THREAD(ENABLED), so the electron wouldn’t have to connect to internet when it wake up for rain count.

I think the problem might be here, but I cannot figure out if it is wrong. Here’s is my wake up code. This function is called at the end of loop() after it finishes sending data

void goIntoLowPowerMode(){
  long sleepLeft = calculateSleepCycleSeconds();
  long sleepPeriod = sleepLeft;
  rainCount = 0;
  long startSleep = Time.now();
  Serial.println(sleepLeft);
  Serial.println(sleepPeriod);
    while (sleepLeft > 0) {
        System.sleep(RAIN_PIN, FALLING, sleepLeft );
        sleepLeft = sleepPeriod - (Time.now() -startSleep);
        if (sleepLeft > 0) {
            Serial.print("RainCount: ");
            Serial.println(rainCount);
        }
    }
}

The calculateSleepCycleSeconds(); is just calculating how long it will be until the 0th,15th, 30th, 45th.

I also have an interrupt to increment the rain. I didn’t increment the rain after the it wakes up in goIntoLowPowerMode() because the rain just increment from interrupt I guess.

attachInterrupt(D3, rainGaugeIncrement, FALLING);//this is in setup

void rainGaugeIncrement(){
  rainCount++;
  Serial.print("Count interrupt");
  Serial.println(rainCount);
}

We are missing some info to properly advise

  • is D3 the same pin as you are using as RAIN_PIN - if so, try to go with only one of the two ways to refer to that pin :wink:
  • what does “work for a while and just stop” mean exactly - what stops? Does the device not wake anymore, does it wake at wrong times, does it wake but the code is not running anymore, is it waking and running but the cloud connection is broken, … ???
  • what do your Serial.print() statements tell you just before and while the issue hits?
  • you may want to add an additional Serial.print() statement for the case of a premature wake which informs you about the current state of your variables
  • is your rainCount declared volatile?

BTW, how have you implemented your calculateSleepCycleSeconds()?

Also, instead of sleepLeft = sleepPeriod - (Time.now() -startSleep) it might be better to call calculateSleeyCycleSeconds() again to avoid the wake/reconnect latency to accumulate and cause a drift on your desired wake time.

Finally, avoid Serial.print() statements in your ISR.

2 Likes
  • The D3 is the same as the RAIN_PIN. I will refer to that pin one way.

  • It doesn’t wake up anymore as fast as I can tell. There might have been one time that it woke up and started working for a while and then stop waking up again.

  • The problem is I don’t really know when the issue will hit. So I don’t know when to monitor the Serial.print(). Is there anyway that I can monitor the Serial.print() without having to connect to my computer right when it wakes up? Right now I am using Putty to monitor the serial output.

  • I have some Serial.print() to show all my variables in the goIntoLowPowerMode() function, but I just removed it from the code that I’m showing here because I thought it would be too messy.

  • Yes I do have my rainCount as volatile.

This is my calculateSleepCycleSeconds() ?

long calculateSleepCycleSeconds() {
  long mins = 0;

  if (Time.minute() >= 0 && Time.minute() <= 15) {
    mins = 15 - Time.minute();
  } else if (Time.minute() >= 16 && Time.minute() <= 30) {
    mins = 30 - Time.minute();
  } else if (Time.minute() >= 31 && Time.minute() <= 45) {
    mins = 45 - Time.minute();
  } else if (Time.minute() >= 46 && Time.minute() <= 60) {
    mins = 60 - Time.minute();
  }

  // on return convert it to seconds
  return (mins * 60) - Time.second();
}

I will implement sleepLeft = sleepPeriod - (Time.now() -startSleep) with calculateSleeyCycleSeconds().

Also, Is there a particular reason why I should avoid Serial.print() statement in ISR?

And Thank you for your reply.

ISRs need to be very short and light weight and Serial.print() isn’t exactly that.

You can use CLI to auto reconnect serial when the device wakes via particle serial monitor --follow but you may want to add a delay(1000) before your first printing attempt after wake to allow for the connection to be established and catch that print.

Your calculateSleepCycleSeconds can be simplified considerably.

const uint32_t PERIOD = 15*60;      // wake period when current epoch time 
                                    // is divisible by this number (aka modulo == 0)

long calculateSleepCycleSeconds() { // elaborate version
  long secNow = Time.local();
  long secInPeriod = secNow % PERIOD;
  long secTillNextPeriod = PERIOD - secInPeriod;
  return secTillNextPeriod;
}

Now single line

  long secToSleep = PERIOD - (Time.local() % PERIOD);

Optionally you can add a negative offset to wake slightly beforehand in order to ensure to be online at the due time - but then make sure to not go negative which would cause your device to “never” wake up again (which might be the reason for your issue at hand).

Wrapping all that together

const uint32_t PRE_WAKE = 5;
const uint32_t PERIOD   = 15*60;    // wake period when current epoch time 
                                    // is divisible by this number (aka modulo == 0)
  ...
  long secToSleep = PERIOD - (Time.local() % PERIOD);
  if (secToSleep > PRE_WAKE) // only go to sleep when there is some point to
    System.sleep(RAIN_PIN, FALLING, secToSleep - PRE_WAKE); 

To check whether the device woke from RTC or pin interrupt you can use wakeupReason

2 Likes

I will try everything that you suggested and see what it will me

Thank you