SparkFun Forums 

Where electronics enthusiasts find answers.

Topics pertaining to the Arduino Core & software used with the Artemis module and Artemis development boards.
User avatar
By robin_hodgson
#207794
It has taken me a while, but I am finally getting the Artemis module on my Blackboard achieve the deepsleep current consumption levels promised by the Ambiq datasheet. To help others interested in this process, I have created an Arduino sketch that shows the steps I took. This sketch is really just a starting point. Different systems will have different requirements for what peripherals need to be active during deepsleep, or how much memory they need powered during runtime or deepsleep, or if they can tolerate a 'cold' cache after waking from deepsleep, just to name a few things.

It is worth noting that deepsleep for any system is a very tricky thing. When you are talking about currents in the microamp and sub-microamp range, all kinds of things start to become measurable effects that might have been previously ignorable. For example, my test board is sleeping right now at 2.5 uA. If I pick the board up off my desk , the power drops to 2.3 uA. If I let go of the board, the power goes back up to 2.5 uA. It is a very repeatable effect. Who knows why, but there you are.

Another class of problems involves the software you might be using: after updating my Arduino system from 1.8.9 to 1.8.10, the deep sleep current jumped from 2.5 uA to 55 uA. I traced that back to what appeared to be another GPIO being configured in a fashion that caused it to suck more current. Changing the appropriate #if in the demo source code (provided below) to invoke the "big hammer" to disable all the GPIOs brought the current back down to 2.5 uA. But to prove that I knew what was going on, I did a search of the GPIOs to see which one it was. And log and behold, it appeared to be none of them. So I changed the source code back to the way it was before. And guess what, the power stayed the same at 2.5 uA, even after a cold start power cycle. So why did it go up in the first place? Again, I don't have an answer to that one. All I know for sure is that deepsleep is affected by subtle things.

Here's a final example, and then I'll shut up: Environment factors also matter. If I exhale a nice, long breath onto my Blackboard, the power consumption goes up over 3 uA and then drifts back down to 2.5 uA over a few seconds as the humid air dissipates.

The bottom line is that there are lots of subtleties involved in any system that is trying to minimize power consumption, and it is a hard problem to truly know that you are on top of all of them. You need to be both careful and ruthless managing your power drains.

Stepping back from the subtleties for a moment, the critical factors that affect deep sleep power consumption are:
  • Disabling power to all peripherals that you don't need operating during deep sleep
  • Making sure that the HFRC (the 48 MHz main RC oscillator) is not being used by any peripheral. This is an issue with the Arduino environment: it configures STIMER to be clocked by the HFRC. That will cost about 60 uA in deepsleep!
  • Make sure that you know what every single GPIO is doing in your system. If you don't need a GPIO, make sure it is disabled. If you do need one, make sure it is not doing something dumb like supplying a weak pullup to external circuitry that is pulling the pin down during deepsleep. Even if the pullup is not being pulled down, the external circuitry that is connected to the pullup will be loading that pin, which will cause a power drain.
Finally, here is an Arduino sketch that puts my Blackboard into a deep sleep at 2.5 uA. Cut and paste the whole mess into your own sketch. Play with it. Try changing memory sizes, or clock sources, and see what changes. You will need a good current meter though. A lot of the changes result in sub-microamp differences in current.

See the photo showing my Blackboard powered from 3.3V being directly injected from an external power supply through my meter and into the measurement connector on the board. I am using Arduino 1.8.10, so who knows if future changes to the Arduino code itself or the Sparkfun Arduino package will affect things.
Code: Select all
// An Arduino sketch for a Sparkfun Artemis Blackboard that demonstrates how to 
// configure the board for deep sleep.

#define LED_ON              HIGH
#define LED_OFF             LOW

const char* peripheralNames[] = {
  "NONE",
  "IOS",
  "IOM0",
  "IOM1",
  "IOM2",
  "IOM3",
  "IOM4",
  "IOM5",
  "UART0",
  "UART1",
  "ADC",
  "SCARD",
  "MSPI",
  "PDM",
  "BLEL",
  "MAX"
  };

void flash(uint32_t count)
{
  while (count > 0) {
    digitalWrite(LED_BUILTIN, LED_ON);
    delay(50);
    digitalWrite(LED_BUILTIN, LED_OFF);
    delay(100);
    count--;
  }
}

void panic()
{
  while (1) {
    flash(1);
  }
}

