Testing the MagTag's power usage to better estimate battery life in various types of use cases.
This type of testing will also be useful for comparing different versions of CircuitPython, different hardware configurations, and different code as time moves on.
- Adafruit MagTag
- Nordic PPK2 Power Profiler Kit
- Nordic Power Profiler software
- Included with the freely available nRF Connect for Desktop software package
- JST PH 2-Pin to female socket cable for power
- Can't find one of these online, but can be custom crimped pretty easily
- JST PH 3-Pin (STEMMA) to female socket cable for digital IO
- Adafruit: https://www.adafruit.com/product/3894
- Can also be custom crimped pretty easily
- MagTag battery input 2-pin JST PH connector
VBAT
,GND
wired to PPK2VOUT
,GND
in SMU mode - MagTag D10 3-Pin JST PH connector
V+
,GND
,Signal
wired to PPK2 Logic PortVCC
,GND
, andD7
- Nordic PPK2 USB/Data connected to an Ubuntu Linux system running Nordic's Power Profiler v3.2.0
- Nordic PPK2 USB Power connected to a 5V 1A USB-A charger
- Nordic Power Profiler software configuration:
- Mode:
Source Meter
- Samples Per Second:
100,000
- Sampling Duration:
432 seconds
- Timestamps:
On
- Digital Channels:
On
,D7
enabled, all others disabled - No changes to default "advanced settings" (gain/smoothing)
Start with PPK2 and MagTag devices disconnected with power switches in the off position.
- Attach MagTag to PPK2 SMU and Digital Input headers
- Plug in PPK2
- Start Power Profiler software
- Start Data Logger
- Enable Power Output
- Turn on MagTag
- Wait for test to complete
- Stop Data Logger
- Save/Export Logged Data
Each test run should result in the creation of two files:
- A binary
ppk
for analysis within Nordic Power Profiler - A plain-text
csv
for analysis using any other tools/methods
Because the PPK2's SMU can be disabled in software, we can connect the MagTag to a computer via USB-C for code updating.
Its probably a good idea to make sure the SMU is disabled when the MagTag is attached to the host system though.
Once code is updated/debugged, power off the MagTag and detach the USB-C cable before turning its power back on.
The general idea is to import modules, execute user code, change states, use peripherals, and perform other actions with periods of time.sleep()
between them. Performing only one one (or very few) actions before entering 1 or 10 second sleep states assists greatly in identifying the specific code being executed while analyzing things.
The PPK2's digital IO inputs can be useful for helping to pinpoint specifically where we are in the code while digging into things.
In the first test code revision this is flipped to high on a few occasions to make it easier to identify the execution a few specific chunks of code.
- While
SPEAKER_ENABLE
is set toTrue
- While blinking the board LED
- While testing the NeoPixels
- While connecting to the WiFi network
A second output pin is configured on A1
but didn't end up being used in this testing. This is flipped to True
when the display is refreshing.
Enabling one or more of these, regardless of whether they're connected or floating, appears to increase power consumption by around 6-7 mA while idle so this should be taken into account while doing any analysis.
The first tests were conducted using magtag-power-test-v1.py
. This was written in just a few minutes without a lot of debugging just to see if this would work conceptually.
There are 7 main phases of this code with 10 second sleeps between them:
- Startup and import of
time
,board
,digitalio
- Init of peripherals
indicator_pin
indicator2_pin
,- board LED,
SPEAKER_ENABLE
, enabled for 1 sec, disable for 1 secNEOPIXEL_POWER_INVERTED
, enabled for 2 sec, disabled for 1 sec- Init of NeoPixels
- LED/Neopixel Tests
- Flash of board D13 LED for 1 sec
- Single NeoPixel max/half-bright for 1 sec each
- All NeoPixels max/half-bright for 1 sec each
- NeoPixels
deinit()
, sleep 1 sec NEOPIXEL_ENABLE
pin toFalse
, sleep 1 sec
- Refresh of display (will contain console output from
print
statements) - Preparing WiFi connect with import of
secrets
andwifi
and definition of a helper method - Connect to WiFi network
- Disable WiFi
- Loop:
- If radio enabled and WiFi not connected, reconnect.
- Refresh display, toggle
wifi.radio.enabled
Device: MagTag
w/ ESP32-S2-WROOM
module
Bootloader: 0.5.2
CircuitPython: 7.0.0 (release)
Data from first test run, 3.7 V
:
- Initial boot:
34.91 mA
avg (870 mA
peak) over1.329 s
for46.41 mC
of charge - CircuitPython boot:
44.03 mA
avg (700 mA
peak) over1.054 s
for46.43 mC
of charge- Each NeoPixel blink (~
125 ms
) averages45.23 mA
(96.80 mA
peak) for5.70 mC
of charge - Idle between blinks:
44.22 mA
- Idle after blinks, before first imports:
27.09 mA
(about1.5 s
)
- Each NeoPixel blink (~
- Phase 0: 1x print statement, import
time
,sleep(10)
:46.30 mA
avg (peak65.31 mA
) over488.1 mS
for23.63 mC
of charge- Idle after print, before import:
27.1 mA
avg (31.30mA
peak) over35.12 mS
- Idle after print, before import:
- Phase 0 End,
sleep(10)
:29.28 mA
avg (34.53 mA
peak) over9.999 s
for292.76 mC
of charge - Phase 1: print statement,
import board
,import digitalio
, print statement52.02 mA
avg (57.48 mA
peak) over0.596 mS
for0.031 mC
of charge
- Phase 1 End,
sleep(10)
:29.30 mA
(34.23 mA
peak) over9.999 s
for292.98 mC
of charge - Phase 2: Digital I/O and NeoPixel setup:
30.57 mA
avg (720 mA
peak) over6.035 s
for184.52 mC
of charge- Pin setup:
49.54 mA
(56.11 mA
peak) over0.25 mS
for0.012 mC
of charge - Speaker pin enable,
sleep(1)
, disable: Idle increases to36.28 mA
(delta of+6.98 mA
) - NeoPixel import and setup:
52.21 mA
avg (720 mA
peak) over32.49 mS
for1.70 mC
of charge
- Pin setup:
- Phase 2 End,
sleep(10)
:30.54 mA
avg (35.98 mA
peak) over9.999 s
for305.38 mC
of charge - Phase 3: LED and Neopixel tests:
51.55 mA
avg (207.53 mA
peak) over16.01 s
for830 mC
of charge- Indicator pin 1 on, on for 1 sec:
32.90 mA
avg (59.50 mA
peak) over1 s
for32.91 mC
of charge - I1 and LED on for 1 sec:
33.07 mA
avg (56.69 mA
peak) over1 s
for33.07 mC
of charge pixel[0] = (255,255,255)
@ 1.0:68.68 mA
avg (95.26 mA
peak) over1 s
for68.74 mC
of chargepixel[0] = (255,255,255)
@ 0.5:49.99 mA
avg (96.80 mA
peak) over1 s
for50.05 mC
of chargepixel[0] = (255,255,255)
@ 0.1:35.48 mA
avg (94.49 mA
peak) over1 s
for35.52 mC
of chargepixel[0] = (255,255,255)
@ 0.05:33.35 mA
avg (83.73 mA
peak) over1 s
for33.38 mC
of chargepixel[0] = (255,0,0)
@ 1.0:45.35 mA
avg (77.58 mA
peak) over1 s
for45.39 mC
of chargepixel[0] = (0,255,0)
@ 1.0:45.48 mA
avg (76.81 mA
peak) over1 s
for45.48 mC
of chargepixel[0] = (0,0,255)
@ 1.0:43.90 mA
avg (76.05 mA
peak) over1 s
for43.94 mC
of chargepixels.fill(0,0,0)
:32.94 mA
avg (75.28 mA
peak) over1 s
for32.97 mC
of chargepixels.fill(255,255,255)
@ 1.0:163.29 mA
avg (207.53 mA
peak) over1 s
for163.44 mC
of chargepixels.fill(255,255,255)
@ 0.5:99.30 mA
avg (191.96 mA
peak) over1 s
for99.40 mC
of chargepixels.fill(255,255,255)
@ 0.1:43.84 mA
avg (181.07 mA
peak) over1 s
for43.86 mC
of chargepixels.fill(255,255,255)
@ 0.05:35.01 mA
avg (131.01 mA
peak) over1 s
for35.07 mC
of chargepixels.deinit()
:31.68 mA
avg (99.87 mA
peak) over1 s
for31.71 mC
of charge
- Indicator pin 1 on, on for 1 sec:
- Phase 3 End,
sleep(10)
:29.28 mA
avg (34.58 mA
peak) over9.999 sec
for292.83 mC
- Phase 4: Display Init and Refresh:
32.8 mA
avg (66.84 mA
peak) over5.371 s
for176.15 mC
of charge- Core display refresh process:
35.04 mA
avg (66.84 mA
peak) over2.371 s
for83.11 mC
of charge - Note:
indicator2
pin is pulled up, probably adding 6-7 mA on top of base current
- Core display refresh process:
- Phase 4 End,
sleep(10)
:29.30 mA
avg (34.63 mA
peak) over9.999 s
for293.03 mC
of charge - Phase 5:
from secrets import secrets
,import wifi
:109.45 mA
avg (289.75 mA
peak) over154.5 ms
for16.91 mC
of charge - Phase 5 End,
sleep(10)
:79.52 mA
avg (107.57 mA
peak) over9.999 s
for800 mC
of charge- Average current draw delta of
+50.22 mA
, more than doubling current, after importingwifi
and before any WiFi activity
- Average current draw delta of
- Phase 6:
wifi.radio.connect()
:92.40 mA
avg (670 mA
peak) over3.362 s
for310.72 mC
of charge - Phase 6 End,
sleep(10)
:31.32 mA
avg (307.08 mA
peak) over9.999 s
for313.21 mC
of charge- Average current draw is back down a delta of only
+2.02 mA
over previous base power draw but there are large300 mA
spikes every315 ms
or so lasting about12-13 ms
before dropping back to a new, slightly lower baseline of about27.02 mA
.
- Average current draw is back down a delta of only
- Phase 7:
wifi.radio.enabled = False
:154.51 mA
avg (328.38 mA
peak) over29.26 ms
for4.52 mC
of charge - Phase 7 end,
sleep(10)
:27.04 mA
avg (51.2 mA
peak) over9.999 s
for270.42 mC
of charge
Run Time: 115.3 s
Current (avg): 39.28 mA
Current (peak): 870 mA
Charge: 4.53 C