Now that deviceOS@1.5.0 is (almost?) here, I have been working to field my first Boron based devices.
First, I build a new carrier board and shared the results here:
Then, I started posting my main counting application over. The biggest adjustment in this effort has been working on low power / sleep. As you all know, the Boron - unlike the Electron - does not have a Real Time Clock. So, I added one to the carrier board based on @rickkas7's awesome MCP79410RK library and circuit design to control the EN or WKP pin (see carrier board thread).
I started to get overwhelmed by the different ways that the Boron could sleep so, I thought it might be helpful to write a sketch that explored all the different sleep modes and use it to both share what is working and see if anyone can help on the one mode that is not.
The idea is that this sketch runs through five different sleep modes and provides a running tally on successful tests.
Here are the main learnings:
The System.sleep seems to add a second to the sleep time - not a big deal but a bit surprising
The Wake on interrupt RISING and FALLING won't work if you are using a debounced switch. However CHANGE does work. I suspect all would work fine with a digital pin from another device.
I cannot get the ENABLE pin sleep to work with @rickkas7's library and circuit. I am quite sure I am doing something wrong but any help here would be appreciated.
@All, In order to test the power savings, I have created a sketch that uses a coulomb counter connected to a Photon / Argon to monitor the Boron which is sleeping.
Here is a first pass at this code which I will use to determine the current consumption in three different sleep modes (STOP, HIBERNATE, and ENABLE) and in two configurations (Bare Boron and Boron in Carrier).
More to come but wanted to share the code I will be using to test:
@all, Here are my initial results. Please take a look and let me know if my approach makes sense. I have built a fairly flexible engine to allow for iteration. So, please take a look and let me know your thoughts.
Here is the code I am using for the Sleep Test cases. You can set the duration and the sleep mode (see below). The test kicks off 5 seconds later and the coulomb counter is triggered when the D7 light goes off. Then the coulomb counter provides a running average of up to 10 coulombs for the calculation.
Test 3 - Enable Pin Sleep with user button wake
In This mode, we simply hold the Enable Pin low as there is no RTC to wake the device (that comes next with the carrier board tests).
Test 3 - Average Current - In progress - coulombs are coming very slowly. Will update when I have something.
Please let me know if you are interested in other test cases. One thing is clear - not much different between STOP mode and HIBERNATE sleep so not having a RTC like the Electron does not seem to be a big deal here.
All these tests were done with a bare Boron - no extra parts. The lowest power consumption would be with the “Enable” sleep but I am still running that test.
Please take a look at my sketch which has no hardware requirements other than a button to wake from HIBERNATE sleep. If I am missing something, I would appreciate the help.
One question is whether I need to go through the whole Cellular.OFF() bit in the new model.
I just cheat and use Manual Mode for initial testing.
I just updated a Boron LTE to 1.5.0 final.
Measuring the Sleep Current with a µCurrent GOLD, I don't see any changes from the same tests on 1.5.0-rc1.
About 660 µA is the best I get, nothing close to the ~150 µA that was previously mentioned for 1.5.0 final. I must be missing a step.
SYSTEM_MODE(MANUAL);
SYSTEM_THREAD(ENABLED);
inline void softDelay(uint32_t t) {
for (uint32_t ms = millis(); millis() - ms < t; Particle.process()); // safer than a delay()
}
SystemSleepConfiguration config;
void setup() {
// Pick a Sleep Mode Li-Po @ 4.08V , Final Release 1.5.0
// config.mode(SystemSleepMode::STOP).gpio(D0, RISING).duration(30s); // 1.128 mA
// config.mode(SystemSleepMode::HIBERNATE).gpio(D0, RISING).gpio(WKP, RISING); // 0.663 mA
// config.mode(SystemSleepMode::STOP).duration(30s); // 1.127 mA
}
void loop() {
softDelay(15000); // wait 15 seconds before Sleep.
System.sleep(config);
}
Im also only able to get down to 660uA using Sleep2.0. I cant figure out how to get it lower. Im using just a bare boron with no other things attached to it.
@jack4566@RWB@wesner0019 The sleep current is still higher than expected. The modem is not shutting down properly - this is being treated as high priority by the Engineering team.
You can get it down quite a bit but is still requires jumping through a few hoops. I’ve personally seen 160 uA on a Boron, so it is possible.
Manual Mode is required and in some cases you need to explicitly turn off the modem.
That would explain the difference between my readings and @Rftop but still leaves some gap between his readings and the expected results.
In my current code, I am using a sequence to help ensure the cellular modem is shut down. I believe this code was originally provided by @rickkas7
bool disconnectFromParticle() // Ensures we disconnect cleanly from Particle
{
Particle.disconnect();
waitFor(notConnected, 15000); // make sure before turning off the cellular modem
Cellular.off();
delay(2000); // Bummer but only should happen once an hour
return true;
}
I was hoping we would not have to do this anymore but, could it be an interim fix? I will do some testing to see if it helps in my connected sketch.
Yes, sorry this took a while.
I tested this over the weekend, and I am getting a consistent reading of 0.00013A/130uA as shown in the screenshot.
SYSTEM_MODE(MANUAL);
void setup()
{
}
void loop()
{
delay (5000);
powerModemOff(); // See the patch.
SystemSleepConfiguration config;
config.mode(SystemSleepMode::STOP)
.gpio(WKP, RISING)
.duration(600s);
System.sleep(config);
}
bool waitModemPowerOff()
{
// Verify that the modem was powered down by checking the VINT pin up to 10 sec
bool powerGood;
for (unsigned i = 0; i < 100; i++) {
powerGood = digitalRead(UBVINT);
if (!powerGood) {
break;
}
delay(100);
}
return !powerGood;
}
bool powerModemOff() {
// Delay enough time to make sure pppncp thread has handled all events.
delay(20000);
// Important! We need to disable voltage translator here
// otherwise V_INT will never go low
digitalWrite(BUFEN, 1);
// Low pulse 1.5s+ on UBPWR pin
// IMPORTANT: SARA R4-based devices need to be using the latest firmware,
// otherwise shutdown may need to be postponed by at least 30 seconds.
// Affected version: L0.0.00.00.05.06,A.02.00
digitalWrite(UBPWR, 0);
delay(1600);
digitalWrite(UBPWR, 1);
// Wait for it to power off again
bool poweredOff = waitModemPowerOff();
if (!poweredOff) {
Log.error("Modem failed to power off explicitly via shutdown sequence");
}
// Just in case explicitly disable voltage translator once again
digitalWrite(BUFEN, 1);
#if PLATFORM_ID == PLATFORM_BORON
// Do not leak current through antenna switch
pinMode(ANTSW1, INPUT);
#endif // PLATFORM_ID == PLATFORM_BORON
// Just in case disable Serial2 connected to the modem
HAL_USART_End(HAL_USART_SERIAL2);
return poweredOff;
}