// For some reason, I need this in the VS Code IDE even though I don't in the Arduino IDE
extern Uart Serial1;

// Disable powering all peripherals except UART0 (used by the Arduino Serial object)
void disablePeripherals()
{
  // Find out what peripherals are enabled at this point and disable them all
  // except UART0 (Arduino 'Serial') which we will still use for a bit:
  Serial.println("Initial peripheral power enable states:");
  for (uint32_t id = (AM_HAL_PWRCTRL_PERIPH_NONE + 1); id < AM_HAL_PWRCTRL_PERIPH_MAX; id++) {
    Serial.print("  ");
    Serial.print(id);
    Serial.print("[");
    Serial.print(peripheralNames[id]);
    Serial.print("]: ");
    uint32_t enabled;
    am_hal_pwrctrl_periph_enabled((am_hal_pwrctrl_periph_e)id, &enabled);
    Serial.println(enabled ? "ENABLED" : "disabled");
    if (enabled && (id != AM_HAL_PWRCTRL_PERIPH_UART0)) {
      am_hal_pwrctrl_periph_disable((am_hal_pwrctrl_periph_e)id);
    }
  }
  Serial.println("All peripherals except UART0 have been powered down.");
}

// Configure the memories for the desired normal runtime and deepsleep operation.
void configureMemories()
{
  // The Apollo3 processor can be configured to only power part of the Flash and SRAM
  // in order to save power during normal operation.
  // For example, if an application doesn't need all of the SRAM, it can arrange to power off the unused parts.
  // A further optimization allows the system to power down even more of the SRAM during deep sleep.
  // 
  // In this example, we will ask to only use 1/2 of the flash during normal operation, 
  // but we will power all 384K of SRAM.
  am_hal_pwrctrl_memory_enable(AM_HAL_PWRCTRL_MEM_FLASH_512K);
  am_hal_pwrctrl_memory_enable(AM_HAL_PWRCTRL_MEM_SRAM_384K);

  // In deepsleep mode, the chip can be configured to turn off even more memory.  Note that if 
  // runmode enables (above) turn some part of the memory off, the sleepmode cannot turn it on.
  // These sleepmode settings only allow you to power down memories that runmode had powered up.
  // Uncommenting the next line would tell the system to power down all of SRAM except the low 32K of RAM.
  // This would take less power, but it would require the codebase to make sure that any information 
  // that it expected to survive a deepsleep would have to be stored in the low 32K of SRAM.
  //PWRCTRL->MEMPWDINSLEEP_b.SRAMPWDSLP = PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_ALLBUTLOWER32K;

  // The Flash memory can also be powered down during deep sleep.
  // changing FLASH0 from being disabled during deep sleep to enabled during sleep adds about 40 uA
  // Testing proves that asking flash1 to be enabled during sleep does not increase the power if runmode has already disabled flash1.
  PWRCTRL->MEMPWDINSLEEP_b.FLASH0PWDSLP = 1;  // '1' indicates that the specified memory will have its power gated OFF during deepsleep
  PWRCTRL->MEMPWDINSLEEP_b.FLASH1PWDSLP = 1;

  // The cache can also be shut down during deepsleep.  This means that when the processor wakes,
  // the cache will be 'empty' and everything will be a miss until the cache refills.
  // The tradeoff is that turning the cache off will cause the system to be a bit slower to wake up.
  PWRCTRL->MEMPWDINSLEEP_b.CACHEPWDSLP = 1;

}

void configureStimer()
{
  // 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.
  CTIMER->STCFG &= ~0xF;
  #if 1
    CTIMER->STCFG |= 0x3;    // selects 32768 Hz via crystal osc. This appears to cost about 0.1 uA versus selecting "no clock"
  #else
    // 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.
    CTIMER->STCFG |= 0x0;    // selects "no clock" (disables STIMER)
  #endif
}

