Rate this page
- ★★
- ★★
- ★★
- ★★
- ★★
Can we improve this page? Send us feedbackRate this page
- ★★
- ★★
- ★★
- ★★
- ★★
There are several situations where you may need your embedded application to be alerted the instant the Notecard receives new information. This guide is designed to aid you in creating an interactive example to demonstrate how to leverage this feature of the Notecard. The goal of this example is to solidify and confirm your understanding of the Notecard's attention interrupt and its behavior.
At a high-level, your program will:
ATTN
interrupt.During the course of this example, you will learn:
Although this guide uses an Adafruit Huzzah32 microcontroller and a Notecarrier-AF to show how the Notecard's attention pin works, you can use any combination of ESP32 microcontroller and Notecarrier to complete this guide. Just note you may need to map the instructions to work with your specific hardware configuration.
You can view or download the full source of this project from GitHub.
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 has been manually reset.
The latching behavior enables you to leverage the interrupt in myriad ways:
To learn more about configuring the Notecard ATTN
interrupts, read the
Handling Notecard Interrupts
section of the Notecard guide.
Ensure you have access to the following hardware:
The attention, or ATTN
, pin is exposed on the Notecarrier-AF, 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 for it be used (as described
above), and then you must wire it the corresponding pin.
ATTN
pin of the Notecard to an interrupt capable GPIO
pin on the Huzzah32. Place the male/male jumper wire between the ATTN
pin on the
Notecarrier-AF 13-Pin Header
and pin 5
on the
Adafruit Feather 24-Pin Breakout Header.That's it! To complete the project, you will use the Huzzah32's built-in LED,
LED_BUILTIN
, and the Notecarrier-AF's built-in button, B0
.
The female headers pictured above are non-standard hardware. In order to connect
your jumper wire between ATTN
and 5
, either soldering or alligator clips
will be required.
First things first, you will need to include the Notecard library.
#include <Notecard.h>
Next, you will want to create some defines to make things easier. Take care
to note B0
and D5
. The pin labels on the Huzzah32 and Notecarrier-AF do not
line up 100%, and these defines make it easier to identify the interrupt pins to
which you will be programmatically attaching.
#ifdef B0 #undef B0 #endif #define B0 21 #ifdef D5 #undef D5 #endif #define D5 14 #define LOOP_HZ 20 #define LOOP_DELAY_MS (1000/LOOP_HZ) #define serialDebug Serial
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.
Notecard notecard;
In order to optimize the interrupt execution
(explained here), 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.
volatile bool notecard_request_to_arm = false;
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.
void IRAM_ATTR armInterrupt() { // Take no action when already armed if (digitalRead(D5)) { notecard_request_to_arm = true; } }
Declare an interrupt to handle the Notecard ATTN
pin interrupt. Use the
following code to set the Huzzah32's built-in LED to follow the state of the
ATTN
pin:
void IRAM_ATTR attention() { // Visualize the attention pin state digitalWrite(LED_BUILTIN, digitalRead(D5)); }
First, you will start by enabling debug messages for the application.
// Initialize Debug Output serialDebug.begin(115200); while (!serialDebug) { ; // wait for serial port to connect. Needed for native USB }
Next, you configure and initialize the Notecard.
// Initialize Notecard
notecard.begin();
notecard.setDebugOutputStream(serialDebug);
You have placed a jumper wire betwen pin 5
and ATTN
. To register the
attention
ISR to activity on pin 5
, you must use the attachInterrupt
API.
// Attach Notecard Interrupt pinMode(D5, INPUT); attachInterrupt(digitalPinToInterrupt(D5), attention, RISING);
Button B0
on the Notecarrier-AF connects through the Feather socket to pin
21
of the Huzzah32. To register the armInterrupt
ISR to a button press
event, you must use the attachInterrupt
API.
// Attach Button Interrupt pinMode(B0, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(B0), armInterrupt, RISING);
The Notecard can be powered seperately, and operates independently, of the
Huzzah32. As a result, the Huzzah32 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.
// Debug LED (mirrors `ATTN`) pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, digitalRead(D5));
Due the fact most of the programs logic is executed through event driven code,
the loop
function is dedicated to servicing the button press event.
When signalled by the interrupt driven flag, notecard_request_to_arm
, the MCU
will construct a JSON request and send it to the Notecard. If the message is
sent successfully, then the Huzzah32's built-in LED will be updated to reflect
the state of the armed interrupt. Finally, loop
will delay at the frequency
specified in LOOP_HZ
.
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 { notecard.logDebug("ERROR: Failed to arm ATTN interrupt!\n"); } } } // Loop at `LOOP_HZ` Hz delay(LOOP_DELAY_MS); }
All GPIO pins on the ESP32 are interrupt capable. 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.
The Notecarrier-AF built-in button B0
is denoted by the orange line (bottom),
and the 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
.
What exactly happens after the button press? Here is the break down:
ATTN
pin.ATTN
pin by pulling the line 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.
ESP32 Interrupt Service Routines should be decorated with IRAM_ATTR
(1).
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 the Flash. 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.
Example:
void IRAM_ATTR attention() { // Visualize the interrupt digitalWrite(LED_BUILTIN, HIGH); }
Due to a shortcoming 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.