Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Power analysis #53

Open
JF002 opened this issue Aug 22, 2020 · 71 comments
Open

Power analysis #53

JF002 opened this issue Aug 22, 2020 · 71 comments
Labels
help wanted Extra attention is needed needs more info More information is needed needs more work This PR needs more work

Comments

@JF002
Copy link
Collaborator

JF002 commented Aug 22, 2020

In commit f7e40b1, 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:

  • Display the Clock Screen
  • BLE disconnected/connected
  • BLE advertising (BLE advertising is enabled for 3 minutes after a wakeup) and continue even if the soft is in sleep mode -> measure power for more than 3 minutes after switch off the screen).
  • ...

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 (f7e40b1) or a next one just to see how long it runs on battery!

Thanks

@JF002 JF002 added the help wanted Extra attention is needed label Aug 22, 2020
@jacobrosenthal
Copy link

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

trig_data

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

@maidenone
Copy link
Contributor

maidenone commented Sep 7, 2020

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.

TestNode

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.
compareOutput

@jacobrosenthal
Copy link

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

@Avamander
Copy link
Collaborator

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.

@JF002
Copy link
Collaborator Author

JF002 commented Sep 7, 2020

@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?

@endian-albin
Copy link

endian-albin commented Sep 7, 2020

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

@maidenone
Copy link
Contributor

maidenone commented Sep 7, 2020

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) ^_^

@maidenone
Copy link
Contributor

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 maidenone mentioned this issue Sep 26, 2020
@JF002
Copy link
Collaborator Author

JF002 commented Sep 27, 2020

@maidenone This is awesome! Keep us up to date with your progress!

@maidenone
Copy link
Contributor

maidenone commented Sep 28, 2020

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:

  • 2x NRF Devkits
  • 2x ina boards (power measurement)
  • 2x servos
  • 2x orange pi
  • 2x relay modules
  • 1x pinetime
  • 1x p8
  • time

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

  • Fully operational
  • break out hardcoded hwspecifics
  • beatuify
  • share gitlab link

@maidenone
Copy link
Contributor

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.

Screenshot from 2020-10-02 10-52-28

@maidenone
Copy link
Contributor

created a forum thread:
https://forum.pine64.org/showthread.php?tid=11711&pid=79840#pid79840

@JF002
Copy link
Collaborator Author

JF002 commented Oct 4, 2020

This is awesome! I posted a reply on the forum post.

@maidenone
Copy link
Contributor

@JF002 I posted some news on the forum, do not know if you get any notifications from there?

@JF002
Copy link
Collaborator Author

JF002 commented Oct 5, 2020

I do not receive notifications from Pine64 forums, but I'll try to enable them!
Thanks for the additional informations and for your work!

@maidenone
Copy link
Contributor

@JF002 check the forum again ;)

@vbelloir
Copy link

vbelloir commented Feb 18, 2021

Hi all,
I started today some power measurement on Devkit.

Setup

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.

Theoretical consumption

According to the schematics, there is a base consumption, and we can't expect less than that.
This consumption depends on:

  • U14: 3.3V LDO for nRF, and memory,
  • U12: 3.3VLDO for sensors,
  • standby consumption of components, power by LDOs or battery.

U14: ME6206

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.
image

U12: SGM2036-3.3

datasheet: https://files.pine64.org/doc/datasheet/pinetime/SGMICRO-SGM2036.pdf

image

nRF52832

@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.

image

total

base consumption on vbat is 28µA

Measurement

first measurements

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!

Without display & touch

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)

Without HR sensor

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

conclusion

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
image

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?

@JF002
Copy link
Collaborator Author

JF002 commented Feb 18, 2021

@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

  • this case called when the user pushes on the button : it sends a message to all the task to put them to sleep
  • and this case when the devices are disabled before the systemtask goes to sleep.

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

@vbelloir
Copy link

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.

@JF002
Copy link
Collaborator Author

JF002 commented Feb 18, 2021

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:

  • 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.

@vbelloir
Copy link

vbelloir commented Feb 18, 2021 via email

@vbelloir
Copy link

vbelloir commented Feb 19, 2021

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%.

@vbelloir
Copy link

Just for example, I just flash on my dev kit, a Nordic beacon example, I get 800µA, without display, touchscreen, and HR sensor.

@vbelloir
Copy link

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:
apache/mynewt-core#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.

@vbelloir
Copy link

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.

@vbelloir
Copy link

vbelloir commented Mar 5, 2021

