Setting Up Electron Sleep to save data

I just received my first Electron on 9/6/17 and set it up adding Node.js, Particle CLI and DFU-Util and after upgrading the system firmware from 0.4.x to 0.6.0 using the particle_firmware_manager-v0.6.0-osx got it connected to the cloud. I had been doing my development using a Photon since 4/17 and the fw version on the Photon was 0.6.2. I could not find a 0.6.2 manager for OS X. I tried putting the Electron in DFU mode and using the CLI, issued a particle update but the info shown on Particle Devices on the web IDE showed the firmware as 0.6.0, I set the pulldown target menu to 0.6.2. Is there a way I can I verify the actual fw version on my Electron?

I used CLI to send (Serial over USB) my latest working version of my data collection code. Within a minute I was publishing to the cloud. I rechecked my usage after 2 hours and I was already at 0.8Mb so I adjusted my data limit down to 1Mb. In the morning I received an email saying my device had been paused at 1.48Mb. So now I need to figure out how to setup up Deep Sleep on the Electron to conserve data.

I tried adding SYSTEM_MODE(AUTOMATIC); , STARTUP(System.enableFeature(FEATURE_RETAINED_MEMORY)); and Particle.keepAlive() to my code, but my code won’t compile. So I wondering if the system fw is incorrect for these commands. I tried adding one at a time with no luck. I’m a newbie at this and could please use some help. I’ve been reading about a 23 minute keep alive that should reduce cloud connection data usage quite a bit but I’m not sure how exactly to use this feature. I was thinking about trying a 2 hour Deep Sleep to see how much data I go through publishing every 2 hours.
Thanks for any suggestions regarding this issue.

First make sure you got the desired device selected (golden star next to the device in Web IDE).

With the Particle SIM you don’t need to set keepAlive() and SYSTEM_MODE(AUTOMATIC) is default too.

To check - and possibly update - your system, you should get the most recent CLI (particle --version should be 1.24.0).
In Listening Mode run

particle identify

If this doesn’t give you 0.6.2 put the device in DFU Mode and run

particle update

If the device is 0.6.2 but Web IDE still shows 0.6.0, try the CLEAR CACHE button in the settings drawer (bottom gear :gear: icon) of Web IDE.

If this still doesn’t help, try to flash a dummy 0.6.0 sketch (empty setup() & loop()) OTA.

Good Morning,
Good news typing particle identify came back with 0.6.2 and now the Particle Devices also is showing 0.6.2.

I had tested a WiFi version of Sleep code on my Photon for a 30 minute sleep time and it seamed to wake after 30 minutes and publish data to the cloud but I had no idea how much data was being used with each publication. I rewrote it and was going to try today on the Electron, replacing wifi.Ready with cell.Ready. Here’s what I came up with. What do you think of this as a starting place?
Thanks so much for your help.

I added these lines just above the start of the publishing code.
// Make sure Electron is connected to the cloud
if (Particle.connected() == false) {
Particle.connect();

This code is at the very end of the Loop
bool cellReady = Cellular.ready(); // Cellular (Electron)
bool cloudReady = Particle.connected();
Serial.printlnf(“wifi=%s cloud=%s counter_slp=%d retainedCounter_slp=%d”, (cellReady ? “on” : “off”), (cloudReady ? “on” : “off”),counter_slp++, retainedCounter_slp++);

if (cellReady) {
	if (firstAvailable == 0) {
		firstAvailable = millis();
	}
	if (millis() - firstAvailable > 30000) {
		// After we've been up for 30 seconds, go to sleep. The delay is so the serial output gets written out before
		// sleeping.
		Serial.println("calling System.sleep(SLEEP_MODE_DEEP, 300)");
		delay(2);

		System.sleep(SLEEP_MODE_DEEP, 60 * 30);//1800secs/30min of Sleep now

		// The rest of the code here is not reached. SLEEP_MODE_DEEP causes the code execution to stop,
		// and when wake up occurs, it's like a reset where you start again with setup(), all variables are
		// cleared, etc.
		Serial.println("returned from sleep, should not occur");
	}
}
else {
	firstAvailable = 0;
}// End of Sleep code

}

Deep sleep won’t return to the instruction following the sleep statement but will restart from scratch (but reading the comment shows you already knew ;-))

To save data you either should sleep less than 23 minutes or considerably longer - in both cases use the SLEEP_NETWORK_STANDBY option to cut down the reconnection “cost” by reusing the previous connection.

So I just substituted "System.sleep(WKP, RISING, 1200, SLEEP_NETWORK_STANDBY);" for the my original line of System.sleep(SLEEP_MODE_DEEP, 60 * 30 * 4); and added at the beginning, STARTUP(System.enableFeature(FEATURE_RETAINED_MEMORY));

