Questions about System.sleep()


#1

Eagerly awaiting my Bluz and gateway shield. Planning on converting a project I currently have running on a Particle Core to Bluz. While going through the docs I saw the System.sleep() call here http://docs.bluz.io/reference/system/. My question is does anything wake it up from sleep or is there something specific that needs to be done? It says in the doc “The device can be ‘awakened’ by any interrupt, including Bluetooth LE data becoming available.” Does that mean if I have a regular interrupt set and call System.sleep() that Bluz will wake up for it? What if I have multiple interrupts? What has to be done in the Particle cloud to wake it up? Does even something as simple as checking a variable wake it up?


#2

Great Question!

So the System.sleep(SLEEP_MODE_CPU) command will put the CPU to sleep until any interrupt happens, including any data showing up from BLE. So yes, if you set an interrupt, it will immediately wake up when that triggers. And any data polling over the BLE connection (including polling variables or calling functions) will wake it up as well.

It is really just an optimized state where the high frequency clock is turned off and the CPU is asleep. The BLE connection will still be active, and so any data sent will wake it up.


#3

That is exactly what I wanted to hear. Than you.


#4

I’m trying to use SLEEP_MODE_CPU such that the system will sleep (halt the CPU) until woken up again via Particle.function() call, except the gateway shield is constantly trying to keep the bluzDK awake. Is there another way to go about this?

Currently just modifying Tinker like this:

uint32_t startTime;

void setup()
{
	//Register all the Tinker functions
	Particle.function("digitalread", tinkerDigitalRead);
	Particle.function("digitalwrite", tinkerDigitalWrite);
	Particle.function("analogread", tinkerAnalogRead);
	Particle.function("analogwrite", tinkerAnalogWrite);
	
	startTime = millis();
}

/* This function loops forever --------------------------------------------*/
void loop()
{
	if (millis()-startTime > 10000UL) {
	    pinMode(D7, OUTPUT); // flash 3 times when we sleep
	    digitalWrite(D7,LOW);
    	    delay(100);
	    for (int x=0; x<3; x++) {
	        digitalWrite(D7,HIGH);
    	        delay(100);
    	        digitalWrite(D7,LOW);
    	        delay(100);
	    }
	    System.sleep(SLEEP_MODE_CPU); // halt system CPU here
	    startTime = millis(); // only stay awake for 10 seconds
	}
}

#5

All you want is the system to stay asleep until woken up by a Particle function call? That is already built in, it is how it will operate normally. When you say the gateway is constantly trying to keep bluz awake, what do you mean by that?

If the main loop has sleep mode CPU set, then the main clock will stay asleep. The only time it would wake up is if BLE data is sent down (a Particle function is called, variable polled, etc), if a user interrupt is set (which you don’t have here) or every 100 mSec by a system firmware timer. That last part is where we take care of system things like setting the RGB lLED, and checking with the cloud. We do send pings to the cloud every 15 second like a Photon would, this is something I am contemplating turning off completely in a more power efficient mode in the future, but haven’t done so yet. Either way, the 100mSec system timer performs minimal amount of code, but it will execute the user loop. So even if you set system_mode sleep, your loop will run every 100mSec

So if you replace your loop code with just a call to system_sleep, it should do what you need


#6

When I call System.sleep(SLEEP_MODE_CPU); I’m assuming the RGB LED should be off and the loop() should not be running. But in my code above it keeps the RGB blinking CYAN and I keep seeing 3 white D7 flashes every 10 seconds. Indicating to me that the loop() is constantly running.

If I replace all of that with just a call to System.sleep(SLEEP_MODE_CPU); in loop() with the Tinker app, the RGB LED stays blinking CYAN and I can toggle D7 immediately at any time.

Because of this, I’m assuming the gateway is waking the unit back up immediately after it sleeps. Do you think that’s what is happening?

Side note: while I OTA’d new firmware, my user loop() was running (the code above) as I got the new code (with just the sleep call in loop). Typically an OTA process would put 100% focus on receiving firmware in case the user app goes into some long loops. Not sure if that is by design on Bluz or if that’s a bug, but it did end up receiving my whole app and reset with the new app running.


#7

Yeah, I was thinking of having a new sleep mode to do what you describe, where the RGB LED is off and the timer to trigger the LED and system calls is turned off. This would mean the user loop wouldn’t run either. This would also mean that we won’t ping the Particle sever either, but that should be ok. David set us up with a way to keep the status as being online without needing to ping the server.

The current CPU sleep mode has a 100mSec timer. When that timer triggers, we run the use loop, check with the system firmware and ping the cloud if we need to, and then handle the RGB LED changes if needed. Then we sleep for 100mSec more.