I suspect that there is one first work that can be done in pinetime bootloader.
I measured consumption at three moments:

  • t1: at startup, when screen and advertising are ON
  • t2: when screen is switched off, be adv is still ON
  • t3: when adv stopped.

Booting 0.14.0 Infinitime release without bootloader, I got those consumptions:

  • t1: 27.3mA
  • t2: 1.16mA
  • t3: 0.9mA

Same Infinitime release, but with bootloader 1.0-RC4:

  • t1: 27.3mA
  • t2: 1.54mA
  • t3: 1.43mA

It seems that there are some ressources, used in mynewt or mcuboot, that are not correctly de initialized.

@JF002 JF002 mentioned this issue Jul 20, 2021
@Riksu9000
Copy link
Contributor

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

https://github.com/JF002/InfiniTime/blob/514481ef7f9c71ad816b31d979c6ab39ce9380dd/src/sdk_config.h#L4165

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

@vbelloir
Copy link

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

@aykevl
Copy link

aykevl commented Apr 19, 2023

@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.

@aykevl
Copy link

aykevl commented Apr 19, 2023

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.

@vbelloir
Copy link

Do you want me to test your bin file, and measure current also?
Your project is available on github or so?

@aykevl
Copy link

aykevl commented Apr 19, 2023

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.

@vbelloir
Copy link

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.

@moriel5
Copy link

moriel5 commented Apr 19, 2023

@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.

@aykevl
Copy link

aykevl commented Apr 19, 2023

@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.

@vbelloir
Copy link

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?

@aykevl
Copy link

aykevl commented Apr 19, 2023

Here is a zip of the ELF file: watch.zip
This is with all the optimizations I know applied. I'm getting 162µA right now from my multimeter.

@aykevl
Copy link

aykevl commented Apr 20, 2023