void dumpRegs()
{
  Serial.println("\nDumping Registers");
  // Display which devices currently are powered
  Serial.print("PWRCTRL->DEVPWREN: $");
  Serial.print((uint32_t)&(PWRCTRL->DEVPWREN), HEX);
  Serial.print(": $");
  Serial.println((uint32_t)PWRCTRL->DEVPWREN, HEX);

  // This register enables power to various memories during runmode.
  // If a memory is not enabled in runnmode, it will not be powered in deep sleep either!
  Serial.print("PWRCTRL->MEMPWREN: $");
  Serial.print((uint32_t)&(PWRCTRL->MEMPWREN), HEX);
  Serial.print(": $");
  Serial.println((uint32_t)PWRCTRL->MEMPWREN, HEX);

  // For every memory that is powered in runmode, this register defines whether the specific
  // memory will remain powered during sleepmode.
  Serial.print("PWRCTRL->MEMPWDINSLEEP: $");
  Serial.print((uint32_t)&(PWRCTRL->MEMPWDINSLEEP), HEX);
  Serial.print(": $");
  Serial.println((uint32_t)PWRCTRL->MEMPWDINSLEEP, HEX);
 
  // Show the MISC register contents
  Serial.print("PWRCTRL->MISC: $");
  Serial.print((uint32_t)&(PWRCTRL->MISC), HEX);
  Serial.print(": $");
  Serial.println((uint32_t)PWRCTRL->MISC, HEX);
  
  Serial.print("BLE Buck ON: ");
  Serial.println(PWRCTRL->SUPPLYSTATUS_b.BLEBUCKON);

  // Note in Apollo3 manual: "The SIMO buck cannot be dynamically enabled/disabled after initial device reset."
  Serial.print("SIMO Buck ON: ");
  Serial.println(PWRCTRL->SUPPLYSTATUS_b.SIMOBUCKON);

  // The CLOCKENSTAT registers are important because they show you if there are any parts of the processor
  // that might be responsible for not letting the HFRC oscillator shut down.
  // Show the CLOCKENSTAT register contents
  Serial.print("CLKGEN->CLOCKENSTAT: $");
  Serial.print((uint32_t)&(CLKGEN->CLOCKENSTAT), HEX);
  Serial.print(": $");
  Serial.println((uint32_t)CLKGEN->CLOCKENSTAT, HEX);

  // Show the CLOCKEN2STAT register contents
  Serial.print("CLKGEN->CLOCKEN2STAT: $");
  Serial.print((uint32_t)&(CLKGEN->CLOCKEN2STAT), HEX);
  Serial.print(": $");
  Serial.println((uint32_t)CLKGEN->CLOCKEN2STAT, HEX);
  
  // Show the CLOCKEN3STAT register contents
  Serial.print("CLKGEN->CLOCKEN3STAT: $");
  Serial.print((uint32_t)&(CLKGEN->CLOCKEN3STAT), HEX);
  Serial.print(": $");
  Serial.println((uint32_t)CLKGEN->CLOCKEN3STAT, HEX);
}


// The last step is to disable any GPIOs that might be the source of 
// stray or leaking current going in or out of the Apollo3.
void disableGpios()
{
  #if 1
    // Use a big hammer: disable every single GPIO
    for (int i = 0; i <= 49; i++) {
      am_hal_gpio_pinconfig(i, g_AM_HAL_GPIO_DISABLE);
    }
  #else
    // Disable the GPIOs that we know are in use:
    
    // 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);
  #endif
}

void setup()
{
  // We will use the Serial object while we get set up, then shut it down during our deep sleep test
  Serial.begin(115200);
  delay(1000);
  Serial.print("DeepSleep Testing V1.3 ");
  Serial.println(__DATE__ " " __TIME__);

  // Shut down the Arduino Serial1 which uses the Apollo3 peripheral UART1
  Serial1.end();

  // The Arduino environment has almost certainly already done this, but it is important and
  // calling it again is harmless: Configure the Apollo3 power control block for low power.
  am_hal_pwrctrl_low_power_init();

  disablePeripherals();
  configureMemories();
  configureStimer();
  
  // Before we shut down, dump the state of some of the CPU registers involved with power control
  // to verify the results of the memory configuration requests.
  dumpRegs();
  
  // Print one last message, allow the serial output to drain, shut down the Arduino Serial object,
  // and finally, disable power to the hardware UART0 peripheral
  Serial.println("\nEntering sleep mode");
  delay(100);
  Serial.end();
  am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_UART0);
  
  // Last thing: disable GPIOs so that they don't leak current or get backfed by external circuitry
  // This step is critical to avoid interactions with the CH340 and its TX/RX LEDs from 
  // interacting with the Apollo3 processor.
  disableGpios();
}


void loop()
{
#if 1
  // On my Artemis Blackboard, this results in a power consumption of 2.5 uA
  am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP);
#else
  // On my Artemis Blackboard, this results in a power consumption of 68.6 uA
  am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_NORMAL);
