|
| 1 | +--- |
| 2 | +title: "Low Power" |
| 3 | +linkTitle: "Low Power" |
| 4 | +type: "docs" |
| 5 | +weight: 35 |
| 6 | +description: > |
| 7 | + How to consume less power on microcontrollers |
| 8 | +--- |
| 9 | + |
| 10 | +Microcontrollers are usually rather non-demanding when it comes to power consumption. |
| 11 | +Couple hudreds mW is the most you may expect a hobby project would use. |
| 12 | + |
| 13 | +Sometimes, even that is not low enough. |
| 14 | +Power your project from a battery, and it'd benefit greatly from consuming less. |
| 15 | + |
| 16 | +Common scenario for such projects is sleeping most of the time, and only rarely briefly wake up to query sensors and execute actions. |
| 17 | +The main caveat here is if not configured properly, microcontroller and peripherals continue to consume power while your program "sleeps". |
| 18 | + |
| 19 | +The standard way to pause execution in Go is to use `time.Sleep()` function that is available in TinyGo too. Depending on the chip and effort put into its support, the efficiency of this function may vary. The only thing certain: this is _not worse_ than busy looping until a certain time has passed. |
| 20 | +Still, with such high-level function as `time.Sleep()` it is not always possible to disable everything that consumes power as the decisions may depend on the application, presense of peripherals and the board used. |
| 21 | + |
| 22 | +Most microcontrollers have one or more "low power" modes, also known as "deep sleep" and, sometimes, "dormant". |
| 23 | +In such modes microcontroller may consume as low as milli- or even micro-Watts. |
| 24 | +TinyGo gives you low level access to hardware to try and make most of it. |
| 25 | + |
| 26 | +## Implementations |
| 27 | + |
| 28 | +Manufacturers implement different modes, depending of capabilites of their products and name these modes differently too. |
| 29 | +Hence no naming consistency across microcontrollers, unfortunately. |
| 30 | + |
| 31 | +Always consult "Power consumption" part of a respective datasheet to understand capabilities of your hardware. |
| 32 | +When reading datasheets, keep in mind peripherals that draw power too. These include \[power\] LEDs, various sensors or co-processors usually present on development boards. |
| 33 | + |
| 34 | +Capabilities of different chips: |
| 35 | +- Some very good chips (like the nRF series) can go to a very low power state (just a few µA) with RAM retention and waking up from a low-power RTC. |
| 36 | +- Some limited chips (like the esp32) can't really "sleep" with low power -- they can disable the core and memory and reset after a predefined time losing state stored in memory. |
| 37 | +- Other chips need to use a special feature to go into deep sleep mode. |
| 38 | + |
| 39 | +Especially the distinction between waking up with or without RAM is important, because it greatly affects how you write software. |
| 40 | + |
| 41 | +The common way to wake up from deep sleep is to use [interrupts](compiler-internals/interrupts), such as timer, real-time-clock or an interrupt on a pin change. |
| 42 | + |
| 43 | +### RP2040 |
| 44 | + |
| 45 | +Minimal achievable power consumption is 0.18mA in "Dormant" and 0.39mA in "Sleep" modes. |
| 46 | +See [RP2040 datasheet](https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf#page=621), section 5.7 Power Consumption. |
| 47 | + |
| 48 | +### nRF Family |
| 49 | + |
| 50 | +[nRF series chips](https://www.nordicsemi.com/Products) are exceptionally efficient and is recommended choice for low-power projects. |
| 51 | +Even with [BLE broadcasting enabled](https://devzone.nordicsemi.com/power/w/opp/2/online-power-profiler-for-bluetooth-le) it can use less power than RP2040 in its lowest power state! |
| 52 | + |
| 53 | +Minimal achievable power consumption is in the area of µA. |
| 54 | + |
| 55 | +TinyGo implements standard `time.Sleep()` very efficiently for nRF chips so you can just use it and have great results. |
| 56 | +The only thing you may want to tweak is to disable the UART with help of `-serial=none` flag to go even lower than default. |
| 57 | + |
| 58 | +## The Way to Low Power |
| 59 | + |
| 60 | +> Attached [debugger](../guides/debugging) usually blocks the low power state in chip. |
| 61 | +> The best way to measure when using a debugger is to flash the code, do a power cycle, and then measure. |
| 62 | +
|
| 63 | +> The changes discussed in this paragraph shall be made in TinyGo and not in your application code. |
| 64 | +> These are `runtime` and/or `machine` packages, in files related to your target. |
| 65 | +
|
| 66 | +Following steps shall help you achieve low power consumption: |
| 67 | + |
| 68 | +- Put a `for { arm.Asm("wfi") }` loop before anything else is initialized (at the beginning of [Reset_Handler](https://github.com/tinygo-org/tinygo/search?q=%22export+Reset_Handler%22)). |
| 69 | + _`wfi` pauses the processor, puts it in "wait for interrupt" state. And when inserted before any initialisation, this ensures no internal subsystem is running consuming power._ |
| 70 | +- Measure the current, this should be the lowest consumption as advertised for the chip. |
| 71 | +- If it is higher than that, investigate why (it could be a power LED, regulator, some clock that's enabled by the bootloader, maybe other things). |
| 72 | + _Usually this ranges somewhere between 1µA and 100µA, depending on the low-power capabilities of the chip. Don't continue until you really do reach the lowest possible power consumption._ |
| 73 | +- Slowly move the loop to later in the code, until you move it into the main function. |
| 74 | +- There are probably things initialized by default that consume current, like UART, PLLs, different clocks. Disable them before continuing, or investigate why they consume power. |
0 commit comments