There are a few options for sleep mode and running the user loop. I chose one to start but am certainly open to changing it. I like the idea of having several sleep modes, one with the current functionality and another to turn off the timers and save as much power as possible (which would stop the loop() and stop the RGB LED. Both would keep the cloud connection meaning both would wake up on any data from the Particle side.


#8

I see now, so the loop() is running every 100ms to process protocol messages and update the RGB.

Ideally I’d like the lowest current possible for coin cell operation. With the current wake up and update RGB every 100ms, I’m measuring about 200uA with 3V input. This jumps up to 270uA when the LED blinks. I’m not sure how much lower it would go with LED off and loop() completely halted, but currently it seems like a coin cell with 150mAh rating would last for about a month. A pair of AA’s should last 300 days or so. Sound about right?


Minimising power usage
#9

Yes, by providing this type of sleep mode, we can certainly save power. The bigger factor, however, is the connection interval. This is the time in between frequency hops in BLE, so essentially the time between the radio events. This value is set by the gateway, and it is currently set very small (20mSec or so). It can be set up to 4 seconds long. The bigger this interval, the more the power savings, but the lower the throughput. Also the transmit power can be set lower, which will save power but lower the range. I plan to open up all of these settings soon through new releases, so we will get better and better on power savings with some tradeoffs.

A normal CR2032 coin cell has about 240mAh capacity. Call it 200mAh in some cheaper batteries. Rough math at 200uA draw means you should get about 30-40 days currently. By opening up some of these other settings, you can tune it to get a lot more.

Also, you can turn off the LED now through the normal LED API, so you can save some power there.


#10

@eric
I would like to dim the RGB led while using SLEEP_MODE_CPU. The boilerplate code settings for this in the docs http://docs.bluz.io/reference/rgb/ apparently aren’t retained once sleep mode commences in loop, if I place the code in setup(). If placed in loop(), it does make the RGB dim but causes the RGB to flicker seemingly dependent on the delay used, which makes sense, but then I guess I’m keeping the bluz awake longer, thus defeating the power saving aspects of sleep and also blocking code execution. How do I get around this? I’m using 1.1.47.
Also, fiddling around with this earlier, I seem to have corrupted a bluzdk such that part of it’s device_id was overwritten with ffff like so:
original b1e2456c06d5361221XXXXXX but android gateway now shows ble2ffff06d5361221XXXXXX {I’m just obscuring last 6 digits}
I have found no way of recovering that bluzdk (UART reprogramming system-part1 and user part, new keys, unclaiming it with particle cli). I’m not sure what I did to cause this; it happened when I was flashing from WEB IDE


#11

Can you post the code for the RGB issue? Sleep mode should have no effect on turning the LED off.

For the other device, is it able to connect to the cloud still?


#12

@eric
Here’s the code: The commented out sections are the various options I tried:

#include "application.h"
volatile int intrflagON = 0;
volatile int intrflagOFF = 0;
unsigned long lastTime = 0;
unsigned long lastTime2 = 0;

void callbackON(){
	intrflagON = 1;
}

void callbackOFF(){
	intrflagOFF = 1;
}

void setup()
{
	pinMode(D2, INPUT_PULLUP);
	pinMode(D3, INPUT_PULLUP);
	attachInterrupt(D2, callbackON, FALLING);
	attachInterrupt(D3, callbackOFF, FALLING);

//RGB.control(true);
//delay(1000);
//RGB.brightness(64);
//delay(1000);
//lastTime2 = millis();
//while (millis()-lastTime2 < 500) {Particle.process();}
//RGB.control(false);

}//setup

void loop(){
/*
RGB.control(true);
delay(1000);
//lastTime2 = millis();
//while (millis()-lastTime2 < 500) {Particle.process();}
RGB.brightness(32);
delay(1000);
//lastTime2 = millis();
//while (millis()-lastTime2 < 500) {Particle.process();}
RGB.control(false);
*/
System.sleep(SLEEP_MODE_CPU);
if (Particle.connected()) {
unsigned long now = millis();
if ((now - lastTime) >= 200) { //simple debouncer??
	lastTime = now;
if (intrflagON == 1)  {
    intrflagON  = 0; 
    Particle.publish("bedroomONOFF","1",60, PRIVATE);
}

if (intrflagOFF == 1) {
    intrflagOFF = 0; 
    Particle.publish("bedroomONOFF","0",60, PRIVATE);
}
}
}

}//loop

as for the second question, no usually on power up it blinks green at about 2-3 HZ for about 20 -50 seconds, replaced by blinking reddish-magenta at 2-3 HZ forever… Occasionally, on power up it blinks blue at 2-3 HZ


#13

One major problem is that bluz doesn’t support the brightness command. Bluz can only turn the RGB on/off as we don’t have PWM pins hooked to it like the Photon does, so it isn’t possible to change the brightness level. The docs do show an example app with that function, so I will get that cleaned up. The only thing you can do is control it and turn it off if you want to save battery.

As for the other device, I will send you a PM. It sounds like something may have been damaged with that bord and we may need to replace it for you.