Picture a battery-powered device out in a remote field. It reads a sensor a few times a day, occasionally gets a command from the cloud, and otherwise does nothing. Plenty of devices like this are programmed to wake every few seconds, ask "is there anything for me?", find nothing, and go back to waiting. Multiply that across a fleet (and months in the field), and you've spent a surprising amount of battery producing the answer: "nope, still nothing!".
That polling loop is one of the quietest ways to drain a battery, and much of
that waste is avoidable. The good news is the
Blues Notecard has a pin built for exactly
this: ATTN. Instead of waking on a timer to check, your host can wake only
when there's actually something to do. This article covers how this
functionality works and when to use it.
It's easy to assume the radio is where all your battery power goes. However, in a well-designed Notecard product, it usually isn't. Notecard itself idles at roughly 8–18 µA @ 5V depending on the model (Cellular, Satellite, LoRa, or WiFi), and the Low-Power Firmware Design guide is blunt about where the real draw lives: in most battery-powered designs, the host MCU, not Notecard, is the largest contributor to idle current.
So one of the most effective things you can do for battery life is keep the host
in true deep sleep as much as possible (e.g. STM32 STOP/STANDBY, ESP32 deep
sleep, Nordic nRF52 System OFF), drawing microamps or less. A polling host can
sleep between checks, but every poll is still a wake, a little I/O, and a return
to sleep. Those unnecessary wakeups drive up its average current even when
there's nothing to report.
The fix is to flip the relationship. Instead of the host repeatedly asking
Notecard for news, let Notecard tell the host when there's news to act on.
That's exactly what ATTN is for.
Notecard's Hardware "Tap on the Shoulder"
ATTN is a
dedicated output pin on Notecard
that you configure through the
card.attn API.
Its job is to physically signal your host that an event of interest happened, so
the host can sleep deeply the rest of the time. You can use it two ways:
- Interrupt-driven wake. Notecard fires the pin when an asynchronous event happens, and your host (already asleep in its own deep-sleep mode) wakes on that notification.
- Power-off sleep. Notecard drives the pin
LOWfor a set interval. If that pin is wired to the host's enable input, it cuts host power entirely until the pin goesHIGHagain.
These map to two card.attn mechanisms: arm mode and sleep mode. They solve
related problems very differently, and choosing between them is most of the
design decision.
The arm/fire Cycle
When you arm ATTN, Notecard drives the pin LOW, and when a monitored event
occurs (or an optional timeout elapses), the pin goes HIGH. That low-to-high
transition is your wake signal: wire ATTN to a host GPIO and configure the MCU
to wake on it. On some MCUs that's a rising-edge interrupt; on others it's a
level-based deep-sleep wake source (more on that below). Either way, your host
can stay asleep until Notecard has something worth waking up for.
The events you can arm on are what make this more interesting than a plain timer:
files— a Notefile has changed, usually in the form of an inbound Note (.qi) arriving from the cloud. This is your "the server has a command for you!" wake.motionandmotionchange— the onboard accelerometer has detected movement, or the motion state flipped between "moving" and "stopped."location— the GPS module got a position fix.env— an environment variable changed.connectedandsignal— Notecard connected to the network, or received an inbound signal.
Once the pin fires, it stays HIGH until you re-arm it. Your host code follows
a simple loop: wake up on the edge, do the work, re-arm the pin, then go back to
sleep. However, be sure to not skip that re-arm step! If you do, the pin never
fires again, which is the most common reason an interrupt-driven design works
only once.
An Implementation Walkthrough
These two mechanisms lead to two different paths: Path 1 keeps the host
powered and wakes it on an event (arm mode) while Path 2 cuts the host's
power entirely between wakes (sleep mode).
Path 1: Interrupt-Driven Wake (arm mode)
Use this when a device mostly sleeps but must react promptly to an event, like a
command arriving from the cloud. The host powers itself down into its own
deep-sleep mode and wakes on the ATTN change.
Wire ATTN to a host GPIO
Connect Notecard's ATTN pin to an interrupt-capable GPIO on your host. That's
the only connection this path needs as the host keeps its own power and manages
its own sleep mode.
Configure Notecard
Associate Notecard with your Notehub project and
set a sync mode. For inbound events, sync mode matters more than people expect.
In periodic mode, Notecard only pulls inbound data on its inbound schedule, so
a files interrupt on an inbound Note can't fire until the next inbound sync.
If you need a command to reach the device as fast as possible, use continuous
mode with sync set to true:
{
"req": "hub.set",
"product": "com.your-company.your-name:your_project",
"mode": "continuous",
"outbound": 30,
"sync": true
}That responsiveness isn't free: a continuously-connected radio draws far more than one that wakes on a schedule. So weigh the whole power budget, not just the host. Sleeping the host is a big win when the device is mostly idle, but if you switch to continuous mode purely to catch fast inbound commands, the added radio draw can outweigh what you saved by sleeping the host.
Arm the pin
Next, tell Notecard to watch a specified inbound Notefile and fire ATTN when
it changes:
{
"req": "card.attn",
"mode": "arm,files",
"files": ["data.qi"]
}FYI you can arm on more than one trigger at once. An asset tracker, for example, might want to wake on either an inbound command or physical movement:
{
"req": "card.attn",
"mode": "arm,files,motion",
"files": ["data.qi"]
}The arm mode also accepts an optional seconds timeout. If no monitored event
occurs within that window, the pin fires anyway, giving you a periodic fallback
so the host still checks in during a long quiet stretch.
Sleep, Wake, and Re-Arm on the Host
The host firmware side is relatively straightforward. Point the MCU's wake
source at the ATTN pin, then drop into deep sleep:
// NOTE: The deep-sleep entry itself is MCU-specific!
attachInterrupt(digitalPinToInterrupt(ATTN_PIN), onAttn, RISING);
// ... enter STOP / deep sleep here ...When ATTN fires, the host wakes, works out what happened, acts on it, and
re-arms before going back to sleep. Since you were watching a Notefile, that
"what happened" step is usually a
note.get request
against data.qi to read whatever the cloud sent. Then you send another
card.attn/mode:arm request and go back to sleep. That's the whole loop.
How you "drop into deep sleep" (and what you can assume when you wake) varies by host MCU. Two things change from chip to chip: how you arm the pin as a wake source, and whether your RAM survives the nap:
| Host MCU | Deepest practical mode | RAM retained on wake? | Arming ATTN as a wake source |
|---|---|---|---|
| STM32L4 (e.g. Blues Swan, Cygnet) | STOP, via LowPower.deepSleep() | Yes | Any EXTI-capable GPIO. LowPower.attachInterruptWakeup(pin, cb, RISING, DEEP_SLEEP_MODE). shutdown() goes lower but reboots. |
| ESP32 / ESP32-S3 | Deep sleep, via esp_deep_sleep_start() | No, but RTC memory persists | esp_sleep_enable_ext0_wakeup(gpio, 1) on an RTC-capable GPIO (level-triggered), or ext1 for several. |
| Nordic nRF52 | System OFF | No, but RAM sections are retainable | GPIO SENSE (a latched, level-based port event). System ON idle keeps all RAM. |
This ESP32 detail often trips people up: a plain attachInterrupt() does not
wake the chip from deep sleep. You have to register ATTN as an RTC wakeup
source before you sleep, and the pin has to be one of the RTC-capable GPIOs.
This works precisely because ATTN stays HIGH after it fires.
It's important to note that the "RAM retained" column determines how you write
your firmware to safely recover from sleep mode. On STM32 STOP, execution
resumes on the line right after your sleep call with your variables intact, so
the wake handler stays tiny. On ESP32 deep sleep or nRF52 System OFF,
a wake is almost like a reboot: setup() runs from the top and ordinary globals
are gone. You can still carry state across the gap, but you have to be
deliberate about it, using ESP32 RTC slow memory (RTC_NOINIT_ATTR), an nRF52
retained-RAM region,
an RTC backup register, or flash.
That storage doesn't have to be on the MCU, though! Notecard can hold it for
you if write the state to a local-only .dbx
database Notefile
with note.add, then read it back on the next boot with note.get. A .dbx
file never syncs, so it costs no cellular data. (The base64 payload helper in
Path 2 below does the same job, but it's tied to card.attn sleep mode, where
a LOW ATTN pin gates the host's power off, so it belongs there, not here where
the host sleeps itself.)
Path 2: Power-Off Sleep (sleep mode)
Use this path for the lowest possible power draw, or for a purely periodic
device. Instead of the host sleeping itself, Notecard drives the ATTN pin
LOW for a set interval and cuts the host's power outright, then restores it
when the interval ends.
This is the pattern from the Putting a Host to Sleep Between Sensor Readings sample app.
Wire ATTN to the host's EN pin
Connect ATTN to the host's enable (EN) pin instead of a GPIO. When Notecard
pulls ATTN LOW, the host loses power, and when it goes HIGH again the host
boots back up. If you're prototyping on a
Notecarrier F,
you can skip the jumper wire and set the FEATHER_EN DIP switch to the N_ATTN
position, which routes ATTN to the Feather host's enable pin for you.
Put the Host to Sleep
The host asks Notecard to power it down with a request like this:
{
"req": "card.attn",
"mode": "sleep",
"seconds": 3600
}Because the host loses power and reboots on wake, any state you care about has
to survive the outage. Notecard can hold it as a base64 payload (one option
among MCU flash and external storage), and the
note-arduino library wraps the encoding
in convenience helpers:
void loop()
{
globalState.cycles++;
// Hand our state to Notecard and power down for an hour.
NotePayloadDesc payload = {0};
NotePayloadAddSegment(&payload, globalSegmentID, &globalState, sizeof(globalState));
NotePayloadSaveAndSleep(&payload, 3600, NULL);
}On the next boot, the host gets its state back with
{"req":"card.attn","start":true} (or the NotePayloadRetrieveAfterSleep
helper) and picks up where it left off. Since every cycle is a cold start, that
restore runs on every wake.
Summary
Interrupt-driven wake through ATTN earns its keep when a device's real work is
sparse and hard to predict, like a control valve waiting on a command, a tracker
that only matters when it moves, or a sensor whose alarm line trips a Notecard
AUX GPIO the moment a threshold is crossed. For strictly periodic work, like an
hourly sensor reading, sleep mode's timer is simpler and lower-power.
To see the full pattern end to end, the Putting a Host to Sleep Between Sensor Readings sample has complete host firmware for the full sleep mode path, and the card.attn API reference documents every trigger available to you.
Grab a Blues Starter Kit, wire up that pin, and put a current meter on your host. The numbers tend to be convincing!
Happy hacking! 💙
Frequently Asked Questions
What is the Notecard ATTN pin?
ATTN is a dedicated output pin on Notecard that can physically signal a host
microcontroller when something happens, such as an inbound Note arriving, a
Notefile changing, motion being detected, or a timer elapsing. Wired to a host
GPIO or enable pin, it lets the host stay in deep sleep and wake only on a real
event instead of polling on a timer.
What events can wake a host through the ATTN pin?
Depending on the Notecard model, ATTN can fire on inbound Notes or Notefile
changes, accelerometer motion, a change in motion state, a GPS position fix, an
environment variable update, a successful cellular connection, an inbound
signal, an AUX GPIO change, USB power events, and an elapsed timer. Notecard for
LoRa supports a subset of these triggers.
What is the difference between card.attn arm mode and sleep mode?
In arm mode Notecard signals a host that manages its own sleep state, so
whether execution and RAM survive a wake depends on that state (STM32 STOP
keeps RAM; ESP32 deep sleep and nRF52 System OFF reset the host). In sleep
mode Notecard holds the ATTN pin LOW for a set time; if you've wired ATTN to
the host's enable or regulator input, that cuts host power entirely, so the host
reboots on wake and must restore any state it needs from MCU flash, RTC-backed
memory, or Notecard itself.
Do I need continuous mode to wake on an inbound Note?
For near-real-time inbound delivery, effectively yes. In periodic mode Notecard
only pulls inbound data on its inbound sync schedule, so a file-based ATTN
interrupt only fires after that sync. Continuous mode delivers inbound Notes
sooner at the cost of higher radio power, so the right choice depends on how
quickly you need to react.