#endif

  // We never intend to get here, so blink the LED forever if we do as a panic indication.
  // It turns out that the Arduino environment is using the STIMER, probably as its basic timer for 
  // managing millis() and things like that.  When this timer rolls over, it appears to cause an interrupt that will 
  // take the system out of sleep again.  Given that we have reconfigured the STIMER to clock at 32 KHz instead
  // of 48 MHz (for the purposes of power testing), we won't wake up for a long time.  Also, note that because
  // we have messed with the Arduino environment before going to sleep, we can't expect the Arduino environment to function 
  // properly when we wake up again.  To really make use of deepsleep modes, a system would need to reconfigure
  // itself after waking up.
  pinMode(LED_BUILTIN, OUTPUT);
  panic();
}
I hope the community finds this useful!
You do not have the required permissions to view the files attached to this post.
User avatar
By robin_hodgson
#207797
I guess I should be extremely clear about 1 more thing: the demo only puts the system into deep sleep. A real system needs to be able to wake from deep sleep effectively, too. For example, the demo program changes how the STIMER is clocked before going to sleep. Instead of being clocked at 48 MHz, the timer will be clocked at 32786 Hz during deep sleep. The Arduino system will not be aware of that, so if you were to make a millis() call after waking from deep sleep, it would appear as though a lot less time had gone past. Of course, you could calculate how many ticks elapsed at the slower clock rate during sleep,use that info to update the arduino counters used by millis(), and reconfigure the STIMER to clock at 48 MHz again. The users of millis() would probably be none the wiser. Going to these lengths is pretty normal. They just represent a potential incremental cost in terms of time and battery energy consumed in order to enter and exit a deep sleep which gets factored into a system-wide cost/benefit tradeoff analysis. For example, it may be that if your desired rate of periodically waking up is fast enough (meaning that the actual sleep period is short enough), it might not be worth the energy cost involved in putting the system to its deepest possible sleep and waking it up again for the short amount of time the system would be able to spend in deep sleep.

Engineering is all about managing tradeoffs, and a system deep sleep mode represents one of the more challenging sets of choices.
User avatar
By sparky
#208763
Hi Robin - Thank you very much for this work. It helped me find my issue (not turning off HFRC).

I've pushed two examples to the core: https://github.com/sparkfun/Arduino_Apollo3/pull/77

I'm measuring ~2.4uA on an Edge 2. I'm not sure how much lower we can go with the datasheet spec'ing 1-2uA at 3.3V.

Please have a look and please comment if you have any additional thoughts.

Cheers,
-Nathan
User avatar
By robin_hodgson
#208765
The best I have been able to do on my Blackboard is 1.63 uA at 3.3V. That is based on:
  • microphone power trace cut
  • All peripherals off
  • All gpios disabled
  • CTimer OFF
  • STIMER configured for 1KHz RX clock
  • All FLASH powered off in deep sleep
  • Cache powered OFF in deep sleep
  • Only 8K of the SRAM remains powered in deep sleep
See this post viewtopic.php?p=208415#p208415 to see a table of power consumption data.

It's all moot though because none of the A1 processors can reliably reach these current levels. As mentioned in this post viewtopic.php?p=208325#p208325, the A1 processors have a bug that comes into play when they are in deep sleep. According the Ambiq, the SIMOBUCK voltage regulator on an A1 can lock up and fail, eventually causing the ASIC to suffer a supply voltage brownout reset. The published workaround from Ambiq is to never let the A1 chip go into deep sleep. That is accomplished by leaving the PDM unit turned on because it takes the least current of any peripheral on the chip. You can see that inside the HAL routine am_hal_pwrctrl_low_power_init() where the code explicitly tests if the processor is an A1 with the SIMOBUCK turned on and if so, turns on the PDM to avoid triggering the bug.

On my Blackboard with its A1 silicon, it means that the deep sleep current I have measured is more like 38.0 uA, as per my current consumption chart mentioned earlier in this post. The only way to get a reliable 1.63 uA deep sleep is via B0 silicon. I have asked if there is a plan to release boards with B0 silicon on them in this post viewtopic.php?p=208325#p208325, but have not heard back from Sparkfun yet. Maybe you can ask around for us!!
User avatar
By adam.g
#208769
Hi Nathan,

Thanks for providing the examples. I recognize much of the code from the Ambiq SDK deepsleep_wake.c example, but for those of us still familiarizing ourselves with the HAL, it can be really beneficial to see the code rewritten for a specific application. I find that using the HAL functions to place the Artemis in deep sleep is very reminiscent of using the <avr/power.h> and <avr/sleep.h> functions to reduce the power consumption of an ATmega328P.