I managed to reproduce the ~66µA power consumption! The final missing bit was the heart rate sensor that is apparently enabled by default and consumes 0.1mA.
My multimeter claims it consumes only 60µA, but this 60µA vs 66µA difference could easily be explained by one or both multimeters being slightly wrong (I have a cheap one that I've noticed changes a bit over time).
I think this is the lowest we can possibly get with the PineTime. I've also investigated the BMA421 accelerometer and it appears to be set in power down mode by default.

@vbelloir here is the updated firmware, in case you'd like to test: watch.zip. It consumes a bit more in my measurement (62-63µA) because it's also polling the button, I get the lowest power consumption when I really disable everything.

As usual, I have updated the wiki.

@moriel5
Copy link

moriel5 commented Apr 21, 2023

Since I mostly need the clock function, I am really looking forward to having my PineTime using this little power most of the time.

@vbelloir
Copy link

Hi @aykevl I just test it right now.
I found 43µA standby with your fw, It's very nice!

Next week, I would be able to lake also some measurements with a better tool. This tool is used by a colleague.

@aykevl
Copy link

aykevl commented Apr 21, 2023

Thanks a lot for testing!
I just received my Power Profiler Kit, and using it I found some interesting details:

  • It uses around 15uA most of the time, with very little peaks every 10-20ms. Averaging this out, we get around 66uA on the short term (matching your original measurement).
  • Every minute, it awakes for about 208ms and during that time it consumes around 2.8mA. I believe I've seen these very short blibs on my multimeter but of course couldn't measure them properly.

When I take the average of multiple minutes of measurement, I get around 80uA (although it fluctuates a bit).

I don't know what is causing these current spikes, but I imagine some of the chips (the touch controller perhaps) is recalibrating during that time. If I remember correctly, the touch controller consumes around 3mA when active, so that would make sense.

@aykevl
Copy link

aykevl commented Apr 21, 2023

I left it running for a bit longer and found some more patterns. It appears to go through periods of higher and lower current consumption. The lower current consumption is around 72uA (averaged out over a minute to include the 200ms spikes). Higher current consumption (up to around 200uA) seems to get triggered by movement, or by me resting my arms on my desk (??), although that could perhaps also be bad cables or something else. In any case, the typical resting current consumption seems to be more like 72uA, which is still pretty low (~100 days battery life).

@vbelloir
Copy link

vbelloir commented Apr 27, 2023

It's very interesting. Will you try to do the same with infinitime? Or will you able to support a FW dev of infinitime?

@aykevl
Copy link

aykevl commented Apr 27, 2023

I have no plans to work on InfiniTime, sorry. But I'd be happy to answer any questions that people might have to get such low current consumption on their firmware.
I do plan to continue working on my own custom firmware, which is written in Go.

@JF002
Copy link
Collaborator Author

JF002 commented Apr 30, 2023

@vbelloir @aykevl Very interesting discussion! And 60-70µA is really amazing! I would really like to see if we could integrate those changes in InfiniTime to improve the battery life! I'll do it when I get a bit of free time ;-)

@JF002
Copy link
Collaborator Author

JF002 commented May 3, 2023

I did a few experiments. With a few minor changes to the code, I manage to reduce the current consumption down to ~130µA. It's waaaaay better than current consumption of the current release (~1.1mA), but still ~40µA more than @aykevl (I measure 97µA using watch.elf).

Not sure where those 40µA come from though...

@aykevl How can I ensure that the low-frequency oscillator is enabled and used?

EDIT : I think I found what's using those 40µA : the motion sensor! It looks like it uses a bit of current when it's initialized and configure to count steps!

@aykevl
Copy link

aykevl commented May 3, 2023

I did a few experiments. With a few minor changes to the code, I manage to reduce the current consumption down to ~130µA. It's waaaaay better than current consumption of the current release (~1.1mA), but still ~40µA more than @aykevl (I measure 97µA using watch.elf).

That's great!
I'd be curious to look at the diff, perhaps I have some more suggestions :)

EDIT : I think I found what's using those 40µA : the motion sensor! It looks like it uses a bit of current when it's initialized and configure to count steps!

Yeah, that's certainly possible. I haven't really investigated low power modes for the motion sensor, but I did find that after reset it enters a low power mode of negligible current consumption (less than 1µA IIRC).

@aykevl How can I ensure that the low-frequency oscillator is enabled and used?

Pretty sure it is, if you manage to get such low current consumption. But if you want to be sure, you can read the LFCLKSRC register (the SRC field should be set to Xtal).

@aykevl
Copy link

aykevl commented May 3, 2023

Actually now I think about it, my firmware doesn't touch the motion sensor at all. So if it was enabled in the previous firmware and wasn't reset or power-cycled, it might still be enabled. That might explain why you measure a higher current consumption than I do.
I don't know your setup, but perhaps you can try power cycling the watch after flashing my firmware?

@JF002
Copy link
Collaborator Author

JF002 commented May 7, 2023

I don't know your setup, but perhaps you can try power cycling the watch after flashing my firmware?

Since my devkit is connected to the debugger, I always power cycle it before measuring the current to ensure that the debug peripheral does not draw any additional current. I think my setup is not optimal for power measurement right now because of all the long wires and the breadboard. That's maybe why I measure a value slightly higher than yours?

I'd be curious to look at the diff, perhaps I have some more suggestions :)

I'll create a few PRs with the changes so we can review them and integrate them in InfiniTime :)
In the mean time, here's a patch with my changes :
power.zip

Note that those changes are pretty rough and disable most of the functionalities of the watch (button, ble, heart rate sensor, motion sensor,...).

Pretty sure it is, if you manage to get such low current consumption. But if you want to be sure, you can read the LFCLKSRC register (the SRC field should be set to Xtal).

I'll check, but I think I remember the SRC was effectively set to Xtal!

@JF002
Copy link
Collaborator Author

JF002 commented May 7, 2023

I've just created 4 PRs:

Together, those PRs decrease the power usage by a lot:

Use-case Fast Advertising Slow Advertising BLE disabled
InfiniTime 1.12 1.48mA 890µA 860µA
With those changes 580µA 200µA 180µA

This reduces the power usage by a ratio of 2.7 to 4.7, which is quite awesome!

The power usage in sleep mode could be further reduced by

  • Disabling the motion sensor (which disables the step counter) : -40µA
  • Disabling all the IRQ on the I/O (which disables the button, touch panel and charger detection) : -20µA

It was also a nice opportunity to check that the feature that disables BLE in InfiniTime actually works : the power consumption is the same when I disable BLE in the code (at compile time) and when I disable it in the settings (at run time)!

The theoretical battery life is increased from ~7 days to ~35days in sleep mode while slow advertising !

Thanks again to @aykevl for sharing their results!

@aykevl
Copy link

aykevl commented May 7, 2023

That's really amazing! I looked at the PRs and they look reasonable - but I don't know much about InfiniTime or FreeRTOS so can't say much about it.

Disabling all the IRQ on the I/O (which disables the button, touch panel and charger detection) : -20µA

Did you try polling the button instead of relying on interrupts?
I have found that polling the button (using the mechanism described here) actually reduces current consumption. Polling each 100ms or so only uses very little current (<10µA) in TinyGo, while leaving pin 15 high uses something like 34µA. As an experiment, you could set pin 15 low and see whether it makes any difference for you.

Also, I found that using the pin sense mechanism instead of using level triggered interrupts for the touch controller avoids the current consumption increase that is caused by edge triggered interrupts. You can find more details here:
https://github.com/aykevl/board/blob/58ffd00a37e218cae35973885c8edd13048b934a/board-pinetime.go#L151
Importantly, there seem to be a few chip errata that cause higher than expected current consumption as a result of interrupts, that can be entirely avoided using pin sense.
(You may not need the direct register accesses I have used, IIRC there's something in nrfx to use the pin sense mechanism in an easy way).

EDIT: one thing I haven't looked into yet is the various options in the touch controller. It might be possible to save some current consumption by changing some of the registers (calibration interval, for example).

@JF002
Copy link
Collaborator Author

JF002 commented May 8, 2023

That's really amazing! I looked at the PRs and they look reasonable - but I don't know much about InfiniTime or FreeRTOS so can't say much about it.

Thanks for the review, a second view is always interesting!

Did you try polling the button instead of relying on interrupts?

No, not yet, but it's probably something worth looking into! Thanks for the links!

one thing I haven't looked into yet is the various options in the touch controller. It might be possible to save some current consumption by changing some of the registers (calibration interval, for example).

The touch panel is veeery sensitive, and tends to wake InfiniTime up way too often, which causes unwanted actions in the UI and higher power usage. I'm very interested if you can find some way to tune it and improve the sensitivity and power usage!

@aykevl
Copy link

aykevl commented May 9, 2023

The touch panel is veeery sensitive, and tends to wake InfiniTime up way too often, which causes unwanted actions in the UI and higher power usage. I'm very interested if you can find some way to tune it and improve the sensitivity and power usage!

Oh, I see.
I can't promise anything, but if I continue this project and find some interesting settings I'll share them!

@vbelloir
Copy link

vbelloir commented May 9, 2023

Very happy to read theses messages!
With about 30 days lifespan, Pinetime will become usable as daily watch!

@toastom
Copy link

toastom commented Jun 24, 2023

I'd say it is already very capable of being used as a daily watch. And whenever someone comments on mine and I tell them that it typically lasts 4 pr sp days on a single charge, they've been shocked (oftentimes coming from Apple Watch users, but idk the battery life on those since I haven't owned one). 10 days is incredible!

@aykevl
Copy link

aykevl commented Jul 2, 2023

I suspect the accelerometer is not set to low power mode by default in InfiniTime. I have my TinyGo version of the BMA421/BMA425 driver almost working and once I get it to work fully, I'll post the results here.

The accelerometer should be able to go down to 14uA when set to sleep mode, without sleep mode it's much more. I did in fact manage to reach that low level (actually 11uA or so but that's probably a measuring error), but had trouble getting the step counter to work (I'm pretty sure it's possible, I just didn't figure it out yet).

@aykevl
Copy link

aykevl commented Jul 14, 2023

Ok, managed to get the step counter to work. It consumes 14µA when fully optimized, exactly as the datasheet states.

I also tested my driver with something similar to the configuration for InfiniTime (https://github.com/InfiniTimeOrg/InfiniTime/blob/main/src/drivers/Bma421.cpp) and found it uses far more power:

  • Changing the configuration to acc_odr=100Hz and acc_bwp=norm_avg4 (I think this is the configuration in InfiniTime?) bumped power consumption to 50µA.
  • Disabling power saving (in ACC_CONF) bumped power consumption to 99µA.
  • Enabling performance mode bumped power consumption to 151µA. Probably not the case for InfiniTime otherwise I don't think you'd be able to reach 180µA current consumption.

So this is probably something to investigate for InfiniTime. My driver is here: https://github.com/tinygo-org/drivers/pull/587/files. Especially important are the ACC_CONF and PWR_CONF registers.

Specifically, the datasheet says the following (page 31 of the PDF):
Screenshot_20230714_144441

So that's what I did, I set the ODR to 50Hz and acc_bwp to osr4_avg1 (no averaging). That may result in worse readings, but it still detects steps. My multimeter now claims the watch uses 79µA most of the time with step counting enabled and BLE disabled. The actual current consumption will be slightly higher because of the spikes the touchscreen (?) produces sometimes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed needs more info More information is needed needs more work This PR needs more work
Projects
None yet
Development

No branches or pull requests