I set the sleepForSeconds to 1200 equalling 20mins. , correct? and downloaded my code. The LED is still OFF is that the correct behavior for SLEEP_NETWORK_STANDBY? So does that mean it won't have to re-register with the network at every wake-up?
Thanks again.:slight_smile:

It should be

  System.sleep(SLEEP_MODE_DEEP, 1200, SLEEP_NETWORK_STANDBY);

Retained memory doesn’t have anything to do with sleep mode (other than variables surviving a deep sleep or reset).

Just made the correction so I’ll let it run now and watch the usage graph.
System.sleep(SLEEP_MODE_DEEP, 1200, SLEEP_NETWORK_STANDBY);


Thanks for the suggestion.

1 Like

I’ve been trying to get my data logger data rate down, I have 7 data points, all floats and I’m exceeding the 3Mb/month.
I tried setting it back to System.sleep(SLEEP_MODE_DEEP, 1200, SLEEP_NETWORK_STANDBY); but when it makes the graph shows a Reset at the beginning and I thought was causing more handshaking on every wake from sleep.

and the slope on my usage graph looks like it is getting steeper using SLEEP_MODE_DEEP.
The sleep time during these records was 22 mins. So I switched back to System.sleep(WKP, 1320, SLEEP_NETWORK_STANDBY); the Reset went away upon Waking.
Still too much data, so I tried combing 4 temps on one event but screwed up the formatting so the data was unreadable.

Next step was go back to 7 individual events but set the Sleep time to 2 hours. Flashed new FW after 10:00pm last night and my last captured event was at 14:30 today. The last data rates measured using the Particle app on my iPhone gives me a data rate of 0.009Mb/hr or over 6Mb/month. Does this sound about right for just 7 items sampled every 2 hours? I should mention that I’m send 2 samples to ThingSpeak during each wake period. I thought my data logger with one using 7 events would be no problem for the data plan. Since I was developing on the Photon I had no idea of the overhead costs associated with sending UDP packets. This is my first project so I sure my code isn’t very efficient . I’m willing to try any ideas or suggestions.
Thank you.

The reset after wake is normal for deep sleep, but the reconnect cost should be a lot less with SLEEP_NETWORK_STANDBY than without (with waking at least once in less than 23min).
However, I’d still pull all your values together into one event instead of seven.

2 Likes

Just coded all 7 samples to 1-Event and the Sleep mode is System.sleep(SLEEP_MODE_DEEP, 60 * 30 * 4, SLEEP_NETWORK_STANDBY); and that is working great. Thanks again for the suggestion.

