I was trying to do some power measurements on my Artemis Blackboard. I started by cutting the MEAS trace and adding 0.1 jumper pins so I could measure the current going through the MEAS jumper pins. When I ran a simple test program, my current meter indicated that there was about 0.5 mA current going through the MEAS jumper pins. That matched the marketing claims of “less than half a milliamp at 48 MHz”, so I figured that all was fine with the world.
But then I noticed that when I removed the current meter wires, the test program continued to run! With no meter or shorting jumper in place across the MEAS pins, that should be impossible. In addition, I could measure about 2.62V on VDD, which again, should be impossible given that without the shorting jumper, there should be no source of VDD!
Diving into the schematic, I think what is happening is that the TX and RX LEDs used by the CH340C USB interface ASIC are powering the processor through its IO pins. The LEDs will act as a source of power to the processor IO pins whenever there is a source of 3.3V, either coming from the USB supply or the barrel connector supply. The only ways to power the processor that don’t also power the LEDs are to power it via V_BATT, or to disconnect the MEAS jumper and inject an external power source directly to the VDD side of the MEAS jumper pins.
Since I don’t have a battery holder on my board, I disconnected the USB power supply and applied 3.3V from an external supply directly to the VDD jumper pin. With a DMM in series with the external supply, the system now indicates that it is taking 5.50 mA, or about 10 times as much power as the 0.5 mA marketing claim at 48 MHz. I guess that there was a fair bit of processor power sneaking in through the IO ports.
There are a couple of issues here: I think that the MEAS jumper does not operate as the designers thought, unless their plan was that power should be injected via the VDD side of the jumper. Also, the processor takes 10 times more power than I was hoping, given the marketing claims. Or maybe, I am doing something totally wrong. But I don’t think so. Let me know if I am missing something here.
void loop() {
volatile uint32_t count;
count = 0;
do {
count++;
} while (count <= 10000000);
trigger_freq_counter();
}
It counts from 0 to ten million, sends a trigger to a freq counter so I could measure how many clocks it took per loop, and just repeats forever. The variable ‘count’ is declared ‘volatile’ in order to force the compiler to not optimize the loop out of existence.
Basically a couple of RAM access per loop along with fetching instructions from the cache.
Fun fact #1: measurements show that the Cortex M4F on the Artemis executes a single iteration of this loop in 10 cycles. Compiling for a Cortex M0+ generates identical assembly code, but the M0+ needs 12 cycles to execute the same instruction sequence! So the M4F is a bit more efficient, perhaps due to its write buffer?
Fun fact #2: I added one single precision floating point operation to the loop, and the loop took exactly 1 cycle longer to run per iteration. Yay hardware floating point!
OK, I think I have it all nailed down now. The issue is that in the Arduino environment I am using, it looks like the default run-time setup is driving one of the Artemis TXO-0 or RXI-0 signals to the CH340. When the system has no 3.3V supply and is being fed power directly into VDD via the MEAS jumper pins, this has the unfortunate side-effect of backfeeding power from the serial pin into the CH340S, causing the system to use more power than it should.
Adding a call to Serial.end() inside setup() tells the Serial object to let go of its RX and TX pins so that they can be used as normal GPIOs. Once that is done, the power going into VDD when running the test program drops from 5.5 mA down to 0.65 mA. That is way closer to the marketing spec of “less than half a millamp”.
I think that the remaining excess current may be due to the fact that the microphone chip on the board is permanently enabled. Too bad the microphone ENABLE signal is not tied to a GPIO!
The bottom line would appear to be that in order to actually measure the power on a Blackboard, you need to:
Cut the MEAS jumper
Unplug all power sources from the barrel connector or USB
Use an external power supply to feed power into the VDD side of the MEAS jumper, otherwise certain processor GPIOs get backfed from the 3.3V source that goes to the RX and TX LEDs
Add a call to Serial.end() inside setup(), otherwise the processor tries to backfeed the CH340S via RXI-0
Finally: the supply current can be measured with a meter in series with the supply that is feeding VDD
Maybe there is a better way, but I think this method produces accurate results.
If you are using the Arduino environment and trying to take power measurements using the MEAS jumper, you need to:
Cut the MEAS jumper
Add a call to Serial.end() in your setup() function
Put your current meter across the MEAS jumper
The current being measured will be accurate now. When active, the Serial object configures the processor IOs connected to RXI-0 and TXO-0 signals in a fashion that will cause power readings at MEAS to be distorted, as per the previous posts. Disabling the Serial object fixes everything.
Today’s experiment was to try the 96 MHz “boost mode” in the new 1.0.2 Arduino toolchain. It works as expected: the test program runs exactly twice as fast since it is completely cache resident, but the power consumption went from 0.61 mA at 48 MHz to 2.31 mA at 96 MHz. That’s almost exactly 4 times as much, so significantly more than a linear increase. Still pretty impressive though: a 96 MHz processor running flat out while taking about as much power as a typical LED!
This is an excellent write up! I welcome the chance to work on this with you. You are right on many things. The Artemis is so low power sneaking power sources is a concern.
The CH340 via the tx and rx lines being a primary leak. In retrospect isolation jumpers or current limiting resistors may have further reduced the leak current but like you I was seeing around 0.5mA and decided that was within the margin of error for most setups.
The microphone select pin could have been wired to a gpio but I don’t think that would have helped. Here’s the datasheet for the mic: https://www.mouser.com/ds/2/218/SPH0641 … 952032.pdf The select pin is only used when two mics are used in the same PDM bus. If you’re not actively clocking the device it goes into low power mode of 80uA.
There are a few more hardware sources that may contribute to current. Currently ADC is enabled by default in our Arduino core. Additionally, turning off some of the cache and flash may reduce power further. Be sure to checkout the examples in the Ambiq SDK for various HAL hooks to help power down additional peripherals. Here is my rough attempt and getting to 2.7uA in sleep. Currently I’m at 72uA so a ways to go.
/*
How low can we go?
By: Nathan Seidle
SparkFun Electronics
Date: June 24th, 2019
License: This code is public domain but the prime number function
comes from Ambiq/John Burkardt and has a GNU LGPL license. Additional
code based on Ambiq's burst example.
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
This example shows how decrease the Artemis current consumption as low as possible.
How close can we get to 2.7uA in deep sleep?
6/26/2019 - 72uA. Is the CH340 IC causing drain on TX/RX pins?
*/
void setup() {
Serial.begin(9600);
Serial.println("Low power sleep example");
Serial.flush();
//Disable Serial
Serial.end();
//Turn off ADC
power_adc_disable();
//pinMode(13, INPUT);
am_hal_gpio_pinconfig(ap3_gpio_pin2pad(13), g_AM_HAL_GPIO_DISABLE);
// Initialize for low power in the power control block
am_hal_pwrctrl_low_power_init();
// Run the RTC off the LFRC.
am_hal_rtc_osc_select(AM_HAL_RTC_OSC_LFRC);
// Stop the XTAL.
am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_XTAL_STOP, 0);
// Disable the RTC.
am_hal_rtc_osc_disable();
// 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;
am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP); //Should stop here and be ~2.4uA
numberOfPrimes(1000); //Find the number of primes in 10,000
}
void loop() {
//Do nothing
}
// Returns the number of primes between 1 and N.
// A naive algorithm is used.
// Input, int N, the maximum number to check.
// Output, int PRIME_NUMBER, the number of prime numbers up to N.
int numberOfPrimes(int maxToSearch)
{
uint32_t ui32Total, ui32Prime;
int32_t ix, jx;
ui32Total = 0;
for ( ix = 2; ix <= maxToSearch; ix++ )
{
ui32Prime = 1;
for ( jx = 2; jx < ix; jx++ )
{
if ( (ix % jx) == 0 )
{
ui32Prime = 0;
break;
}
}
ui32Total += ui32Prime;
}
return ui32Total;
}
I’ve scratched the surface and found similar measurements that you did. I hot air removed the mic (80uA in power down). In the above code I attempt to power down as much as possible. For future tests I need to cut the traces to the CH340. I suspect this will help with the deep sleep current use.
One thing I have done is to power very low-power devices (such as the mic) directly from a GPIO pin. At such low current draws, the GPIO is perfectly capable of sourcing enough current without an appreciable voltage drop, as long as there are not large current spikes during operation. Obviously, this approach is not suitable for every peripheral, but when it is, it lets the system power the peripheral to a genuine ‘off’ state, as opposed to some form of deep sleep.
I in interested in seeing how low we can get the processor power to go! Thanks for the update!
For other people wanting to temporarily disable the microphone, there is a much easier way than hot-air removing it from the board. Just use a brand-new Xacto blade to cut the mic’s power trace in the location show by the black ‘X’ in the image. Use a meter to confirm that you cut the trace by measuring for continuity between the ends of the capacitors circled in black. There will be no continuity if you have cut the trace completely. The best part is that if you want to reactivate the mic at some point, it is quite easy to add a jumper wire between the exposed ends of the capacitors marked by the black circles in the same image.
For the record, cutting power to the microphone saved 26.6 uA on my Blackboard. The spec sheet claims a typical sleep mode current of 25 uA. It’s always nice when the spec sheet matches reality!
After cutting the mic power, explicitly disabling some GPIOs (RXI-0, TXO-0, SWDCLK, SDWDIO), disabling every peripheral that was enabled by the Arduino environment (UART0, UART1, ADC), and doing basically what was in your example code, I am down to 67.4 uA in deep sleep mode. There must be some more low-hanging fruit somewhere if the ASIC claims deep sleep under 3 uA because I’m still more than 20 times worse than that!
For example, I think there are some timers running. I have things set up so that if my sleep operation ever wakes up for any reason, I make it blink the built-in LED forever. I have found that the code stays in deep sleep for some number of minutes (maybe around 5-10 minutes, but I’ve never timed it), and then it wakes up. Something must be running inside the ASIC in order to cause that!
Until today, the best I could get the system to do was about 66 uA in deep sleep. It took a couple of days of carefully reading data sheets followed by many experiments, but my Artemis blackboard is finally doing a low power deep sleep at the current consumption levels promised by the Ambiq datasheet. My Fluke meter is currently reporting a deepsleep consumption of 2.02 uA at 3.3V. It took me a long time to figure out that the STIMER peripheral is getting enabled by the Arduino environment using the 48 MHz HFRC (High Frequency RC) clock source. When I changed the STIMER to use the 32768 Hz XTAL clock instead of the HFRC, the board’s power consumption dropped from 66 uA down to 2 uA in deep sleep. Turning the STIMER completely off (by selecting the clock source “none”) drops the power down to about 1.7 uA. Plus, there was the small matter of disabling the microphone, as well as a bunch of GPIO configuration that needed to occur so that the processor and CH340 would not be trying to backfeed each other, detailed in the posts above.
When I get a bit of time, I’ll provide a minimalist code example of how to put the device into deepsleep using the Arduino environment. But in the meantime, it appears that the Artemis really can deep-sleep down around 2 uA!
I would love to show it, but I’m not quite finished with the example and now my blackboard won’t let me upload my code anymore. I’m dead in the water right now. See post viewtopic.php?f=169&t=50888
Bootloader is reflashed and the low power code is finished. This forum appears to be locked now, so I created a new topic discussing the process over here: viewtopic.php?f=169&t=50904