A question I have is: what happens when the Artemis module wakes up from deep sleep? Given that the ADC, SRAM, and Flash1 are manually disabled/turned off, when the system wakes back up from deep sleep, will it automatically re-enable/turn on all of the disabled on-board peripherals?

Cheers,
Adam
User avatar
By robin_hodgson
#208770
The only things that have automatic power control when the module wakes from deepsleep are memory-related: Flash, SRAM and Cache. The flash will remember what it contained (obviously), but any flash that was unpowered during deepsleep takes some extra latency to get started up after the wake event. Any cache or SRAM that was configured to be unpowered during deepsleep will lose their contents as the result of a deepsleep.

In contrast, the individual peripherals must be powered off manually before a deepsleep, and must be manually powered up again after a deepsleep. Powering a peripheral off has the side effect of destroying its register configuration. After exiting deepsleep, the system software can't just repower the peripheral, but it will need to completely reinitialize the peripheral's internal registers and IO pin configurations before it can be used again.

If I remember right, one of the Ambiq examples showed a method of dealing with a peripheral across a deep sleep power down. Before deepsleeping, they copied the state of the existing UART configuration into a RAM structure, disabled the GPIO pins associated with the UART to avoid leaking power in or out of the IO pads, powered down the UART, then finally went into deepsleep. After waking from deepsleep, they powered the UART peripheral back up and used the saved peripheral configuration to reinitialize the UART peripheral. That is the basic process for any peripheral that you want powered down during a deep sleep.
User avatar
By adam.g
#209146
Hi,

Just a quick update that I was also able to achieve a quiescent draw of ~2.64 uA with an Edge 2 (B0 silicon confirmed) using the LowPower_WithWake example that has now been pushed to the SparkFun Apollo3 board definitions.

However, I feel it's important to restate what Robin mentioned earlier about his code:

robin_hodgson wrote: Wed Sep 18, 2019 11:23 am I guess I should be extremely clear about 1 more thing: the demo only puts the system into deep sleep. A real system needs to be able to wake from deep sleep effectively, too.
While neither Robin's code above, nor the SparkFun Advanced examples bring the system back out of deep sleep, they are really good starting points to learn from. I imagine that a library will eventually be written to simplify the sleep functionality, but in the meantime it would still be great to see an example of how this can be effectively accomplished.

Cheers,
Adam
User avatar
By robin_hodgson
#209149
I've been working on that for a while now. From a silicon perspective, it pretty trivial. Follow the basic steps from the original Arduino example (above), and you are good to go to sleep. When an event or interrupt occurs that causes the processor to start running again, the call to am_hal_sysctrl_sleep() will return, the next line of code executes, and off you go. There is nothing you *have* to do when the system wakes up, unless you want to undo some things that you did before deep sleeping. But those things to be undone are not silicon requirements, they represent your own specific software system requirements. For example, maybe your system uses the ADC to sample some sensor while the system is awake. Even without considering deep sleep, your software system would have required some form of an adc_init() routine that makes sure the ADC peripheral is powered and properly configured before use. In order to minimize system power, you would power down the ADC peripheral before calling am_hal_sysctrl_sleep(). After waking, you would just call your adc init() routine and you are good to go. It really is that simple. Something like this:
Code: Select all
...

// Power down the ADC
am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_ADC);

// Go to sleep
am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP);

// Power up and reconfigure the ADC before use!
adc_init();
The complexities arise due to the requirements of your specific system. For example, it you want to turn off RAM during deepsleep, that's easy. But your software system needs to be written with the understanding that any time it executes am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP), any unpowered SRAM gets erased. That could end up being a very complicated problem. Another example of a complexity is when you add an RTOS to the mix. The RTOS will sleeping whenever it has no tasks that are ready to run, as it should. But when the RTOS puts the processor to sleep, it only knows that it has nothing immediate to do. The issue is that the RTOS has no innate knowledge of your system's overall power states. So the RTOS can't tell the difference between a situation where the only running task asks for a 1 millisecond sleep delay and the situation where your entire system wants to go into the deepest possible sleep for the next hour. That makes it a much trickier problem to figure out when to shut peripherals down, and how to explain all that to the RTOS. I'm still working on that one!

