Open JF002 opened 4 years ago
I have a ppk here but no real experience. Can hook it up and see what we see https://www.nordicsemi.com/Software-and-tools/Development-Kits/Power-Profiler-Kit
Im using it in the external DUT but with nrf52 attached configuration remove battery, and im just hooking up the 2 pins form external DUT output so it can control power and read usage https://infocenter.nordicsemi.com/pdf/PPK_User_Guide_v2.4.pdf
and this open source python sdk instead of their js stuff https://github.com/inductivekickback/ppk_api/
upstream is be05997
this waits through startup, but screen still on
python3 main.py -p 3 -a 5
Average: 17999.27uA
waits long enough to be measuring when screen is off
python3 main.py -p 25 -a 5
Average: 1195.97uA
Not sure if these are the range of what you're expecting or if I need to dial this in
python3 main.py -p 25 -t 2000 -w 5850 -o trig_data.csv --png
Trigger buff average: 3554.10uA
im sure youd like to try some special firmwares with only certain devices or bluetooth stuff enabled
Sadly im not sure how to automate the damn thing for CI but I can run a few tests occasionally for you, its a pretty clean setup and not too much bother
I have set up simular integration testing nodes before.
i have used: rpi (flashing + read spi data from ina219 + uart) ina219 current sense module
you can then set up a git hook that automatically triggers a build and execution, then upload the results.
for extra points you can add a few servos to tilt / simulate touch event.
even more extra points if you connect a controllable PSU to emulate a battery, then you can also test low/full power detection
Here is what i did: (you can also skip using the NRF dev kit and use openocd to flash through RPI GPIO, but you cant use RTT then.
I then had a webbased interface to allocate / execute and view test nodes. you could also compare between executions.
top left is power consumption, lower left is test framework output (ignore flash failed, its a bug :p ), to the right is the RTT output. the blue is one execution and the grey is another. I have omitted hardware names as it contained customer information.
Yeah ppk doesn't look great for automated purposes I don't think. You have to manually flip a switch to be able to program target and the switch back
You have to manually flip a switch to be able to program target and the switch back
That could be replaced with a relay/transistor.
@jacobrosenthal Thanks for these measurements! So, if I understand correctly, the firmware uses 1.2mA in sleep mode and 180mA when the display is ON?
@maidenone your setup is amazing, I wish I could build something similar to auto-test new versions of the firmware!
In fact, I didn't even think about the automatisation of power measurements, but now, I really want to do that!
By curiosity, how much does the PPK cost and where can I find it?
When I measured Hypnos' power consumption this spring, I got the results below. This is with the HR sensor physically disconnected and BLE advertising disabled.
Sleep | Screen on |
---|---|
1.07 mA | between 12 and 15 mA |
This was manly a "integration test framework" the automatic power profiling was just a bonus. It was written to test various HW revisions of a cellular IoT product deployed in different countries. I can put a few days to clean things up and then release it as open source, if you want to poke around.
Each node (RPI + DUT) connects to a common "manager" (the web interface) through http/json requests. so if i hook up my pinetime, you can deploy and test on it. i also had command line tools so i could flash and get real time RTT output from devices in UK, USA, China or Spain while sitting in my comfy basement. ^_^
I had two git repositories, one for the test-project and one specific for the tests, before a test executed the nodes run git pull on the test repo, so you could add/modify test cases and the nodes was always up to date. Most of the tests was based on parsing debug strings from the RTT feed. but there was also tests that verified that the power consumption was within expected range.
example of a test script:
def run(self):
self.timeSinceStart = 0
self.flash()
# verify that modem was detected
self.addDelayedParse(20,"IAmNow",1)
# run, then turn off'
self.addDelayedEvent(20,self.buttonIn,())
self.addDelayedEvent(5,self.buttonOut,())
self.addDelayedEvent(30,self.parse,("WillNowPowerOff",1))
# verify that we do not boot when off and charging starts
self.addDelayedEvent(10,self.chargerOn,())
self.addDelayedEvent(20,self.parse,("OFFcharging",1))
# wait, then turn on again, verify that we remember our modem type
self.addDelayedEvent(10,self.buttonIn,())
self.addDelayedEvent(5,self.buttonOut,())
self.addDelayedEvent(30,self.parse,("IKnowIAmA",1))
self.addDelayedEvent(1,self.end,())
self.start()
@JF002 The PPK is this: https://infocenter.nordicsemi.com/pdf/Power_Profiler_Kit_PB_v1.0.pdf https://www.digikey.com/products/en?keywords=NRF6707&v=1490 (80$ ish )
But i would go with a custom solution (Pineboard or rpi and a ina219 module) ^_^
will set up two testnodes one with pinetime and one with p8, i will document this on the forum, i would like to make it open to the public, but must find a way to parse the binaries for "bad bits" before flashing to avoid locking/ bricking of the units. i think i got all the hardware i need. automated power measurements between builds will be easy to fix ;)
@maidenone This is awesome! Keep us up to date with your progress!
I detected that my pile of RPIs have been decimated to a broken RPI3, but i have two Orange Pi Zero 256MB H2+ that i can use. My two P8 have entered the country, :D, sadly local customs is usually the big delay.. : (
Hardware:
I have ported to py3 / cleaned up the testing framework, its now operational, but still a bit too "hard coded" in some aspects. Will have to put some more time on it before i share the gitlab link ;) maybe even add bootstrap to beautify the UI :p
Software
I have now started the "beautify" process, bootstrap really makes a difference, just compare the node/test/firmware form compared with the tables beneath.
I have also disassembled my pinetime again :'( are looking on how to wire everything together.
created a forum thread: https://forum.pine64.org/showthread.php?tid=11711&pid=79840#pid79840
This is awesome! I posted a reply on the forum post.
@JF002 I posted some news on the forum, do not know if you get any notifications from there?
I do not receive notifications from Pine64 forums, but I'll try to enable them! Thanks for the additional informations and for your work!
@JF002 check the forum again ;)
Hi all, I started today some power measurement on Devkit.
Bootloader 1.0 RC4
Infinitime 0.13.0
Current is measured with a multimeter (Metrix MX 554) in series with battery terminal +.
Letter, I will make more accurate measurement if needed.
According to the schematics, there is a base consumption, and we can't expect less than that.
This consumption depends on:
datasheet: https://datasheetspdf.com/pdf-file/825717/Microne/ME6206/1
There are several part for the same reference. I hope we don't have ME6206K, which consumes a lot.
datasheet: https://files.pine64.org/doc/datasheet/pinetime/SGMICRO-SGM2036.pdf
@JF002 can you tell me which low power mode you are using when watch is in standy? I mean no screen, no ble connection nor advertising.
base consumption on vbat is 28µA
I made quick measurements :
display | Connection ? | ADV | Consumption (mA) | |
---|---|---|---|---|
Mode 1 | OFF | OFF | OFF | 1,43 |
Mode 2 | OFF | OFF | ON | 1,58 |
Mode 3 | ON | OFF | ON | 27 |
We can see that consumption is really to high!
To see if this high consumption come from display and touchscreen, there are physically disconnected.
display | Connection ? | ADV | Consumption (mA) | |
---|---|---|---|---|
Mode 4 | - | OFF | OFF | 1,4 |
Mode 5 | - | OFF | ON | 1,46 |
Mode 6 | - | ON | OFF | 1,47 |
High consumption is still there and seems not to be related to display. Regarding consumption well all is in sleep, we can imagine that touchscreen and display, in standby, consume about 30µA. (1.4mA without them, 1.43mA within)
Same think, but without HR sensor
HR | display | Connection ? | ADV | Consumption (mA) | |
---|---|---|---|---|---|
Mode 7 | - | - | OFF | OFF | 1,3 |
Mode 8 | - | - | OFF | ON | 1,42 |
Mode 9 | - | - | ON | OFF | 1,35 |
there is still about 1mA of consumption that should not be there.
With that state of measurement, I can't say if it comes from flash, accelerometer, battery charger or nRF52.
I think we can battery charger, as it only consumes on 5V input, not on battery.
We can also forget BMA421 accelerometer. It is not used in infinitime 0.13.0, en even if it was activated, it only consumes 14.5µA in normal mode
I could from flash memory, which consumes few mA in read or write circle.
@JF002 is the flash memory used when watch is in standby?
@vbelloir Thank you very much for this detailed analysis!
Regarding the low-power mode in sleep mode : devices are stopped when possible (ex : the LCD is shut down) and all peripherals (I²C, SPI,...) are disabled. Also, all task are waiting for an event on a queue, which allows the scheduler to enable the "tickless sleep mode" (from FreeRTOS), which, in the end, calls WFI()/WFE(). The instructions puts the CPU in SYSTEM ON low-power mode. All RAM regions are maintained, and it can wake up on any event (timer, ble,...). From the table, I think this is ON_RAMON_EVENT.
Previously, InfiniTime sent the SLEEP command to the external SPI flash memory, but it triggered a bug in the bootloader so I disabled that. The SPI bus is still disabled, though.
In the code, you can have a look at
Regarding the high power consumption you measured : did you ensure that the debug circuitry was not enabled while measuring? The debug circuitry is enabled when the SWD connects to the MCU and is not disabled when the debugger is physically disconnected or by a soft reset. The only way to disable it is to issue a hardware reset or unplug/plug the power. From what I read, this debug circuitry use a lot of power. More info about this here. This wiki page document ways to disable the debug circuitry, but I don't know if they really work. You might be able to check them :)
If it is disabled and you still measure these high numbers, then, we are a lot of room for improvements :p
Thanks for you response.
After posting, I have checked the code, and systemTask.cpp.
And I was surprised that there is no action on CPU, here:
case Messages::GoToSleep:
isGoingToSleep = true;
NRF_LOG_INFO("[systemtask] Going to sleep");
xTimerStop(idleTimer, 0);
displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::GoToSleep);
heartRateApp->PushMessage(Pinetime::Applications::HeartRateTask::Messages::GoToSleep);
break;
I'm not a real firmware guy, so, I will probably say a mistake, but I would have expect something a call to sd_power_system_off, found in SDK.
I will try to put a debugger, to get RTT logs.
This last sentence make me answer your question : I don't think that debug circuitry of dev kit is on, because I have never connected a swd probe to it. I updated it with DFU.
Ok, the debug circuitry is probably disabled, then !
It's not easy to check that the CPU is actually sleeping without waking it up to log that it's sleeping, so it's possible that it's not sleeping as much as I think it should!
You won't find any call to sd_power_system_off
because this is a function from the NRF SoftDevice (NRF BLE stack). InfiniTime is based on NimBLE, an open source ble stack from MyNewt.
You'll find the call to WFE(), where the system is put to sleep, here : https://github.com/JF002/Pinetime/blob/develop/src/FreeRTOS/port_cmsis_systick.c#L266
Here is the procedure to go to sleep:
Messages::GoToSleep
is sent to SystemTaskMessages::GoToSleep
to the other tasks (Display and Heartrate)Messages::OnDisplayTaskSleeping
When this is over, all the tasks are waiting on a queue with a longer timeout. When all the tasks are waiting, FreeRTOS calls WFE to to into sleep mode.
Is it hard to get a simpler project, that just put nrf52 in low power mode? The same you are using in infinitime ?
Also, I got a pca10056 board based on a nrf52840 chip. I will try ti build this project to see which cinsumption i can reach: https://github.com/apache/mynewt-nimble/tree/master/apps/advertiser
Le Jeudi 18 février 2021, JF002 a écrit :
Ok, the debug circuitry is probably disabled, then !
It's not easy to check that the CPU is actually sleeping without waking it up to log that it's sleeping, so it's possible that it's not sleeping as much as I think it should!
You won't find any call to
sd_power_system_off
because this is a function from the NRF SoftDevice (NRF BLE stack). InfiniTime is based on NimBLE, an open source ble stack from MyNewt. You'll find the call to WFE(), where the system is put to sleep, here : https://github.com/JF002/Pinetime/blob/develop/src/FreeRTOS/port_cmsis_systick.c#L266Here is the procedure to go to sleep:
- The idle timer is triggered, or the user pushes the button
- The message
Messages::GoToSleep
is sent to SystemTask- SystemTask sends
Messages::GoToSleep
to the other tasks (Display and Heartrate)- These task do whatever they need to go to sleep (ex : DisplayTask powers the LCD and the backlight off). Display task sends the message
Messages::OnDisplayTaskSleeping
- When SystemTask receives this message, it disables the lcd, touchpanel, and then the SPI and TWI busses.
When this is over, all the tasks are waiting on a queue with a longer timeout. When all the tasks are waiting, FreeRTOS calls WFE to to into sleep mode.
-- You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub: https://github.com/JF002/Pinetime/issues/53#issuecomment-78158125
--
Just as a test, I flashed waspos (bootloader.hex, and micropython.zip).
When Watch is in standby , screen is off, advertising is still there, and consumption is about 2.7mA.... So, we can say that Infinitime is quite efficient ;)
EDIT : in parallel, I let my sealed device discharging itself, without any connection. After 24h, watch still says that battery level is 100%.
Just for example, I just flash on my dev kit, a Nordic beacon example, I get 800µA, without display, touchscreen, and HR sensor.
Today, I made measurement with a really reduced app.
In Mynewt 1.8, a bsp for pinetime was added by Casper Meiin: https://github.com/apache/mynewt-core/tree/master/hw/bsp/pinetime
A tutorial is available to build the mynewt blinky app for PineTime: https://github.com/apache/mynewt-core/tree/master/hw/bsp/pinetime
I also noticed that there is a issue opened by Daniel Kucera concerning low power on nRF52: https://github.com/apache/mynewt-core/issues/2393
I use part of is github work on thie blinky app project.
while loop in main.c becomes:
main(int argc, char **argv)
{
int rc;
#ifdef ARCH_sim
mcu_sim_parse_args(argc, argv);
#endif
sysinit();
g_led_pin = LED_BLINK_PIN;
hal_gpio_init_out(g_led_pin, 1);
hal_timer_deinit(0);
while (1) {
os_eventq_run(os_eventq_dflt_get());
// ++g_task1_loops;
//
// /* Wait one second */
// os_time_delay(OS_TICKS_PER_SEC);
//
// /* Toggle the LED */
// hal_gpio_toggle(g_led_pin);
}
assert(0);
return rc;
}
In that condition, I was able to reach 66µA.
But keep in mind that very few peripheral are used in that setup.
I started some measurement on infinitime code (tag 0.13.0). If I WFE before or after nimble_port_init in main function, and consumption increase from 60µA to 800µA. If itt put just after start of scheduler, it increases to 1.06mA.
I would like to remove all task, and re-activate them on by one, to see where so ressources need to be deinit, but I don't reaally know how to do that.
@JF002 do you have some time to ping me on Telegram, to see how I can help? I can create a Matrix account if you prefer.
I suspect that there is one first work that can be done in pinetime bootloader. I measured consumption at three moments:
Booting 0.14.0 Infinitime release without bootloader, I got those consumptions:
Same Infinitime release, but with bootloader 1.0-RC4:
It seems that there are some ressources, used in mynewt or mcuboot, that are not correctly de initialized.
There are some posts on the NordicSemi forums about power consumption increasing after the first use of SAADC. I'm hoping someone with the means to measure the power consumption could measure the difference with the low power mode enabled, and some other workarounds if necessary
Replacing nrf_drv_saadc_uninit()
with the following fixed the issue for someone. Note that in InfiniTime a different function is used nrfx_saadc_uninit()
.
static void uninit_saadc_on_disconnect(void)
{
nrf_drv_timer_disable(&m_timer);
nrf_drv_timer_uninit(&m_timer);
nrf_drv_ppi_channel_disable(m_ppi_channel);
nrf_drv_ppi_uninit();
nrf_saadc_task_trigger(NRF_SAADC_TASK_STOP);
nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
nrf_saadc_disable();
}
https://devzone.nordicsemi.com/f/nordic-q-a/34702/regarding-nrf-52832-power-consumption-saadc-ppi-timer https://devzone.nordicsemi.com/f/nordic-q-a/74892/power-consumption-increases-1-1ma-after-first-adc-sample
I could try after my summer holidays. I have few time available since few weeks, but I am interested in that subject.
@Riksu9000 I'd like to step up to this, if this can be done with a simple multimeter.
If so, how do I go about this?
@Riksu9000 I'd like to step up to this, if this can be done with a simple multimeter.
If so, how do I go about this?
First you'd need a multimeter that can measure currents lower than 1mA. Then I'd assume you could just attach it between the battery/power supply and the watch and measure all the current going into the watch. Please state whether you use a battery or a power supply, because the results will be different (because of the voltage).
EDIT: I should also mention that you could easily cause a short when measuring current with a multimeter, so make sure you know what you're doing.
I don't have my jtag probe right now. I will get back it next week, then, I will be able to make that measurement.
@Riksu9000 As of now, I only know how to measure voltages (and residence, to a degree), I am still trying to figure out how to measure amperages, so I have no idea what is the lower limit of my multimeter in that regard.
My multimeter runs off a 9V battery pack (nonrechargable).
@vbelloir Regardless of whether I do anything or not, your methodology will be way better.
I have a NRFPPK2 that I use for testing the PineTime now. So I have slowly been amassing some more info on power consumption and will slowly be documenting it as I go. Lots of optimizations to be had I am sure as we worth through stuff!
@geekbozu That would be nice, as @vbelloir has already found many possible optimizations, but I couldn't find enough time to have a closer look at them :)
I did some measurements using my cheap multimeter (that can somehow measure down to 1µA) and posted my findings on the wiki: https://wiki.pine64.org/wiki/PineTime#Reducing_power_consumption
In summary, I was able to get my custom firmware to use only about 0.18mA in standby, while still listening for button events. It doesn't enable BLE, the step counter, or the accelerometer yet which will likely increase this somewhat but I think this means InfiniTime can improve current consumption quite significantly.
@aykevl That sounds quite nice.
By the way, I just watched a video by bigclivedotcom on YouTube the other day, where he made his own cables for his multimeter, to improve the preciseness of his results. That may be a good source of information when dealing with these tiny variances.
@aykevl Thank you so much for sharing your findings! Your results are definitely better than what InfiniTime can do right now (around 1mA in sleep mode). This definitely shows that we have a lot of room for improvements!
I believe I can get lower than the ~177µA I'm now at, by putting the SPI flash in deep sleep mode. The SPI flash uses 12µA in regular (non-deep) sleep mode according to the datasheet, so that would be a nice win. I'll report back when I manage to do that.
@vbelloir how did you get this 66µA value? I tried reproducing it and while I can get to roughly the same value as I get in my own firmware (~0.18mA) I can't get it any lower. This is my main function, based on the blinky tutorial:
int
main(int argc, char **argv)
{
int rc;
#ifdef ARCH_sim
mcu_sim_parse_args(argc, argv);
#endif
sysinit();
g_led_pin = LED_BLINK_PIN;
hal_gpio_init_out(g_led_pin, 1);
NRF_CLOCK->TASKS_HFCLKSTOP = 1;
hal_gpio_init_out(5, 1);
hal_gpio_init_out(25, 1);
hal_timer_deinit(0);
while (1) {
os_eventq_run(os_eventq_dflt_get());
}
assert(0);
return rc;
}
By the way, I just watched a video by bigclivedotcom on YouTube the other day, where he made his own cables for his multimeter, to improve the preciseness of his results.
My setup isn't exactly great. I wired up my broken multimeter cables directly between the VCC wires to measure current. The multimeter itself is a cheap Voltcraft one. I think I'll try to get a Nordic Power Profiler Kit, which is designed for this kind of stuff (unlike this multimeter). I don't think quality of cables matters that much to be honest, because we're dealing with very low currents so even bad cables should work just fine.
hi @aykevl, I'm happy to see that someone is looking on that point! I really think that it is possible to reach 1 month of autonomy with pinetime.
You don't managed to reproduce my setup?
If you want I can do some measurement for you. Unfortunately, I'm not enough good in firmware to go further.
I really think that it is possible to reach 1 month of autonomy with pinetime.
With 0.18mA, 1 month should indeed be possible if the watch is lightly used. With 66µA, up to three months might be possible (but I suspect using the screen will then become a larger power drain).
You don't managed to reproduce my setup?
Unfortunately not. I'm not very familiar with Mynewt but I managed to get the blinky example to work. Can you describe it in some more detail? What steps did you take and which files did you modify? What I did was I followed the blinky tutorial and modified the main function as I posted above.
I tried quickly to reproduce the setup, without any success. It is quiet old in my head.... Right now, I only managed to get 5mA consumption when backlight is off...
I don't remember if I was using bootloader in Feb 2021
@vbelloir thank you for testing! Maybe the LCD is still on? That would explain 5mA of current. You could try power cycling the watch, or send the SLPIN command.
As far as I know, it's not possible to use Mynewt without bootloader.
I managed to put the SPI flash in deep power down mode, which (according to my multimeter) reduces power from 178µA down to 164µA (a reduction of 14µA). This matches the datasheet, which gives 12µA for standby current and 0.1µA for deep power down current (the 2µA difference between spec and measurement is probably well within tolerance of both the flash chip and my multimeter).
As usual, I've put my findings on the wiki.
Do you want me to test your bin file, and measure current also? Your project is available on github or so?
Do you want me to test your bin file, and measure current also?
That would be very useful! It would rule out differences in measurement tools. You could also send me the ELF (or bin) file so I can try myself.
My project is here: https://github.com/aykevl/things/tree/master/watch I don't have any documentation yet and I don't have a way to do OTA updates (it will destroy your bootloader if you have one, so be careful), I will try to add this some time.
Are you sure of the url? it is a GO software? I was expecting a mynewt project or something around infinitime firmware.
I don't know anything about go. How is it build?
I will use it with pinetime dev kit with jlink probe. No need of OTA.
@aykevl
I don't think quality of cables matters that much to be honest, because we're dealing with very low currents so even bad cables should work just fine.
True, I had mixed up impedance with voltage. Sorry about that.
@vbelloir yes it is written in Go (it does not use Mynewt). I haven't provided any documentation yet how to use it, I will try to do so at a later time.
ok, can you at least share me a bin/hex/elf file. It could be able to make some measurement. Are you interested in a boot sequence measurement?
In commit f7e40b1b5879242b4ce59854dbbadb44fe5f75e4, I re-implemented sleep/wakeup for all devices (touchpanel, display, NOR Flash, SPI and TWI). I checked (using the logs) that all Sleep() and Wakeup() method are called in the correct order. I also checked that the MCU is put in deep sleep with a logic analyzer (the MCU is in deepsleep during the call to __WFE() in port_cmsis_systick.c).
Now, I think it would be very interesting to actually measure the power consumption of InfiniTime while running different use-cases:
But... I do not have the necessary instruments and knowledge to do the measurement by myself.
If anyone has the setup and instruments necessary to measure the power consumed by InfiniTime, just write a comment to this issue !
Also, if you can, just leave your Pinetime running this commit (f7e40b1b5879242b4ce59854dbbadb44fe5f75e4) or a next one just to see how long it runs on battery!
Thanks