---
title: Notecard Attention Guide
description: Configuring the Notecard attention pin on the Blues Swan and Notecarrier F.
source_url: https://dev.blues.io/guides-and-tutorials/notecard-guides/attention-pin-guide/
canonical_url: https://dev.blues.io/guides-and-tutorials/notecard-guides/attention-pin-guide/
markdown_url: https://dev.blues.io/guides-and-tutorials/notecard-guides/attention-pin-guide.md
---

# Attention Pin (`ATTN`) Guide

There are several situations where you may need your embedded application to be alerted the instant Notecard receives new information. This guide is designed to demonstrate how to leverage Notecard's attention interrupt.

At a high-level, your program will:

1. Respond to a button click.
2. Author a request to Notecard; instructing it to fire after a few seconds.
3. Respond to interrupts and update an LED to visualize the behavior of the `ATTN` interrupt.

During the course of this example, you will learn:

1. How to configure Notecard's attention interrupt.
2. How to use the Blues Swan's onboard button and LED from your program.
3. How to write and handle an interrupt service routine (ISR).

> **Note:**
>
> Although this guide uses a [Blues Swan microcontroller](https://shop.blues.com/collections/feather-mcu/products/swan?utm_source=dev-blues\&utm_medium=web\&utm_campaign=store-link) and a [Notecarrier F](https://shop.blues.com/products/notecarrier-f?utm_source=dev-blues\&utm_medium=web\&utm_campaign=store-link) to show how Notecard's attention pin works, you can use any combination of STM32 or ESP32 microcontroller and Notecarrier to complete this guide. Just note you may need to map the instructions to work with your specific hardware configuration.

## Notecard Interrupt

Originally designed for low-power use cases, the Notecard attention interrupt is a **latching interrupt**. Meaning, once it fires, it stays in the fired position until it is manually reset.

The latching behavior enables you to leverage the interrupt in myriad ways:

1. Notecard may idle or delay while waiting for communication from a cellular tower, while simultaneously disabling the host microcontroller with the enable pin.
2. When used in a powered setting and connected to an interrupt capable pin on the host MCU, the host MCU can receive and respond to network communication as quickly as possible.
3. The host MCU may optimize polling, by querying the logic value of the pin, as opposed to transacting with Notecard to look for new data.

> To learn more about configuring the Notecard `ATTN` interrupts, read the [Handling Notecard Interrupts](https://dev.blues.io/notecard/notecard-walkthrough/inbound-requests-and-shared-data.md#handling-notecard-interrupts) section of the Notecard guide.

## Hardware Setup

Ensure you have access to the following hardware:

- [Blues Notecard](https://shop.blues.com/collections/notecard?utm_source=dev-blues\&utm_medium=web\&utm_campaign=store-link)
- [Blues Swan STM32 host microcontroller](https://shop.blues.com/collections/feather-mcu/products/swan?utm_source=dev-blues\&utm_medium=web\&utm_campaign=store-link)
- [Notecarrier F](https://shop.blues.com/products/notecarrier-f?utm_source=dev-blues\&utm_medium=web\&utm_campaign=store-link)
- Male/male jumper wire
- Micro USB cable
- Momentary tactile push button (built-in to Blues Swan)
- LED (built-in to Blues Swan)

> The [Blues Starter Kit for Cell+WiFi](https://shop.blues.com/products/blues-global-starter-kit?utm_source=dev-blues\&utm_medium=web\&utm_campaign=store-link) includes a Notecard Cell+WiFi, Swan, and Notecarrier F.

### Wiring

The attention, or `ATTN`, pin is exposed on the Notecarrier F, however it is not wired to any pins that are exposed from the Feather socket. To utilize the `ATTN` pin you must first decide how you would like it to be used ([as described above](#notecard-interrupt)), and then you must wire it to the corresponding pin.

You'll need to connect the `N_ATTN` pin of Notecard to an interrupt capable GPIO pin on the Swan. Place the male/male jumper wire between the `N_ATTN` and `F_D5` [pins on the Notecarrier F](https://dev.blues.io/datasheets/notecarrier-datasheet/notecarrier-f-v1-3.md#header-descriptions).

![Male/male jumper wire placement](https://dev.blues.io/images/guides/notecard-guides/attn-wiring-swan.jpg?v=de308d4d)

That's it! To complete the project, you will use the Swan's built-in LED, `LED_BUILTIN`, and button, `USER_BTN`.

## Firmware Breakdown

The following code sample demonstrates an Arduino implementation using the [note-arduino SDK](https://dev.blues.io/tools-and-sdks/firmware-libraries/arduino-library.md). However, you can implement the same workflow using any of the other [Notecard SDKs](https://dev.blues.io/tools-and-sdks/firmware-libraries.md).

> **Tip:**
>
> **Let AI write your firmware.** Blues Expert MCP connects your AI coding assistant (Claude Code, GitHub Copilot, Cursor) directly to our API docs, providing live request validation and firmware best practices for Arduino, C, Zephyr, and Python. [Install the Blues Expert MCP →](https://dev.blues.io/tools-and-sdks/generative-ai-tools/blues-expert-mcp.md)

> The full Arduino sketch is available [here on GitHub](https://gist.github.com/rdlauer/4877247536c7add499f1960119bd8e14).

### Definitions and Declarations

1. First things first, you'll need to include the Notecard library.

   ```cpp
   #include <Notecard.h>
   ```

2. Next, you'll want to create a define for `IRAM_ATTR` to add compatibility with STM32 hosts. On ESP32, `IRAM_ATTR` tells the function to [use internal RAM](#esp32-interrupt-handling).

   ```cpp
   #ifndef IRAM_ATTR
   #define IRAM_ATTR
   #endif

   #define usbSerial Serial
   ```

3. You will need to instantiate the Notecard class globally, which enables you to configure and interact with your Notecard device in both the `setup` and `loop` functions.

   ```cpp
   Notecard notecard;
   ```

4. In order to optimize the interrupt execution, you need to declare a `volatile bool` flag. This allows the interrupt and main loop to share state, which enables the interrupt to offload processing onto the main loop.

   ```cpp
   volatile bool notecard_request_to_arm = false;
   ```

5. Next, declare an interrupt to handle the button press event. This ISR will notify the main loop of the request by setting the flag to `true`, after checking if the `ATTN` pin is already armed.

   ```cpp
   void IRAM_ATTR armInterrupt() {
      // Take no action when already armed
      if (digitalRead(D5)) {
         notecard_request_to_arm = true;
         usbSerial.println("INFO: ATTN interrupt armed!");
      }
   }
   ```

6. Declare an interrupt to handle the Notecard's `ATTN` pin interrupt. Use the following code to set the Swan's built-in LED to follow the state of the `ATTN` pin:

   ```cpp
   void IRAM_ATTR attention() {
      // Visualize the attention pin state
      digitalWrite(LED_BUILTIN, digitalRead(D5));
   }
   ```

### `setup` Function

1. In `setup`, you will start by enabling debug messages for the application.

   ```cpp
   delay(1000);
   usbSerial.begin(115200);
   notecard.setDebugOutputStream(usbSerial);
   ```

2. Next, you configure and initialize the Notecard.

   ```cpp
   // Initialize Notecard
   notecard.begin();
   ```

3. To register the `attention` ISR to activity on pin `5`, you must use the `attachInterrupt` API.

   ```cpp
   // Attach Notecard Interrupt
   pinMode(D5, INPUT);
   attachInterrupt(digitalPinToInterrupt(D5), attention, RISING);
   ```

   The ISR listens for the `RISING` edge because of how `card.attn` drives the pin: arming the interrupt pulls `ATTN` (and therefore `D5`) `LOW`, and when the interrupt *fires* — after an event occurs or the `seconds` timeout elapses — the pin goes `HIGH`. That `LOW`-to-`HIGH` transition is the rising edge you want to detect.

4. To register the `armInterrupt` ISR to a button press event on the Swan, you must use the `attachInterrupt` API.

   ```cpp
   // Attach Button Interrupt
   pinMode(USER_BTN, INPUT_PULLUP);
   attachInterrupt(digitalPinToInterrupt(USER_BTN), armInterrupt, RISING);
   ```

5. Notecard can be powered separately, and operates independently of the Swan. As a result, the Swan's built-in LED and the Notecard's `ATTN` pin can get out of sync. To ensure alignment, you must initialize the state of the LED to match the state of the `ATTN` pin.

   ```cpp
   // Debug LED (mirrors `ATTN`)
   pinMode(LED_BUILTIN, OUTPUT);
   digitalWrite(LED_BUILTIN, digitalRead(D5));
   ```

### `loop` Function

Due to the fact that most of the program's logic is executed through event-driven code, the `loop` function is dedicated to servicing the button press event.

1. When signalled by the interrupt driven flag, `notecard_request_to_arm`, the MCU will construct a JSON request and send it to Notecard. If the message is sent successfully, then the Swan's built-in LED will be updated to reflect the state of the armed interrupt.

   ```cpp
   void loop() {
      // Process arming request
      if (notecard_request_to_arm) {
         notecard_request_to_arm = false;

         // Arm ATTN Interrupt
         J *req = NoteNewRequest("card.attn");
         if (req) {
            JAddStringToObject(req, "mode", "arm");
            JAddNumberToObject(req, "seconds", 3);
            if (notecard.sendRequest(req)) {
               // Visualize the attention pin state
               digitalWrite(LED_BUILTIN, digitalRead(D5));
            } else {
               usbSerial.println("ERROR: Failed to arm ATTN interrupt!");
            }
         }
      }

      delay(20);
   }
   ```

### Results

With your firmware uploaded to the Swan, when you press `USER_BTN` the following should occur:

1. **Button Interrupt Triggered:** The `USER_BTN` press triggers the `armInterrupt()` function, which checks if the `D5` pin is `HIGH`. If it is, it sets the flag `notecard_request_to_arm`.
2. **Notecard Request Sent:** In the main `loop`, once the flag is set, a `card.attn` request is created with `mode: "arm"` and `seconds: 3`. When this request is sent, Notecard is instructed to "arm" its attention behavior for 3 seconds.
3. **LED Mirrors D5's State:** The LED is programmed to mirror the state of the `D5` pin via the `attention()` interrupt service routine and the update in the loop. If Notecard, as a result of the `card.attn` command, pulls `D5` `LOW` for 3 seconds, then the LED (which reads `D5`'s state) will **turn off** for that duration.

Using the same techniques shown in this guide, you can use Notecard to interrupt your host when it receives environment variable updates, when it receives an inbound Note, when it detects motion, [and more](https://dev.blues.io/api-reference/notecard-api/card-requests/latest.md#card-attn).

## ESP32 Interrupt Handling

If you are using an ESP32-based host MCU, it's important to note that all GPIO pins on the ESP32 are [interrupt capable](https://lastminuteengineers.com/handling-esp32-gpio-interrupts-tutorial/). This is an amazing feature of the ESP32, and is not true of most microcontrollers. However, the ESP32's hardware interrupts require special handling, especially when using the Arduino board support package. Those details, and more, are discussed in this section.

![Attention Pin Behavior](https://dev.blues.io/images/guides/notecard-guides/attn-pin-behavior.png?v=fee7c926)

An arbitrary momentary push button (`B0`) is denoted by the orange line (bottom), and Notecard's `ATTN` interrupt is shown in white (top). As illustrated by the yellow marker, the rising edge of the button is the trigger. Once the button is released, the program generates and sends a request to arm the attention interrupt (depicted by the red area). Lastly, the Notecard arms the `ATTN` interrupt, observed as the white line being pulled `LOW`.

In the timing graph, you can see it takes \~80ms to service the request to arm. While 80ms may seem fast, it is quite slow for an MCU, and is precisely why the operation needs to be moved out of the interrupt and into the main loop.

> **Note:**
>
> ESP32 Interrupt Service Routines should be decorated with [IRAM\_ATTR](https://lastminuteengineers.com/handling-esp32-gpio-interrupts-tutorial/).
>
> **What is IRAM\_ATTR?**
>
> By flagging a piece of code with the `IRAM_ATTR` attribute we are declaring that the compiled code will be placed in the Internal RAM (IRAM) of the ESP32. Otherwise the code is placed in flash storage and flash on the ESP32 is much slower than internal RAM.
>
> If the code we want to run is an interrupt service routine (ISR), we generally want to execute it as quickly as possible. If we had to "wait" for an ISR to load from flash, things would go horribly wrong.

> **Warning:**
>
> Due to a [shortcoming](https://github.com/espressif/arduino-esp32/issues/1111#issuecomment-743912255) in Espressif System's `esp32` Arduino Board Package, all interrupts must be configured to fire on the same edge. To successfully observe the Notecard attention pin interrupt, you **must** monitor the `RISING` edge. As a result, any other interrupts in your project will also need to fire on the `RISING` edge.

## Additional Resources

- [Notecard Datasheet](https://dev.blues.io/datasheets/notecard-datasheet.md)
- [Notecarrier F Datasheet](https://dev.blues.io/datasheets/notecarrier-datasheet/notecarrier-f-v1-3.md)
- [Blues Swan Datasheet](https://dev.blues.io/datasheets/swan-datasheet/swan-v3-0.md)
- [Handling Notecard Interrupts](https://dev.blues.io/notecard/notecard-walkthrough/inbound-requests-and-shared-data.md#handling-notecard-interrupts)
