Electron stays asleep after Deep Sleep

All,

I have a situation where the electron does not wake from sleep if it misses the time to wake up. What I have noticed is that if the battery voltage drops below a certain value as it goes to sleep, it will not have enough juice to wake up on.

I am using a solar panel connected to a battery, the battery in in turn connected to the USB power input of the electron. This solution is based on the blog at Build Solar Powered & Connected Devices With Particle

The surprise is that even after the battery charges enough, the electron stays asleep. Trying to reset it manually takes several tries of plugging power in and out.

The code below is what I have running. Is there any way to solve this lack of awakening due to battery power being low at time of scheduled awakening?

// This #include statement was automatically added by the Particle IDE.
#include "ThingSpeak/ThingSpeak.h"
#include "application.h"

#define MONITOR_PIN D0
#define MODE_CONTROL_PIN D2
#define LEDPin D1
#define publish_cycle 30000 // Only publish every 10 minutes

SYSTEM_THREAD(ENABLED);

/* Thingspeak */
TCPClient client;
unsigned long myChannelNumber = 123913;
const char * myWriteAPIKey = "XXXXXXXXXXXX";
//
unsigned int lastPublish = 0;
FuelGauge fuel;
float distance;
char publishStr[20];
float timeZone = +2.0;  // my local time offset
uint32_t _TheHour;
uint32_t Sleep_Hour;
uint32_t _now;
uint32_t _hour;

unsigned long pulse;


void setup() {
    // Connect to ThingSpeak
    ThingSpeak.begin(client);
    // Give power to the sensor
    pinMode(MODE_CONTROL_PIN, OUTPUT); // Set pin 0 as trigger pin
    digitalWrite(MODE_CONTROL_PIN, LOW); // Set trigger LOW for continuous read
    pinMode(MONITOR_PIN, INPUT); // Set pin 4 as monitor pin
    pinMode(LEDPin,OUTPUT);

    
  
    // Connect variables to particle cloud
    // This allows you to save data to particle.io, and run commands against it such as "particle variable Photon get light"
    Particle.variable("dist", double(distance));
    Particle.function("batt", batteryStatus);
    Serial.begin(115200);
    
    Time.zone(timeZone); 
    if (Time.year() <= 1970) Particle.syncTime();
    
   
}  

void loop() {
    
    unsigned long now = millis();
    
    // Read value from sensor Pin
    distance = float(get_distance()); 
   
    Sleep_Hour = Time.hour();
    
    if (Sleep_Hour >= 6 && Sleep_Hour <= 18 ) {
        
    
        if (distance < 250.00 ) {
            //Turn on visual LED  so we can have visual clue when it 'sees' something
            digitalWrite(LEDPin, HIGH);
        }
        else {
            digitalWrite(LEDPin, LOW);
        }
        
        // Update the ThingSpeak fields with the new data
        ThingSpeak.setField(1, distance );
    
        // Write the fields that you've set all at once.
        // Publish to thinkspeak. We only publish if it has been 60 seconds since the last time we published
        if ((now - lastPublish) > publish_cycle) {
            ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
            lastPublish = now; // update the last time we published to current time
            Serial.println(" - Published!");
            Serial.println(String(distance));
            // I would like to see battery status as well when the distance is updated
            Particle.publish(
                "B","v:" + String::format("%.2f",fuel.getVCell()),60, PRIVATE
            );
            // as well as the distance that was recorded
            Particle.publish("D", 
                "d:" + String::format("%.2f",distance,60,PRIVATE));  
            //Particle.process(); // Looks like this helps with OTA updates
            
    
        }
       
    }
    else {
        _now = Time.now();
        _hour = Time.hour();
        //                ( till midnight UTC  ) and (  time to wake but UTC  ) and (  make local   )
        //int _secs2sleep = (86400 - _now % 86400)  +  (4 * 3600 + 00 * 60 + 00)  +  (timeZone * 3600); 
        int _secs2sleep = (86400 - _now % 86400)  +  (4 * 3600 + 00 * 60 + 00);
  
        Particle.publish("After Hours - We are sleeping", Time.format(_now + _secs2sleep));
        //Particle.publish("Current time by the hour",String(Sleep_Hour));
        //delay(1000);
        Particle.publish("Current Hour is:", Time.format(_now ));
        System.sleep(SLEEP_MODE_DEEP, _secs2sleep); 
    }
    
    
    Particle.process(); // looks like this helps with OTA updates
    
}

//get the distance from the lidar sensor
int get_distance() {
    // read the input on pin 4:
    pulse = pulseIn(MONITOR_PIN, HIGH);
    if(pulse != 0) {
       pulse = pulse / 10; // 10usec = 1 cm of distance
    }
    return pulse;
    
}



// Lets you remotely check the battery status by calling the function "batt"
// Triggers a publish with the info (so subscribe or watch the dashboard)
// and also returns a '1' if there's >10% battery left and a '0' if below
int batteryStatus(String command){
    // Publish the battery voltage and percentage of battery remaining
    // if you want to be really efficient, just report one of these
    // the String::format("%f.2") part gives us a string to publish,
    // but with only 2 decimal points to save space
    Particle.publish("B", 
          "v:" + String::format("%.2f",fuel.getVCell()) + 
          ",c:" + String::format("%.2f",fuel.getSoC()),
          60, PRIVATE
    );
    // if there's more than 10% of the battery left, then return 1
    if(fuel.getSoC()>50){ return 1;} 
    // if you're running out of battery, return 0
    else { return 0;}
}

