-
Notifications
You must be signed in to change notification settings - Fork 56
EnergyTrace
Howdy y'all,
This quick little article explains how we perform power profiling, with greatest concern for the average power consumption case. The hardware used will be a recent (MSP430F5528-based) TI FET wired to a GoodWatch, and the software is energytrace-util from the Pluto Watch project.
--Travis KK4VCZ
To profile the GoodWatch, you need to wire its board to a JTAG FET that supports power profiling. I use the MSP-EXP430FR4133 kit, which can be had for $15 on Digikey. The actual target portion of the board is unused, and only the eZ-FET portion is active.
Remove the 0.1" jumpers to disconnect the old target board, then run
four jumper wires to a GoodWatch. In addition to VCC
and GND
, run
SBWTCK
to TX
and SBWTDIO
to !RST
.
Like the BootStrapLoader, the SBW connection can be used to flash
the firmware and read the kernel boot messages. To flash the firmware, use
make sbwflash
.
nuc16% make sbwflash
mspdebug tilib "prog goodwatch.elf" "load codeplug.hex"
MSPDebug version 0.25 - debugging tool for MSP430 MCUs
Copyright (C) 2009-2017 Daniel Beer <[email protected]>
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Chip info database from MSP430.dll v3.13.0.601 Copyright (C) 2013 TI, Inc.
Using new (SLAC460L+) API
MSP430_GetNumberOfUsbIfs
MSP430_GetNameOfUsbIf
Found FET: ttyACM1
MSP430_Initialize: ttyACM1
Firmware version is 31300601
MSP430_VCC: 3000 mV
MSP430_OpenDevice
MSP430_GetFoundDevice
Device: CC430F6147 (id = 0x00f5)
3 breakpoints available
MSP430_EEM_Init
Chip ID data:
ver_id: 8135
ver_sub_id: 0000
revision: 10
fab: 55
self: 5555
config: 10
fuses: 55
Device: CC430F6147
Erasing...
Programming...
Writing 4096 bytes at 8000 [section: .text]...
Writing 4096 bytes at 9000 [section: .text]...
Writing 4096 bytes at a000 [section: .text]...
Writing 4096 bytes at b000 [section: .text]...
Writing 4096 bytes at c000 [section: .text]...
Writing 4096 bytes at d000 [section: .text]...
Writing 1286 bytes at e000 [section: .text]...
Writing 3926 bytes at e506 [section: .rodata]...
Writing 60 bytes at f45c [section: .data]...
Writing 128 bytes at ff80 [section: .vectors]...
Done, 29976 bytes total
Writing 60 bytes at 1800...
Done, 60 bytes total
MSP430_Run
MSP430_Close
nuc16%
Dumping the kernel dmesg uses make sbwdmesg
.
nuc16% make sbwdmesg
...
Device: CC430F6147
Done, 2048 bytes total
...
strings dmesg.bin
Zeroed buffer for bad magic.
----
RNG REF LCD rtc osc CC430F6147 Recognized
buzz cp rad This watch has a radio.
Beginning POST.
10 button entries are available for Jukebox.
key but Initializing UART Booted.
----
RNG REF LCD rtc osc CC430F6147 Recognized
buzz cp rad This watch has a radio.
Beginning POST.
key but Initializing UART Booted.
----
RNG REF LCD rtc osc CC430F6147 Recognized
buzz cp rad This watch has a radio.
Beginning POST.
key but Initializing UART Booted.
nuc16%
On the software end, you need Daniel Beer's mspdebug utility to flash the watch and Lukas K's energytrace-util from the Pluto Watch to dump the consumption graph.
Run make energytrace.txt
to flash the firmware then generate a 30
second trace, which ought to cover the early booting period and then
also the stable period of the clock application ticking.
nuc16% head -n 30 energytrace.txt
#Initializing the interface: #MSP430_Initialize(portNumber=TIUSB, version=31300601) returns 0
#Setting the device Vcc: #MSP430_VCC(3300) returns 0
#Opening the device: #MSP430_OpenDevice() returns 0
#MSP430_GetFoundDevice() returns 0
# device.id: 58
# device.string: CC430F6137
# device.mainStart: 0x8000
# device.infoStart: 0x1800
# device.ramEnd: 0x2bff
# device.nBreakpoints: 3
# device.emulation: 5
# device.clockControl: 2
# device.lcdStart: 0x0000
# device.lcdEnd: 0x0000
# device.vccMinOp: 1800
# device.vccMaxOp: 3600
# device.hasTestVpp: 1
#MSP430_EnableEnergyTrace=0
#MSP430_ResetEnergyTrace=0
1.318000e-03 0.000000e+00 3.280000e+00 2.500000e-06
1.531000e-03 0.000000e+00 3.296000e+00 2.900000e-06
1.800000e-03 0.000000e+00 3.293000e+00 3.200000e-06
2.012000e-03 0.000000e+00 3.289000e+00 3.400000e-06
2.225000e-03 0.000000e+00 3.292000e+00 3.600000e-06
2.635000e-03 0.000000e+00 3.290000e+00 3.800000e-06
2.848000e-03 0.000000e+00 3.293000e+00 4.300000e-06
3.061000e-03 0.000000e+00 3.293000e+00 4.500000e-06
3.331000e-03 0.000000e+00 3.291000e+00 5.000000e-06
3.544000e-03 0.000000e+00 3.290000e+00 5.000000e-06
3.954000e-03 0.000000e+00 3.291000e+00 5.400000e-06
...
3.012178e+01 6.600000e-06 3.292000e+00 3.430800e-03
3.012205e+01 6.600000e-06 3.291000e+00 3.430800e-03
3.012226e+01 6.600000e-06 3.291000e+00 3.430800e-03
3.012248e+01 6.600000e-06 3.291000e+00 3.430800e-03
3.012289e+01 6.600000e-06 3.291000e+00 3.430800e-03
3.012316e+01 6.600000e-06 3.291000e+00 3.430800e-03
3.012337e+01 6.600000e-06 3.291000e+00 3.430800e-03
The columns of this file are the time, current, voltage, and energy, respectively.
Once energytrace.txt
has been generated, you can graph it to a PNG
with gnuplot energytrace.gnuplot
.
You can also run gnuplot energytrace-txt.gnuplot
to give a record of
the current consumption on the console.
GoodWatch Current Consumption
1e-05 +-----------------------------------------------------------+
| + + + + |
| "energytrace.txt" ******* |
8e-06 |-+ ********** +-|
| * * |
| * * *|
|******* * ******************* *|
6e-06 |-+ ********** * * +*|
| ********* * *|
| * *|
4e-06 |-+ *********|
| |
| |
| |
2e-06 |-+ +-|
| |
| + + + + |
0 +-----------------------------------------------------------+
20 21 22 23 24 25
Seconds
While graphs are great to get a sense of high-power features, we generally just want to know how long the Clock applet can tick before the battery needs to be replaced. For this, we simply average the current consumption after boot and then see how long that would take to burn though the battery's capacity.
#!/usr/bin/python3
## This is a quick little python script that takes the output of
## energytrace-util, averages the current consumption for all samples
## after ten seconds, and then predicts battery life from a 100mAH
## CR2016 battery.
## Usage: et 60 | python3 batterylife.py
import sys;
capacity=100 #mAH
ampsum=0.0;
ampcount=0;
#Ugly shotgun parser to ignore comments and early records.
for line in sys.stdin:
if line[0]=='#':
pass;
else:
words=line.split();
time=float(words[0]);
amps=float(words[1]);
milliamps=amps*1000.0;
#We only count after the first 10 seconds, as booting takes 5 seconds.
if time>10.0:
ampcount=ampcount+1;
ampsum=ampsum+amps;
if ampcount>0:
ampavg=ampsum/(ampcount*1.0);
milliamp=ampavg*1000.0;
microamp=ampavg*1000000.0;
print("%f µA average consumption"%microamp);
hours=100/milliamp;
days=hours/24.0;
years=days/365.2425;
months=years*12.0;
print("%f months of CR2016 battery life."%months);
You can pipe energytrace-util
directly into this script to run a
test over a longer period of time, in case you need to quantitatively
compare changes to the codebase.
nuc16% et 600 | ./batterylife.py
6.106727 µA average consumption
22.417138 months of CR2016 battery life.
nuc16%
As of 29 August 2018, the Clock applet idles at roughly 7µA, the radio idles at 1.5mA, and the radio trapped in a Morse transmission pulls 16mA.