paulvha:
some time ago I wrote the attached deepsleep sketch with BLE. Works on V1.x.x and V2.x.x
I tried adding the BLE code to the sleep mode example I got working with GPIO earlier, and I think I’ve found the problem, sort of…
below is the code I got working for GPIO sleep and wakeup. The I’m running into is that, and I need to triple check that the BLE is what’s causing this, when I press the button the first time, it starts to loop through the interrupt, seemingly as soon as the software debounce has run its course. What’s more, the built-in LED doesn’t illuminate after it wakes up the first time.
#include "RTC.h"
#include <ArduinoBLE.h>
#define BUTTON_CTRL 14
#define DEBOUNCETIME 1000 // number of milli seconds needed between pushes
void BLE_Setup();
void setSleepMode();
void goToSleep();
void peripheralSleep();
const char BLE_PERIPHERAL_NAME[] = "Peripheral Sleep Test BLE";
BLEService SleepService("19B10010-E8F2-537E-4F6C-D104768A1214");
BLECharacteristic rxCharacteristic("19B10011-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify, 8);
bool sleep_mode_set = false;
unsigned long debounce; // Stores the last millis()
unsigned long count = 0;
unsigned int loop_count = 0;
void BLE_Setup()
{
Serial.println("Starting BLE");
if(!BLE.begin())
{
delay(30);
}
BLE.setLocalName(BLE_PERIPHERAL_NAME);
BLE.setAdvertisedService(SleepService);
SleepService.addCharacteristic(rxCharacteristic);
BLE.addService(SleepService);
BLE.advertise();
}
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
pinMode(BUTTON_CTRL, INPUT_PULLUP);
Serial.begin(115200);
Serial.println("SparkFun RTC Low-power Alarm Example");
BLE_Setup();
// // Easily set RTC using the system __DATE__ and __TIME__ macros from compiler
//RTC.setToCompilerTime();
// Manually set RTC date and time
rtc.setTime(0, 50, 59, 12, 3, 6, 20); // 12:59:50.000, June 3rd, 2020 (hund, ss, mm, hh, dd, mm, yy)
// Set the RTC's alarm
//rtc.setAlarm(0, 0, 0, 13, 3, 6); // 13:00:00.000, June 3rd (hund, ss, mm, hh, dd, mm). Note: No year alarm register
// Set the RTC alarm mode
/*
0: Alarm interrupt disabled
1: Alarm match every year (hundredths, seconds, minutes, hour, day, month)
2: Alarm match every month (hundredths, seconds, minutes, hours, day)
3: Alarm match every week (hundredths, seconds, minutes, hours, weekday)
4: Alarm match every day (hundredths, seconds, minute, hours)
5: Alarm match every hour (hundredths, seconds, minutes)
6: Alarm match every minute (hundredths, seconds)
7: Alarm match every second (hundredths)
*/
//rtc.setAlarmMode(6); // Set the RTC alarm to match on minutes rollover
//rtc.attachInterrupt(); // Attach RTC alarm interrupt
debounce = millis();
attachInterrupt(digitalPinToInterrupt(BUTTON_CTRL), setSleepMode, FALLING);
}
void loop()
{
BLEDevice central = BLE.central();
// Print date and time of RTC alarm trigger
if(central)
{
while(central.connected())
{
if(loop_count >= 200000)
{
Serial.print("count: "); Serial.println(count);//printDateTime();
count++;
loop_count = 0;
rxCharacteristic.writeValue(count);
}
else
{
loop_count++;
}
// Enter deep sleep and await RTC alarm interrupt
}
}
if(sleep_mode_set == true)
{
peripheralSleep();
}
}
// Print the RTC's current date and time
void printDateTime()
{
rtc.getTime();
Serial.printf("20%02d-%02d-%02d %02d:%02d:%02d.%03d\n",
rtc.year, rtc.month, rtc.dayOfMonth,
rtc.hour, rtc.minute, rtc.seconds, rtc.hundredths);
Serial.println();
}
void setSleepMode()
{
if(sleep_mode_set == false)
{
digitalWrite(LED_BUILTIN, HIGH);
if (millis() - debounce < DEBOUNCETIME )
{
debounce = millis();
return;
}
//detachInterrupt(digitalPinToInterrupt(BUTTON_CTRL));
//attachInterrupt(digitalPinToInterrupt(BUTTON_CTRL), wakeUp, FALLING);
sleep_mode_set = true;
return;
}
else
{
wakeUp();
sleep_mode_set = false;
}
}
void peripheralSleep()
{
BLE.stopAdvertise();
//Wire.end();
BLE.end();
goToSleep();
}
// Power down gracefully
void goToSleep()
{
// Disable UART
Serial.println("Going to sleep...");
delay(100);
Serial.end();
// Disable ADC
powerControlADC(false);
// Force the peripherals off
am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_IOM0);
am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_IOM1);
am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_IOM2);
am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_IOM3);
am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_IOM4);
am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_IOM5);
am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_ADC);
am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_UART0);
am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_UART1);
// Disable all pads (except UART TX/RX)
for (int x = 0 ; x < 50 ; x++)
{
if(x != LED_BUILTIN && x != BUTTON_CTRL)
{
am_hal_gpio_pinconfig(x, g_AM_HAL_GPIO_DISABLE);
}
}
//Power down CACHE, flashand SRAM
am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_ALL); // Turn off CACHE and flash
am_hal_pwrctrl_memory_deepsleep_retain(AM_HAL_PWRCTRL_MEM_SRAM_384K); // Retain all SRAM (0.6 uA)
// Keep the 32kHz clock running for RTC
am_hal_stimer_config(AM_HAL_STIMER_CFG_CLEAR | AM_HAL_STIMER_CFG_FREEZE);
am_hal_stimer_config(AM_HAL_STIMER_XTAL_32KHZ);
am_hal_interrupt_master_enable();
am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP); // Sleep forever
// And we're back!
wakeUp();
}
// Power up gracefully
void wakeUp()
{
// Go back to using the main clock
am_hal_stimer_config(AM_HAL_STIMER_CFG_CLEAR | AM_HAL_STIMER_CFG_FREEZE);
am_hal_stimer_config(AM_HAL_STIMER_HFRC_3MHZ);
// Power up SRAM, turn on entire Flash
am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_MAX);
// Go back to using the main clock
am_hal_stimer_config(AM_HAL_STIMER_CFG_CLEAR | AM_HAL_STIMER_CFG_FREEZE);
am_hal_stimer_config(AM_HAL_STIMER_HFRC_3MHZ);
// Renable UART0 pins
am_hal_gpio_pinconfig(48, g_AM_BSP_GPIO_COM_UART_TX);
am_hal_gpio_pinconfig(49, g_AM_BSP_GPIO_COM_UART_RX);
// Renable power to UART0
am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_PERIPH_UART0);
am_hal_ctimer_start(7, AM_HAL_CTIMER_TIMERB);
am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_PERIPH_IOM0);
am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_PERIPH_IOM1);
am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_PERIPH_IOM2);
am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_PERIPH_IOM3);
am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_PERIPH_IOM4);
am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_PERIPH_IOM5);
// Enable ADC
powerControlADC(true);
initializeADC();
// Enable Serial
Serial.begin(115200);
digitalWrite(LED_BUILTIN, LOW);
debounce = millis();
delay(100);
Serial.println("Waking up! Hello world!");
BLE_Setup();
}
This is the output, though I should also add that the “Waking up! Hello world!” line has a backwards question mark in front of it.
SparkFun RTC Low-power Alarm Example
Starting BLE
Going to sleep...
Waking up! Hello world!
Starting BLE
Going to sleep...
Waking up! Hello world!
Starting BLE
Going to sleep...
Waking up! Hello world!
Starting BLE
Going to sleep...
Waking up! Hello world!
Starting BLE
Going to sleep...
I’m only guessing, but I think the interrupt flag isn’t being cleared properly. I’m still researching and testing though, so if you have any suggestions or ideas, my ears are wide open