I’d go with SYSTEM_MODE(SEMI_AUTOMATIC) and something like this check

  if(FuelGauger().getSoC() > 25)
  {
    Cellular.on();
    Particle.connect();
    waitUntil(Particle.connected);
  }
  else
  {
    Cellular.off();
    System.sleep(SLEEP_MODE_DEEP, sleep_long_enough); 
  }

@ScruffR,
Thanks for the feedback.

Is this code snippet inside of the time boundary check of between 6am and 7pm in my code? Don’t I have potential of waking it up too early before the sun is strong enough to charge the battery?

Thanks

Since you are deep sleeping I’d put that in setup() and in there you can check for any other side parameters you want (including time or even a photo resistor or what not)

thanks, I will try that out and provide feedback

Anthony

Hi @ScruffR,

I have a weird issues with deep sleep when I am using with 2 breadboard jumpers ( as water sensor). When I leave it for a day and touch the water then it does not detect and it did not wake up unless I make these jumper dry (wipe out).

I do not why drying ( wiping ) the jumpers make it work.

Any idea?

Thanks,
Satyen

I guess you got the sensors connected to WKP?
And I don’t know how they are actually placed, but I could imagine by having them wet, you may have creepage over the wet surface preventing the signal ever go below the HI/LO threshold and hence you’ll not be able to provide a detectable rising edge on WKP.

Thanks @ScruffR for reply !

I am using D0 as Wake up pin, 3v3 and GND.

Do you think changing D0 to WKP pin will help? I pretty much sure that wet surface is preventing the signal.

Thanks,
Satyen

The only pin that can wake the device from deep sleep is WKP and only with a RISING edge too.

1 Like

Hi @ScruffR,
In the document below it is mentioned that the below pin can be used for wake up and it does supports external interrupts:
D0, D1, D2, D3, D4, A0, A1, A3, A4, A5, A6, A7

https://docs.particle.io/reference/firmware/photon/#sleep-sleep-

I am using the below code for deep sleep, could you please check?

System.sleep(D0, FALLING, 3660);

Thanks,
Satyen

Since it is a water sensor the pin goes from high to low ( when the water is touched) but I am not sure about deep sleep case - My code is below

System.sleep(D0, FALLING, 3660);

Thanks,
Satyen

That is not deep sleep, which is why you can use any of those pins to wake up. For deep sleep, you would have something like this,

System.sleep(SLEEP_MODE_DEEP,6000);

If you need deep sleep, then you would have to use the WKP pin to wake it up, and you would need an inverter to invert your signal, so it goes from LOW to HIGH when the probe detects water.

1 Like

Since your topic title explicitly states: " Electron stays asleep after Deep Sleep ", that’s what I refered to - and that does in fact only wake on a rising edge on WKP (or after timeout - which is set quite long in your code).

And your calculation seems a bit off here

  if (Sleep_Hour >= 6 && Sleep_Hour <= 18 ) {
    ...
  }
  else {
        _now = Time.now();
        _hour = Time.hour();
        //                ( till midnight UTC  ) and (  time to wake but UTC  ) and (  make local   )
        //int _secs2sleep = (86400 - _now % 86400)  +  (4 * 3600 + 00 * 60 + 00)  +  (timeZone * 3600); 
        int _secs2sleep = (86400 - _now % 86400)  +  (4 * 3600 + 00 * 60 + 00);
  
        Particle.publish("After Hours - We are sleeping", Time.format(_now + _secs2sleep));
        //Particle.publish("Current time by the hour",String(Sleep_Hour));
        //delay(1000);
        Particle.publish("Current Hour is:", Time.format(_now ));
        System.sleep(SLEEP_MODE_DEEP, _secs2sleep); 
  }

If you happen to execute this bit of code between 0:00 and 4:00 UTC you will send the device to sleep till next day 4:00 UTC - so more than 24 hours deep sleep.

Thanks for this insight.

So I use the Lidar Lite Version 3 laser sensor to detect cars on one lane of a road. The traffic situation is really only important during the day time and thats my focus period.

My intention is to have the Electron turn off at 19:00Hrs (7pm) and back on at 06:00hrs (6am) the following day, regardless of when I might manually reset it. That would be the math I think I have gotten wrong. Any pointers?

Thanks

Anthony

  if (WAKE_HOUR <= Time.hour() && Time.hour() < SLEEP_HOUR)
  {
    dt = (WAKE_MINUTES - Time.minute() % WAKE_MINUTES) * 60 - Time.second();  // wake at next time boundary
  }
  else
  {
    uint32_t now = 86400 - Time.local() % 86400;

    dt = (now + WAKE_HOUR*3600) % 86400;
  }

This is how I do it in one project (only full hour boundaries, but easily extended for minutes).

thank you, will do it that way and observe.

I just have a different problem now before I get to the real issue at hand: I am not able to do any flashing at all. Neither OTA nor Serial. Will revert after I get past the non flashing problem

Anthony