My test case to try and work through these issues uses a FreeRTOS program to drive a current sensor board that measures the AC current being drawn by whatever is plugged into a specific power outlet. While no AC current is being drawn, the system remains in deep sleep. The current sensor hardware is designed to present an analog voltage trigger to the Apollo3 Voltage Comparator unit. The Apollo3 comparator is set up so that whenever the current sensor board sees a current draw of about 1 Amp, it generates an interrupt that wakes the processor from deep sleep. This causes an RTOS task to run that powers up an I2C interface so it can start logging. The task logs 16-bit current readings at 10Hz. During the entire logging process, the RTOS itself will be deep sleeping periodically as the logging software starts ADC conversions and waits for results. But these deep sleeps are different in that I don't want the system turning off my I2C interface for example. Logging continues until the logging task observes the current draw drop below 0.1A for more than a second. At that point, the task shuts down the I2C interface, primes the Voltage Comparator unit to look for the next 1A current event, and arranges for the lowest-possible deep power to be entered the next time the RTOS goes into deep sleep. It's a pretty simple system, but it has served to expose a lot of the issues that I mentioned. FWIW, the system works, but I think it is telling me that I don't have a general solution yet on how to integrate things like this with the RTOS.
User avatar
By jur123@xs4all.nl
#209443
Hi,
I am using your exact code on a new Artemis Thing Plus (new, without any hardware alterations) and in deep sleep
I measure 1,8 mA (which is considerbly higher than then then expected value of < 250 uA).

I use a battery-pack 3,7 V with the suplied connector, not connecting the usb).
The red power led is on (how can I turn that off?).

What am I doing wrong. Help is appreciated,

Regards, Jur
User avatar
By adam.g
#209444
Hi Jur,

Unfortunately, the SparkFun Artemis Thing Plus does not have a jumper that you can cut to disable the power LED. I experienced the same problem with the Artemis Nano (viewtopic.php?f=172&t=50789#p207655). If you want to reduce the quiescent draw, you will either need to delicately cut the trace to the LED or remove it with a hot air soldering rework station. Given how close all of the LEDs are, I'd suggest cutting the trace.

Cheers,
Adam
User avatar
By ironhalo
#212597
I am experimenting with deep sleep on the Artemis Nano, and am learning quite a bit. Thank you to everyone who has shared all of the valuable info above. I have two related questions so far...

1) When running the associated code examples in the core, "lowPower" and "lowPower_WithWake", I don't get any successful Serial output, just a few "???" in the terminal window. My terminal and serial connection are definitely setup correctly, correct baud rate, etc. For example with the code Nathan provided to check the silicon revision on the Nano boards, I get successful output confirming B0 silicon on all of my boards. But with these two lowPower sketches I get nothing. Is anyone else seeing this, or is something peculiar about my setup? I've tested it on three different rev B0 Nano boards with the same result. I was hoping to modify these sketches with additional serial output to learn more about what's going on within them.

2) On one of my boards I have connected a switch across the PSWC pins. However it seems that when using this switch to disable the power on the board, the power draw remains in the ~0.3mA range. Clearly in a 'low power' application to have the board drawing more power in the "power off" state than a deep sleep state doesn't make much sense. Is this expected behavior, or am I doing something incorrectly? If normal behavior, it seems that if I want to be able to truly stop the board from drawing power, my switch needs to go between the 3.7v LiPo and the board instead (which is what I likely would have done initially had I not seen the option of the PSWC pins as an attractive alternative to cutting and soldering one of battery leads into my switch...making it infinitely harder to swap out battery packs using the onboard JST connector).

Thanks in advance.
User avatar
By ironhalo
#212599
Nevermind on question #1, I realized the RX/TX pins had been disabled in setup. Commenting those two lines out temporarily restores the serial output.

After studying this sketch further though, I now realize what others meant when they said the device is never truly woken from sleep in the 'withWake' example. It essentially stays in sleep mode and merely performs a periodic task via RTC interrupt. Has anyone managed to produce an example of a more conventional sketch that while performing a set of tasks reaches a condition that results in deep sleep, and then by way of interrupt or timer, wakes from deep sleep and resumes those original tasks? As a novice programmer, that would be an invaluable example to learn from. While I mostly understand what's going on the in examples provided thus far, I am having a hard time making the leap between these examples and the type of sleep/wake routine that could function within a more conventional sketch. Even a rough outline of how a sketch like that would function would be a great start.

Any help or guidance is very much appreciated! TIA.
 Topic permissions

You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum