mirror of
https://github.com/arduino-libraries/ArduinoLowPower.git
synced 2025-04-22 09:42:54 +03:00
Added nRF52 compatibility
Waking from deepSleep() is comparable to an hard reset; the sketch won't restart from the sleep invocation but the wakeuup source can be retrieved with wakeupReason()
This commit is contained in:
parent
fcbf16f6a3
commit
21d2f7527f
92
examples/PrimoDeepSleep/PrimoDeepSleep.ino
Normal file
92
examples/PrimoDeepSleep/PrimoDeepSleep.ino
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
PrimoDeepSleep.ino
|
||||||
|
|
||||||
|
Written by Chiara Ruggeri (chiara@arduino.org)
|
||||||
|
|
||||||
|
This example for the Arduino Primo board shows how to use
|
||||||
|
low power library to enter in power off mode and save power.
|
||||||
|
This mode ensure the deepest power saving mode. If you need
|
||||||
|
a faster response from the board use standby function instead.
|
||||||
|
|
||||||
|
Please note that once exited from the deepest sleep mode the
|
||||||
|
board will reset (so setup will be run again).
|
||||||
|
|
||||||
|
The functions enableWakeupFrom set the peripheral that will wake up
|
||||||
|
the board. By calling it more than once you can choose more than
|
||||||
|
a wakeup source.
|
||||||
|
The board will be reset when it wakes up from power off.
|
||||||
|
You can use wakeUpCause() function to find out what signals woke up
|
||||||
|
the board if you use more than one wakeUpBy.. function.
|
||||||
|
|
||||||
|
This example code is in the public domain.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ArduinoLowPower.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Pin used to wakeup the board
|
||||||
|
const int digitalPin = 10;
|
||||||
|
|
||||||
|
// Pin used in Compatarot module to wake up the board
|
||||||
|
const int analogPin = A0;
|
||||||
|
|
||||||
|
|
||||||
|
void StmEspPM(bool sleep){
|
||||||
|
// enable USER1_BUTTON to turn STM32 off and on when pressed.
|
||||||
|
// note that when STM32 is off you cannot load any new sketch.
|
||||||
|
pinMode(USER1_BUTTON, STM32_IT);
|
||||||
|
|
||||||
|
// turn ESP8266 off or on
|
||||||
|
digitalWrite(GPIO_ESP_PW, sleep ? LOW: HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
pinMode(LED_BUILTIN, OUTPUT);
|
||||||
|
digitalWrite(LED_BUILTIN, HIGH);
|
||||||
|
delay(500);
|
||||||
|
digitalWrite(LED_BUILTIN, LOW);
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
//look for what peripheral woke up the board
|
||||||
|
//reason is 0 at the first execution
|
||||||
|
wakeup_reason reason=LowPower.wakeupReason();
|
||||||
|
if(reason==GPIO_WAKEUP) //GPIO caused the wake up
|
||||||
|
doMyStuff();
|
||||||
|
else
|
||||||
|
if(reason==NFC_WAKEUP) //NFC caused the wake up
|
||||||
|
doMyStuffWithNFC();
|
||||||
|
else
|
||||||
|
if(reason==ANALOG_COMPARATOR_WAKEUP) //Comparator caused the wake up
|
||||||
|
doOtherStuff();
|
||||||
|
|
||||||
|
Serial.println("Hi all, I return to sleep");
|
||||||
|
|
||||||
|
LowPower.companionLowPowerCallback(StmEspPM);
|
||||||
|
// Send sleep command to ESP and enable USER1_BUTTON to turn STM off
|
||||||
|
LowPower.companionSleep();
|
||||||
|
|
||||||
|
//set digital pin 10 to wake up the board when LOW level is detected
|
||||||
|
LowPower.enableWakeupFrom(GPIO_WAKEUP, digitalPin, LOW);
|
||||||
|
//let the board be woken up by any NFC field
|
||||||
|
LowPower.enableWakeupFrom(NFC_WAKEUP);
|
||||||
|
//wake up the board when the voltage on pin A0 goes below the voltage on pin AREF
|
||||||
|
LowPower.enableWakeupFrom(ANALOG_COMPARATOR_WAKEUP, analogPin, AREF, UP);
|
||||||
|
//go in low power mode. Note that the board will reset once it is woken up
|
||||||
|
LowPower.deepSleep();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void loop() {}
|
||||||
|
|
||||||
|
void doMyStuff(){
|
||||||
|
//insert your code here
|
||||||
|
}
|
||||||
|
|
||||||
|
void doMyStuffWithNFC(){
|
||||||
|
//insert your code here
|
||||||
|
}
|
||||||
|
|
||||||
|
void doOtherStuff(){
|
||||||
|
//insert your code here
|
||||||
|
}
|
10
keywords.txt
10
keywords.txt
@ -17,7 +17,17 @@ idle KEYWORD2
|
|||||||
sleep KEYWORD2
|
sleep KEYWORD2
|
||||||
deepSleep KEYWORD2
|
deepSleep KEYWORD2
|
||||||
attachInterruptWakeup KEYWORD2
|
attachInterruptWakeup KEYWORD2
|
||||||
|
enableWakeupFrom KEYWORD2
|
||||||
|
companionLowPowerCallback KEYWORD2
|
||||||
|
companionSleep KEYWORD2
|
||||||
|
companionWakeup KEYWORD2
|
||||||
|
wakeupReason KEYWORD2
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
# Constants (LITERAL1)
|
# Constants (LITERAL1)
|
||||||
#######################################
|
#######################################
|
||||||
|
|
||||||
|
OTHER_WAKEUP LITERAL1
|
||||||
|
GPIO_WAKEUP LITERAL1
|
||||||
|
NFC_WAKEUP LITERAL1
|
||||||
|
ANALOG_COMPARATOR_WAKEUP LITERAL1
|
@ -2,8 +2,8 @@ name=Arduino Low Power
|
|||||||
version=1.0.0
|
version=1.0.0
|
||||||
author=Arduino
|
author=Arduino
|
||||||
maintainer=Arduino LLC
|
maintainer=Arduino LLC
|
||||||
sentence=Power save primitives features for SAMD 32bit boards
|
sentence=Power save primitives features for SAMD and nRF52 32bit boards
|
||||||
paragraph=With this library you can manage the low power states of newer Arduino boards
|
paragraph=With this library you can manage the low power states of newer Arduino boards
|
||||||
category=Device Control
|
category=Device Control
|
||||||
url=http://arduino.cc/libraries/ArduinoLowPower
|
url=http://arduino.cc/libraries/ArduinoLowPower
|
||||||
architectures=samd
|
architectures=samd,nrf52
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
#include "RTCZero.h"
|
#include "RTCZero.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(ARDUINO_SAMD_TIAN)
|
#if defined(ARDUINO_SAMD_TIAN) || defined(ARDUINO_NRF52_PRIMO)
|
||||||
// add here any board with companion chip which can be woken up
|
// add here any board with companion chip which can be woken up
|
||||||
#define BOARD_HAS_COMPANION_CHIP
|
#define BOARD_HAS_COMPANION_CHIP
|
||||||
#endif
|
#endif
|
||||||
@ -21,6 +21,14 @@
|
|||||||
//typedef void (*voidFuncPtr)( void ) ;
|
//typedef void (*voidFuncPtr)( void ) ;
|
||||||
typedef void (*onOffFuncPtr)( bool ) ;
|
typedef void (*onOffFuncPtr)( bool ) ;
|
||||||
|
|
||||||
|
typedef enum{
|
||||||
|
OTHER_WAKEUP = 0,
|
||||||
|
GPIO_WAKEUP = 1,
|
||||||
|
NFC_WAKEUP = 2,
|
||||||
|
ANALOG_COMPARATOR_WAKEUP = 3
|
||||||
|
} wakeup_reason;
|
||||||
|
|
||||||
|
|
||||||
class ArduinoLowPowerClass {
|
class ArduinoLowPowerClass {
|
||||||
public:
|
public:
|
||||||
void idle(void);
|
void idle(void);
|
||||||
@ -55,9 +63,16 @@ class ArduinoLowPowerClass {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef ARDUINO_ARCH_NRF52
|
||||||
|
void enableWakeupFrom(wakeup_reason peripheral, uint32_t pin = 0xFF, uint32_t event = 0xFF, uint32_t option = 0xFF);
|
||||||
|
wakeup_reason wakeupReason();
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setAlarmIn(uint32_t millis);
|
void setAlarmIn(uint32_t millis);
|
||||||
|
#ifdef ARDUINO_ARCH_SAMD
|
||||||
RTCZero rtc;
|
RTCZero rtc;
|
||||||
|
#endif
|
||||||
#ifdef BOARD_HAS_COMPANION_CHIP
|
#ifdef BOARD_HAS_COMPANION_CHIP
|
||||||
void (*companionSleepCB)(bool);
|
void (*companionSleepCB)(bool);
|
||||||
#endif
|
#endif
|
||||||
|
178
src/nrf52/ArduinoLowPower.cpp
Normal file
178
src/nrf52/ArduinoLowPower.cpp
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
/*
|
||||||
|
ArduinoLowPower class for nRF52.
|
||||||
|
|
||||||
|
Written by Chiara Ruggeri (chiara@arduino.org)
|
||||||
|
|
||||||
|
Copyright (c) 2017 Arduino AG. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
See the GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(ARDUINO_ARCH_NRF52)
|
||||||
|
|
||||||
|
#include "ArduinoLowPower.h"
|
||||||
|
#include "WInterrupts.h"
|
||||||
|
#include "nrf_rtc.h"
|
||||||
|
|
||||||
|
volatile bool event = false;
|
||||||
|
void (*functionPointer)(void);
|
||||||
|
nrf_lpcomp_input_t aPin[]={NRF_LPCOMP_INPUT_1, NRF_LPCOMP_INPUT_2, NRF_LPCOMP_INPUT_4, NRF_LPCOMP_INPUT_5, NRF_LPCOMP_INPUT_6, NRF_LPCOMP_INPUT_7};
|
||||||
|
|
||||||
|
void wakeUpGpio(){
|
||||||
|
event = true;
|
||||||
|
if(functionPointer)
|
||||||
|
functionPointer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArduinoLowPowerClass::idle() {
|
||||||
|
// nRF52 has just two low power modes. Call sleep if idle is called.
|
||||||
|
sleep();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArduinoLowPowerClass::idle(uint32_t millis) {
|
||||||
|
setAlarmIn(millis);
|
||||||
|
idle();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArduinoLowPowerClass::sleep() {
|
||||||
|
sd_power_mode_set(NRF_POWER_MODE_LOWPWR);
|
||||||
|
event=false;
|
||||||
|
while(!event){
|
||||||
|
sd_app_evt_wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArduinoLowPowerClass::sleep(uint32_t millis) {
|
||||||
|
setAlarmIn(millis);
|
||||||
|
sleep();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArduinoLowPowerClass::deepSleep() {
|
||||||
|
//Enter in systemOff mode only when no EasyDMA transfer is active
|
||||||
|
//this is achieved by disabling all peripheral that use it
|
||||||
|
NRF_UARTE0->ENABLE = UARTE_ENABLE_ENABLE_Disabled; //disable UART
|
||||||
|
NRF_SAADC ->ENABLE = (SAADC_ENABLE_ENABLE_Disabled << SAADC_ENABLE_ENABLE_Pos); //disable ADC
|
||||||
|
NRF_PWM0 ->ENABLE = (PWM_ENABLE_ENABLE_Disabled << PWM_ENABLE_ENABLE_Pos); //disable all pwm instance
|
||||||
|
NRF_PWM1 ->ENABLE = (PWM_ENABLE_ENABLE_Disabled << PWM_ENABLE_ENABLE_Pos);
|
||||||
|
NRF_PWM2 ->ENABLE = (PWM_ENABLE_ENABLE_Disabled << PWM_ENABLE_ENABLE_Pos);
|
||||||
|
NRF_TWIM1 ->ENABLE = (TWIM_ENABLE_ENABLE_Disabled << TWIM_ENABLE_ENABLE_Pos); //disable TWI Master
|
||||||
|
NRF_TWIS1 ->ENABLE = (TWIS_ENABLE_ENABLE_Disabled << TWIS_ENABLE_ENABLE_Pos); //disable TWI Slave
|
||||||
|
|
||||||
|
//Enter in System OFF mode
|
||||||
|
sd_power_system_off();
|
||||||
|
|
||||||
|
/*Only for debugging purpose, will not be reached without connected debugger*/
|
||||||
|
while(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArduinoLowPowerClass::setAlarmIn(uint32_t millis) {
|
||||||
|
nrf_rtc_prescaler_set(NRF_RTC1, 32);
|
||||||
|
//enable interrupt
|
||||||
|
NVIC_SetPriority(RTC1_IRQn, 2); //high priority
|
||||||
|
NVIC_ClearPendingIRQ(RTC1_IRQn);
|
||||||
|
NVIC_EnableIRQ(RTC1_IRQn);
|
||||||
|
nrf_rtc_event_clear(NRF_RTC1, NRF_RTC_EVENT_COMPARE_0);
|
||||||
|
nrf_rtc_int_enable(NRF_RTC1, NRF_RTC_INT_COMPARE0_MASK);
|
||||||
|
//Tick every 1 ms
|
||||||
|
nrf_rtc_cc_set(NRF_RTC1, 0, millis);
|
||||||
|
|
||||||
|
//start RTC
|
||||||
|
nrf_rtc_task_trigger(NRF_RTC1, NRF_RTC_TASK_START);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArduinoLowPowerClass::attachInterruptWakeup(uint32_t pin, voidFuncPtr callback, uint32_t mode) {
|
||||||
|
functionPointer = callback;
|
||||||
|
|
||||||
|
if(pin == RTC_ALARM_WAKEUP)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pinMode(pin, INPUT_PULLUP);
|
||||||
|
attachInterrupt(pin, wakeUpGpio, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArduinoLowPowerClass::enableWakeupFrom(wakeup_reason peripheral, uint32_t pin, uint32_t event, uint32_t option){
|
||||||
|
if(peripheral == NFC_WAKEUP){
|
||||||
|
NRF_NFCT->TASKS_SENSE=1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(peripheral == ANALOG_COMPARATOR_WAKEUP){
|
||||||
|
detect_mode mode;
|
||||||
|
if(option == DOWN)
|
||||||
|
mode = DOWN;
|
||||||
|
else if(option == UP)
|
||||||
|
mode = UP;
|
||||||
|
else
|
||||||
|
mode = CROSS;
|
||||||
|
nrf_lpcomp_config_t config={(nrf_lpcomp_ref_t)event, (nrf_lpcomp_detect_t)mode};
|
||||||
|
nrf_lpcomp_configure(&config);
|
||||||
|
if(pin<14 && pin>19)
|
||||||
|
return; //no analog pin is choosen
|
||||||
|
nrf_lpcomp_input_select(aPin[pin-14]);
|
||||||
|
nrf_lpcomp_enable();
|
||||||
|
nrf_lpcomp_task_trigger(NRF_LPCOMP_TASK_START);
|
||||||
|
while(!nrf_lpcomp_event_check(NRF_LPCOMP_EVENT_READY));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(peripheral == GPIO_WAKEUP){
|
||||||
|
if(pin > 20)// allow wake up only from digital and analog pins
|
||||||
|
return;
|
||||||
|
if(event==LOW)
|
||||||
|
nrf_gpio_cfg_sense_input(g_APinDescription[pin].ulPin, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
|
||||||
|
else
|
||||||
|
nrf_gpio_cfg_sense_input(g_APinDescription[pin].ulPin, NRF_GPIO_PIN_PULLDOWN, NRF_GPIO_PIN_SENSE_HIGH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wakeup_reason ArduinoLowPowerClass::wakeupReason(){
|
||||||
|
uint32_t guilty;
|
||||||
|
sd_power_reset_reason_get(&guilty);
|
||||||
|
if(guilty & 0x10000){ // GPIO
|
||||||
|
//RESETREAS is a cumulative register. We need to clear it by writing 1 in the relative field
|
||||||
|
sd_power_reset_reason_clr(1 << 16);
|
||||||
|
return GPIO_WAKEUP;
|
||||||
|
}
|
||||||
|
if(guilty & 0x80000){ //NFC
|
||||||
|
sd_power_reset_reason_clr(1 << 19);
|
||||||
|
return NFC_WAKEUP;
|
||||||
|
}
|
||||||
|
if(guilty & 0x20000){ //COMP
|
||||||
|
sd_power_reset_reason_clr(1 << 17);
|
||||||
|
return ANALOG_COMPARATOR_WAKEUP;
|
||||||
|
}
|
||||||
|
return OTHER_WAKEUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ArduinoLowPowerClass LowPower;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void RTC1_IRQHandler(void)
|
||||||
|
{
|
||||||
|
event=true;
|
||||||
|
nrf_rtc_event_clear(NRF_RTC1, NRF_RTC_EVENT_COMPARE_0);
|
||||||
|
nrf_rtc_task_trigger(NRF_RTC1, NRF_RTC_TASK_CLEAR);
|
||||||
|
nrf_rtc_task_trigger(NRF_RTC1, NRF_RTC_TASK_STOP);
|
||||||
|
if(functionPointer)
|
||||||
|
functionPointer();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // ARDUINO_ARCH_NRF52
|
@ -1,3 +1,5 @@
|
|||||||
|
#if defined(ARDUINO_ARCH_SAMD)
|
||||||
|
|
||||||
#include "ArduinoLowPower.h"
|
#include "ArduinoLowPower.h"
|
||||||
#include "WInterrupts.h"
|
#include "WInterrupts.h"
|
||||||
|
|
||||||
@ -88,3 +90,5 @@ void ArduinoLowPowerClass::attachInterruptWakeup(uint32_t pin, voidFuncPtr callb
|
|||||||
}
|
}
|
||||||
|
|
||||||
ArduinoLowPowerClass LowPower;
|
ArduinoLowPowerClass LowPower;
|
||||||
|
|
||||||
|
#endif // ARDUINO_ARCH_SAMD
|
Loading…
x
Reference in New Issue
Block a user