Electronics Design AU
ThreadnRF

How Do You Configure an nRF52840 as a Battery-Powered OpenThread Sleepy End Device?

Last updated 12 July 2026 · 8 min read

Direct Answer

A battery-powered nRF52840 Thread device is configured in the nRF Connect SDK as a Minimal Thread Device (MTD) with sleepy behaviour enabled — `CONFIG_OPENTHREAD_MTD=y` and `CONFIG_OPENTHREAD_MTD_SED=y` — which stops the device from maintaining a full routing table and lets it sleep between transmissions like a Zigbee end device, relying on its parent Router to buffer any pending downlink data. The core tuning parameter is the poll period (`CONFIG_OPENTHREAD_POLL_PERIOD`, or set dynamically with `otLinkSetPollPeriod()`): a short poll period gives low command-delivery latency at the cost of frequent radio wake events and higher average current draw, while a long poll period maximises battery life at the cost of slower response to any downlink command, and must always stay short enough relative to the parent's configured child timeout that the device doesn't get dropped from the network for appearing unresponsive.

Detailed Explanation

A Thread network built from Full Thread Devices alone assumes every device stays powered and reachable at all times — a reasonable assumption for a mains-powered Border Router or Router, but not for a coin-cell or battery-pack device that needs to last months or years in the field. OpenThread addresses this with the Sleepy End Device (SED) role, and Nordic's nRF Connect SDK (built on Zephyr) exposes the configuration for it through a specific set of Kconfig options and OpenThread API calls. This page covers the practical configuration and battery-life trade-offs specific to running an nRF52840 in this role; for Thread's device roles and network architecture generally, see what is Thread?

MTD vs FTD, and MED vs SED

OpenThread devices split first into two broad categories:

  • Full Thread Device (FTD) — maintains a complete routing table, can act as a Router or Router-Eligible End Device (REED), and stays continuously reachable. Appropriate for mains-powered devices: a Border Router, a mains-powered sensor hub, or any device expected to relay traffic for others.
  • Minimal Thread Device (MTD) — does not maintain a routing table and relies entirely on a parent Router for mesh connectivity, splitting further into two sub-roles:
    • Minimal End Device (MED) — radio stays on continuously; can receive data at any time, but never routes for others.
    • Sleepy End Device (SED) — radio powers down between transmissions and polls its parent periodically for any buffered data, the role a genuinely battery-powered device uses.

In the nRF Connect SDK, these map to Kconfig options: CONFIG_OPENTHREAD_FTD=y for a Full Thread Device, or CONFIG_OPENTHREAD_MTD=y plus CONFIG_OPENTHREAD_MTD_SED=y for a Sleepy End Device specifically (omitting the SED option with MTD alone configures a MED instead).

The Poll Period

The single most consequential tuning parameter for a SED is its poll period — how often the device wakes its radio and sends a MAC data-request frame to its parent, asking whether any data is waiting. This is conceptually identical to the end-device polling behaviour in Zigbee mesh networks, just implemented within Thread's own MAC layer. It can be set at build time via CONFIG_OPENTHREAD_POLL_PERIOD (in milliseconds) or adjusted dynamically at runtime with the OpenThread API call otLinkSetPollPeriod() — useful for a device that wants a short poll period briefly (for example, while awaiting a response to a CoAP request it just sent) and a much longer one the rest of the time to save power.

The trade-off runs in one direction: a shorter poll period means the parent's buffered data reaches the device sooner, at the cost of more frequent radio wake events and correspondingly higher average current draw; a longer poll period saves battery but increases worst-case downlink latency. There is no single correct value — the right poll period depends entirely on what the application actually needs to be responsive to, matched against its battery-life target.

Child Timeout and Re-Attachment Risk

A parent Router only keeps a Sleepy End Device in its child table for a configured child timeout period; if the SED doesn't poll (or otherwise communicate) within that window, the parent drops it and the device must go through the full Thread attach process again to rejoin — a meaningfully more expensive operation, in both time and radio energy, than a routine poll would have been. The poll period must be set with real margin below the child timeout, not simply shorter than it on paper — normal scheduling jitter, a missed radio window, or a brief RF disturbance can turn a poll period that's only marginally shorter than the timeout into an occasional unnecessary re-attach. otThreadSetChildTimeout() configures this value on the child side; check the current OpenThread documentation for your SDK's specific default rather than assuming a fixed number, since OpenThread's default child timeout has changed between releases.

Coordinated Sample Listening (CSL)

Traditional polling has an inherent inefficiency: the child doesn't know whether the parent actually has data waiting, so every poll happens regardless, and a shorter poll period to reduce latency directly increases the number of "empty" polls that find nothing waiting. Coordinated Sample Listening (CSL), defined in IEEE 802.15.4-2015 and adopted into Thread 1.2, addresses this by having the child and parent negotiate a specific scheduled listening window instead — the parent knows precisely when the child will next listen and can time a transmission to that window, reducing the child's total radio-on time for the same effective responsiveness compared to interval-based polling alone. Support for CSL depends on both the OpenThread stack version and the underlying radio driver's capability; check the release notes for your specific nRF Connect SDK version before assuming it's available, since this is an area that has evolved across SDK releases rather than a fixed, long-standing capability.

