Skip to content

Add examples demoing low power config #77

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions libraries/Examples/examples/Advanced/LowPower/LowPower.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
Artemis Low Power: How low can we go?
By: Nathan Seidle
SparkFun Electronics
Date: October 17th, 2019
License: This code is public domain. Based on deepsleep.c from Ambiq SDK v2.2.0.
A big thanks to robin_hodgson for pointing out the HFRC shutdown requirement.

SparkFun labored with love to create this code. Feel like supporting open source hardware?
Buy a board from SparkFun! https://www.sparkfun.com/products/15376

How close can we get to 2.7uA in deep sleep?
This example shows how decrease the Artemis current consumption to less than ~2.5uA in deep sleep.

Note that Artemis modules with revision A1 silicon will use ~30uA. Please see the
Ambiq errata for more information: https://www.ambiqmicro.com/static/mcu/files/Apollo3_Blue_Errata_List_v1_0_external_release.pdf

To monitor the current to the Edge cut the MEAS jumper, solder in headers, and attach
a DMM via IC hooks (https://www.sparkfun.com/products/506).

The USB to serial bridge draws some current:
Serial Basic C - ~1.2uA (https://www.sparkfun.com/products/15096)
FTDI Basic - ~5.5uA (https://www.sparkfun.com/products/9873)

The various components on the Edge2 can be powered on/off as well
PDM microphones (2) - ~50.9uA
Accelerometer (POR mode) - ~79.7uA
Camera regulator enabled (no camera) - ~96.8uA
*/

void setup()
{
Serial.begin(115200);
Serial.println("Low power sleep example");

#if defined(ARDUINO_SFE_EDGE2)
pinMode(ACCEL_VDD, OUTPUT);
digitalWrite(ACCEL_VDD, LOW);

pinMode(MIC_VDD, OUTPUT);
digitalWrite(MIC_VDD, LOW);

pinMode(CAMERA_VDD, OUTPUT);
digitalWrite(CAMERA_VDD, LOW);
#endif

//Turn off ADC
power_adc_disable();

// Initialize for low power in the power control block
am_hal_pwrctrl_low_power_init();

// Stop the XTAL.
am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_XTAL_STOP, 0);

// Disable the RTC.
am_hal_rtc_osc_disable();

// Disabling the debugger GPIOs saves about 1.2 uA total:
am_hal_gpio_pinconfig(20 /* SWDCLK */, g_AM_HAL_GPIO_DISABLE);
am_hal_gpio_pinconfig(21 /* SWDIO */, g_AM_HAL_GPIO_DISABLE);

// These two GPIOs are critical: the TX/RX connections between the Artemis module and the CH340S on the Blackboard
// are prone to backfeeding each other. To stop this from happening, we must reconfigure those pins as GPIOs
// and then disable them completely:
am_hal_gpio_pinconfig(48 /* TXO-0 */, g_AM_HAL_GPIO_DISABLE);
am_hal_gpio_pinconfig(49 /* RXI-0 */, g_AM_HAL_GPIO_DISABLE);

// The default Arduino environment runs the System Timer (STIMER) off the 48 MHZ HFRC clock source.
// The HFRC appears to take over 60 uA when it is running, so this is a big source of extra
// current consumption in deep sleep.
// For systems that might want to use the STIMER to generate a periodic wakeup, it needs to be left running.
// However, it does not have to run at 48 MHz. If we reconfigure STIMER (system timer) to use the 32768 Hz
// XTAL clock source instead the measured deepsleep power drops by about 64 uA.
am_hal_stimer_config(AM_HAL_STIMER_CFG_CLEAR | AM_HAL_STIMER_CFG_FREEZE);

// This option selects 32768 Hz via crystal osc. This appears to cost about 0.1 uA versus selecting "no clock"
am_hal_stimer_config(AM_HAL_STIMER_XTAL_32KHZ);

// This option would be available to systems that don't care about passing time, but might be set
// to wake up on a GPIO transition interrupt.
// am_hal_stimer_config(AM_HAL_STIMER_NO_CLK);

// Turn OFF Flash1
if (am_hal_pwrctrl_memory_enable(AM_HAL_PWRCTRL_MEM_FLASH_512K))
{
while (1)
;
}

// Power down SRAM
PWRCTRL->MEMPWDINSLEEP_b.SRAMPWDSLP = PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_ALLBUTLOWER32K;

Serial.println("Going to sleep...");
delay(100); //Wait for print to complete

Serial.end(); //Disable Serial

am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP);

//We should never get here.
}

void loop()
{
//Do nothing
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*
Artemis Low Power: How low can we go?
By: Nathan Seidle
SparkFun Electronics
Date: October 17th, 2019
License: This code is public domain. Based on deepsleep_wake.c from Ambiq SDK v2.2.0.
A big thanks to robin_hodgson for pointing out the HFRC shutdown requirement and
turning off the SWD pins.

SparkFun labored with love to create this code. Feel like supporting open source hardware?
Buy a board from SparkFun! https://www.sparkfun.com/products/15376

How close can we get to 2.7uA in deep sleep?
This example shows how decrease the Artemis current consumption to ~2.4uA in deep sleep
with a wake up every 5 seconds to blink the LED. The RTC is used to trigger an interrupt
every second.

Note that Artemis modules with revision A1 silicon will use ~30uA. Please see the
Ambiq errata for more information: https://www.ambiqmicro.com/static/mcu/files/Apollo3_Blue_Errata_List_v1_0_external_release.pdf

To monitor the current to the Edge cut the MEAS jumper, solder in headers, and attach
a DMM via IC hooks (https://www.sparkfun.com/products/506).

The USB to serial bridge draws some current:
Serial Basic C - ~1.2uA (https://www.sparkfun.com/products/15096)
FTDI Basic - ~5.5uA (https://www.sparkfun.com/products/9873)

*/

static uint32_t g_RTCseconds = 0;

void setup()
{
Serial.begin(115200);
Serial.println("Low power sleep example");

pinMode(LED_BUILTIN, OUTPUT);

//Turn off ADC
power_adc_disable();

// Set the clock frequency.
am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0);

// Set the default cache configuration
am_hal_cachectrl_config(&am_hal_cachectrl_defaults);
am_hal_cachectrl_enable();

// Initialize for low power in the power control block
am_hal_pwrctrl_low_power_init();

// Disabling the debugger GPIOs saves about 1.2 uA total:
am_hal_gpio_pinconfig(20 /* SWDCLK */, g_AM_HAL_GPIO_DISABLE);
am_hal_gpio_pinconfig(21 /* SWDIO */, g_AM_HAL_GPIO_DISABLE);

// These two GPIOs are critical: the TX/RX connections between the Artemis module and the CH340S on the Blackboard
// are prone to backfeeding each other. To stop this from happening, we must reconfigure those pins as GPIOs
// and then disable them completely:
am_hal_gpio_pinconfig(48 /* TXO-0 */, g_AM_HAL_GPIO_DISABLE);
am_hal_gpio_pinconfig(49 /* RXI-0 */, g_AM_HAL_GPIO_DISABLE);

// The default Arduino environment runs the System Timer (STIMER) off the 48 MHZ HFRC clock source.
// The HFRC appears to take over 60 uA when it is running, so this is a big source of extra
// current consumption in deep sleep.
// For systems that might want to use the STIMER to generate a periodic wakeup, it needs to be left running.
// However, it does not have to run at 48 MHz. If we reconfigure STIMER (system timer) to use the 32768 Hz
// XTAL clock source instead the measured deepsleep power drops by about 64 uA.
am_hal_stimer_config(AM_HAL_STIMER_CFG_CLEAR | AM_HAL_STIMER_CFG_FREEZE);

// This option selects 32768 Hz via crystal osc. This appears to cost about 0.1 uA versus selecting "no clock"
am_hal_stimer_config(AM_HAL_STIMER_XTAL_32KHZ);

// This option would be available to systems that don't care about passing time, but might be set
// to wake up on a GPIO transition interrupt.
//am_hal_stimer_config(AM_HAL_STIMER_NO_CLK);

//Turn OFF Flash1
if (am_hal_pwrctrl_memory_enable(AM_HAL_PWRCTRL_MEM_FLASH_512K))
{
while (1)
;
}

// Power down SRAM
PWRCTRL->MEMPWDINSLEEP_b.SRAMPWDSLP = PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_ALLBUTLOWER32K;

setupRTC();

Serial.println("Going to sleep...");
delay(100); //Wait for print to complete
Serial.end(); //Disable Serial

// Enable interrupts to the core.
am_hal_interrupt_master_enable();
}

void loop()
{
// Go to Deep Sleep.
am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP);
}

void setupRTC()
{
// Enable the XT for the RTC.
am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_XTAL_START, 0);

// Select XT for RTC clock source
am_hal_rtc_osc_select(AM_HAL_RTC_OSC_XT);

// Enable the RTC.
am_hal_rtc_osc_enable();

// Set the alarm repeat interval to be every second.
am_hal_rtc_alarm_interval_set(AM_HAL_RTC_ALM_RPT_SEC);

// Clear the RTC alarm interrupt.
am_hal_rtc_int_clear(AM_HAL_RTC_INT_ALM);

// Enable the RTC alarm interrupt.
am_hal_rtc_int_enable(AM_HAL_RTC_INT_ALM);

// Enable RTC interrupts to the NVIC.
NVIC_EnableIRQ(RTC_IRQn);
}

extern "C" void am_rtc_isr(void)
{
// Clear the RTC alarm interrupt.
am_hal_rtc_int_clear(AM_HAL_RTC_INT_ALM);

// Check the desired number of seconds until LED is toggled.
if (++g_RTCseconds >= 5)
{
// Reset the seconds counter.
g_RTCseconds = 0;

// Toggle LED
digitalWrite(LED_BUILTIN, HIGH);
delay(100);
digitalWrite(LED_BUILTIN, LOW);
}
}
4 changes: 2 additions & 2 deletions variants/SparkFun_Edge2/config/variant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ SOFTWARE.

// Apollo3 pads 30 and 46 are not exposed by Artemis module
const ap3_gpio_pad_t ap3_variant_pinmap[AP3_VARIANT_NUM_PINS] = {
AP3_GPIO_PAD_UNUSED,
0, //Mic VDD
AP3_GPIO_PAD_UNUSED,
AP3_GPIO_PAD_UNUSED,
AP3_GPIO_PAD_UNUSED,
Expand Down Expand Up @@ -65,7 +65,7 @@ const ap3_gpio_pad_t ap3_variant_pinmap[AP3_VARIANT_NUM_PINS] = {
AP3_GPIO_PAD_UNUSED,
39, //Qwiic SCL
40, //Qwiic SDA
AP3_GPIO_PAD_UNUSED,
41, //Accel VDD
42, //Accel SCL
43, //Accel SDA
44, //GPIO 44
Expand Down
4 changes: 4 additions & 0 deletions variants/SparkFun_Edge2/config/variant.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,8 @@ extern Uart Serial;
#define MIC_DATA 29
#define MIC_CLOCK 12

#define MIC_VDD 0
#define ACCEL_VDD 41
#define CAMERA_VDD 32

#endif // _AP3_VARIANT_H_