Waking from Sleep Help
I plan to have a water leak detector state bit which would be published to the cloud and trigger an IFTTT event. I tested the operation and all worked fine but this was without using Sleep. It looks like the Electron will be waking up, every 2 hours so I need to be able to wake from sleep if this sensor goes low, indicating the presence of water.
I’m using D5 for (waterDetected), pinMode(waterdetectPin, INPUT); and D7 for (alarmPin0, pinMode(alarmPin, OUTPUT);. It looks like I just need to connect a wire to the WKP pin and the use one of the sleep modes that lets you assign a wakepin and direction.
Can anyone suggest which mode to use? Can I add parameters to the modes like this:System.sleep(A7,FALLING,7200,SLEEP_NETWORK_STANDBY):// 2hrs sleep? Or is there is an error in my logic?

Since I need to wake the Electron immediately, does this prevent me from using SLEEP_MODE_DEEP?
If I use a mode like System.sleep(A7,FALLING,7200,SLEEP_NETWORK_STANDBY):, will the pin that is used to wake the device need to be defined in the setup() area?
Or is that automatically taken care of when you use the command?
Should I also use Particle.keepAlive(23 * 6);?
I found an example of this in the Reference,
Particle.keepAlive(23 * 60); // send a ping every 23 minutes
Can the keepAlive time be increase to 2 hours?
Thanks in advance.

You should be able to publish 8 values to ThingSpeak every 20 minutes (using snprintf and a webhook) and stay under 1 MB/ month without the need to Sleep the Electron. There are examples in this forum, but it appears you have a handle on combining the 7 samples into 1 publish. Reducing the number of decimal places will also help.

This thread may help, it’s where I learned.
https://community.particle.io/t/how-to-set-up-a-json-for-multiple-variables-in-a-webhook-integration/33172

I have several Electrons that publish 8 ThingSpeak fields at a minimum of 20 minutes (no sleeping), and any additional event triggered publishes. Those never use 2 MB/month.

The maximum possible keepAlive is 23 minutes - that’s a fixed setting by the cellular service provider. You can go shorter but not longer.

If you want to wake from deep sleep you need to have a rising edge on WKP/A7.
For Stop Mode Sleep you can use the same pin as for your interrupt, you are not limited to WKP/A7 in that mode and yes, the pin will be set implicitly by the System.sleep(pin, ...) command (including pull resistors FALLING->pull-up, RISING->pull-down, CHANGE->no pull-resistor) - so there is no need to set pinMode() for the wake pin.

2 Likes

I now have combined my 7 events down to **one event (“D”) and have formatted the data published with %.1f but I.m getting 2 combined events separated in time by 22 secs., after each wake and fw change. I apparently is going through the loop section twice.
After the System.sleep(SLEEP_MODE_DEEP, 60 * 20, SLEEP_NETWORK_STANDBY); command is sent there seems to be a delay before the cell goes into standby, and the LED turns Off,. Its seems to be long enough to go through my loop and execute another publish command. I tried adding an IF statement right at the start of the Loop section so the second time through the loop it starts a 25 sec delay, delay(25000);. But that seems just push the second “D” event back later in time.
Since I have a RGB LSD 16x2 display attached to the particle Shield I tried changing the Backlight Color at different stops in my code but still I haven’t been able to figure it out.

I copied the code by rickkas7 and set it up for cellular mode and shortened the delay if (millis() - firstAvailable > 30000), to if (millis() - firstAvailable > 500) , thinking this was the reason for the double publish . I’m confused on just exactly is going on in that section. Is it making sure you have a good connection before letting the Particle.publish(“D”, String::format… be executed? Yet even after being executed the radio is staying on long enough for the extra “D” event.

Is it true that once the USB serial connection is removed and the Electron is deployed, you no longer can see the Serial.printlnf(“wifi=%s cloud=%s counter_slp=%d retainedCounter_slp=%d”… info, since the serial Terminal connection has been removed?
Thanks for any ides or suggestions on how to stop that second publish.

Sleep code:

bool cellReady = Cellular.ready(); // Cellular (Electron)
	bool cloudReady = Particle.connected();

	Serial.printlnf("wifi=%s cloud=%s counter=%d retainedCounter=%d", (wifiReady ? "on" : "off"), (cloudReady ? "on" : "off"),
			counter++, retainedCounter++);

	if (cellReady) {
		if (firstAvailable == 0) {
			firstAvailable = millis();
		}
// changed >30000 to >500
		if (millis() - firstAvailable > 500) {
			// After we've been up for 30 seconds, go to sleep. The delay is so the serial output gets written out before
			// sleeping.
			Serial.println("calling System.sleep(SLEEP_MODE_DEEP, 30)");
			delay(2);

			// Changed from  "System.sleep(SLEEP_MODE_DEEP, 30);"
                       System.sleep(SLEEP_MODE_DEEP, 60 * 20, SLEEP_NETWORK_STANDBY);//20 mins
			// The rest of the code here is not reached. SLEEP_MODE_DEEP causes the code execution to stop,
			// and when wake up occurs, it's like a reset where you start again with setup(), all variables are
			// cleared, etc.
			Serial.println("returned from sleep, should not occur");
		}
	}
	else {
		firstAvailable = 0;
	}// End of Sleep code

I figured it out. So I only get One combined event after waking.

What exactly did you figure out?

Was there a trick to only getting one publish when the Electron wakes up?

I added an IF condition just before the Particle.publish line

if (sleep < 1) {
sleep = 1;
lcd.setBacklight(WHITE); // just to get a visual indication of where I was in the loop.
delay(1500);
}
else {
delay(500); // Only one Combined Event “D” before CELL Turns OFF
Particle.publish(“D”, …);
delay(5000);
}

Before it was going through the loop twice.

1 Like

Hello Rftop,
I’ve been combining Particle events using the following command,
Particle.publish(“D”, String::format("%.1f,%.1f,%.0f,%.0f",V1, V2, sensor.readHumidity(), f), PRIVATE);
Would you please post an example of your method, combining fields for publishing to ThingSpeak?

Currently I’ve tried single field per line as shown below:
ThingSpeak.setField (1,EngBatt); //field 1 EngBatt
ThingSpeak.setField (2,HouseBatt); //field 2 HouseBatt
ThingSpeak.setField (3,f); //field 3 Temperaure4
ThingSpeak.setField (4,Humidity); //field 4 Humidity

ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);

Thanks

It appears your latest CODE uses the ThinkSpeak Library, so you wont need a Particle.Publish & Webhook.

The Library will send the data to ThingSpeak “behind the scenes”… you wont see anything on the console event log when using ThingSpeak.writeFields

ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);

I think you are using 2 different concepts (at the same time) to get your data to ThingSpeak.

Here is sample CODE for using a Particle.Publish and a Webhook to send multiple fields at one time:

Click Here
/*

  1.  Create a free account at www.ThingSpeak.com

  2. Create a Webhook manually at  https://console.particle.io/integrations/webhooks/create
    Click [CUSTOM JSON] at the Top Right
    Copy/Paste the following into the JSON window:

                        {
                            "event": "TEST",
                            "url": "https://api.thingspeak.com/update",
                            "requestType": "POST",
                            "form": {
                                "api_key": "{{k}}",
                                "field1": "{{1}}",
                                "field2": "{{2}}",
                                "field3": "{{3}}",
                                "field4": "{{4}}",
                                "field5": "{{5}}",
                                "field6": "{{6}}",
                                "field7": "{{7}}",
                                "field8": "{{8}}",
                                "lat": "{{a}}",
                                "long": "{{o}}",
                                "elevation": "{{e}}",
                                "status": "{{s}}"
                            },
                            "mydevices": true,
                            "noDefaults": true
                        }


    You will change the "event" in the first line of the JSON to whatever event name you wish:
            The Example names the WebHook's event: "TEST",
    So you would change the CODE (for Photon or Electron) below under [Specific Values for each Installation] to :
            const char * eventName = "TEST"
    To match the WebHook event name.

  OR* Follow these instructions :   https://www.hackster.io/15223/thingspeak-particle-photon-using-webhooks-dbd96c

*/



//      [ Specific Values for each Installation ]
//////////////////////////////////////////////////////
const char * eventName = "TEST";                    //  This must match the name of the event you chose for the WebHook in Step #3
int publish_delay =          300000;                //  Multiply # of Seconds * 1000. This is how often to update  ThingSpeak.com
//ThingSpeak Channel Info                           //
const char * myWriteAPIKey = "Xxxxxxxxxxxxxxx";     //  From your ThinkSpeak Account Info (API KEYS tab)
//////////////////////////////////////////////////////

SYSTEM_THREAD(ENABLED);

char msg[256];
unsigned int lastPublish = 0;           // Previous Publish to ThingSpeak

//  These 4 Floats will hold the values to send to ThinkSpeak.com :
float CH1, CH2, CH3, CH4;

void setup() {
}

void loop() {

  //  Do Something to Update CH1 - CH4


   if ( millis() - lastPublish >= publish_delay) {   //  Wont publish more often than publish_delay.
    //  Build the Particle Publish String
    snprintf(msg, sizeof(msg), "{\"1\":\"%.1f\",\"2\":\"%.1f\",\"3\":\"%.1f\",\"4\":\"%.1f\",\"k\":\"%s\"}", CH1, CH2, CH3, CH4, myWriteAPIKey);

    Particle.publish(eventName, msg, PRIVATE, NO_ACK);  // Publish with NO Acknowledgement to save Electron Data
    lastPublish = millis();
  }


}  // End LOOP

Hello Rftop,
Thanks very much fot the example. I am not sure what you mean about using 2 different concepts at the same time. Do you mean using particle.publish & ThingSpeak.setField at the same time? I’m still trying to get my plan usage numbers down.
Before even turning on ThingSpeak publishing On, my DataPlanUage for the “D” event with just 4 items publishing every 20 minutes and using
System.sleep(SLEEP_MODE_DEEP, 1200, SLEEP_NETWORK_STANDBY);
is 0.144Mb/24hours. At that rate after 10 days I’ve exceeded 1Mb.

I saw your post where your sending 8 values using ThingSpeak at 20 minute intervals and not Sleeping. So today I commented out Particle.publish(“D”, String::format("%.1f,%.1f,%.0f,%.0f",V1, V2, sensor.readHumidity(), f), PRIVATE); and then turned on the lines of ThingSpeak code as shown above, and turned Sleep Off. Tomorrow after 24 hours elapse I’ll record my Data Usage. I assume my ThingSpeak code isn’t optimized yet, since I’m using 4 separate ThingSpeak.setField lines
.
Tomorrow I’ll try your example code that uses snprintf and webhook.
Thanks again.

1 Like

@ScruffR,

“Deep sleep won’t return to the instruction following the sleep statement but will restart from scratch”

Whoa, I did not realize that. Looking at the reference it is clear but I missed it. Thank you and @ovro67 for making this explicit (though now that I re-read the reference docs it is there).

Thank you both!

Chip

1 Like