Radio and System Power States

Between polls, the nRF52840's overall system power state matters as much as the Thread-layer poll configuration — the radio being off is only part of the current budget. See nRF52 power optimisation for the System ON idle vs System OFF trade-offs, RAM retention configuration, and peripheral power management that determine the device's actual sleep current between Thread polls, and how to calculate battery life for an embedded device for combining a device's active/sleep current profile with its actual duty cycle into an estimated field battery life.

Practical Examples

A battery-powered door/window sensor uses a long poll period (on the order of tens of seconds to minutes, sized against the application's acceptable state-change reporting latency) for the great majority of its operating life, since a state change is an infrequent event the device itself initiates by waking and transmitting — it doesn't need to poll frequently just to receive commands it rarely gets.

A battery-powered smart lock temporarily shortens its poll period (or uses CSL where supported) immediately after sending a status update, to receive an acknowledgement or follow-up command with low latency, then returns to a much longer default poll period for the rest of its idle time — balancing the occasional need for responsive two-way interaction against a multi-month battery-life target.

Design Considerations

  • Set the poll period against the application's actual downlink-latency requirement, not an arbitrary default. A device that only needs to report its own state changes (and rarely receives commands) can tolerate a much longer poll period than one that needs to feel responsive to an incoming command.
  • Leave real margin between the poll period and the child timeout. Treat the child timeout as a hard limit that normal jitter and occasional missed windows must never approach, not a number to poll just barely faster than.
  • Budget system-level sleep current alongside the Thread poll configuration. The poll period controls how often the radio wakes, but the device's overall battery life depends equally on how efficiently it sleeps between those events — see nRF52 power optimisation for the System OFF and RAM-retention choices that determine that baseline.
  • Use dynamic poll-period adjustment for bursty interactions. Calling otLinkSetPollPeriod() to temporarily shorten the poll period around a known request/response exchange, then restoring a longer default afterward, gets low latency exactly when it's needed without paying for it continuously. Zeus Design's embedded team designs battery-optimised Thread and Zigbee products on Nordic nRF52/nRF53 silicon, including poll-period and system power-state tuning against a target field battery life.

Common Mistakes

  • Configuring a device as an FTD or MED by default and only later discovering the current draw is far too high for the battery budget. Confirm CONFIG_OPENTHREAD_MTD_SED is actually set before profiling current consumption — an easy oversight when starting from a sample project configured for a mains-powered role.
  • Setting the poll period only marginally shorter than the child timeout, so that any real-world scheduling jitter or a single missed poll window causes an unnecessary and comparatively expensive re-attach cycle.
  • Assuming CSL is available without checking the specific SDK and OpenThread version in use, then finding the build falls back to standard polling with a correspondingly different power profile than expected.
  • Profiling current consumption only at the Thread/application layer and ignoring system-level sleep configuration. A correctly tuned poll period doesn't help if the MCU isn't actually reaching its lowest available power state between polls — see the Common Mistakes in nRF52 power optimisation for the system-level side of this.
  • Leaving the poll period fixed at one value for the device's entire operating life when the application has genuinely different responsiveness needs at different times (for example, immediately after sending data versus long idle periods), missing an easy opportunity to shorten it only when actually needed.

Frequently Asked Questions

What is the difference between a Sleepy End Device (SED) and a Minimal End Device (MED) in OpenThread?
Both are Minimal Thread Device (MTD) roles that don't maintain a full routing table and rely on a parent Router for mesh forwarding, but they differ in radio duty cycle. A Minimal End Device (MED) keeps its radio receiver on continuously and can receive data at any time, the same as a Full Thread Device, but without doing any routing itself — appropriate for a mains-powered or otherwise power-unconstrained device that still doesn't need to route for others. A Sleepy End Device (SED) powers its radio down between transmissions and polls its parent periodically for any buffered data, trading response latency for substantially lower average current draw — the configuration a genuinely battery-powered device needs.
What happens if a Sleepy End Device doesn't poll before its child timeout expires?
The parent Router drops it from its child table, treating it as having left the network, and the device must go through the full attach process again — a more expensive operation in both time and energy than a routine poll would have been. This is why the poll period must be set with real margin below the child timeout (configurable via `otThreadSetChildTimeout()`, with an OpenThread-defined default in this area — check the current OpenThread documentation for the exact default in your SDK version, since it can change between releases), not just close enough that occasional radio or scheduling jitter risks a missed window and an unnecessary re-attach.
Does the nRF52840 support Coordinated Sample Listening (CSL) instead of traditional polling?
CSL is a Thread 1.2 / IEEE 802.15.4-2015 feature that lets a child and parent negotiate a specific scheduled listening window instead of the child sending unsolicited data-request polls at a fixed interval, reducing the radio's on-time further than classic polling for the same effective responsiveness. Nordic's nRF Connect SDK has added CSL support in its OpenThread integration in more recent SDK releases — check the current nRF Connect SDK release notes and OpenThread version bundled with your specific SDK release before assuming CSL is available, since support depends on both the OpenThread stack version and the underlying radio driver's capability.

References

Related Questions

Related Forum Discussions