One Firmware for all ESP32 Variants: Solving Pin Mapping Pain
For my embedded project, I needed NFC card functionality for WiFi onboarding and user interactions. When integrating NFC functionality into ESP32 projects, pin mapping became a major pain point as I was working with different ESP32 boards.
Adafruit's arduino library example sets up the NFC reader in following manner:
#include <Wire.h>
// Using the SPI breakout, define the pins for SPI communication.
#define PN532_SCK (2)
#define PN532_MOSI (3)
#define PN532_SS (4)
#define PN532_MISO (5)
Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS);
These pins are placeholders and they would vary for each ESP32 variant and I had several: ESP-WROOM-32, ESP32-C3 Super Mini, S3, XIAO ESP32S3
I tested the reader across all these variants, different modes: SPI,
I2C, wiring and reading different NFC cards.
First challenge was to figure out the mapping of pins. I found that
espressif's arduino support is the best resource for it. For each
board the file pins_arduino.h gives us the right pins. For the
ESP32-C3 Super Mini board, the above example NFC reader code would
become:
#include <Wire.h>
#define PN532_SCK (4)
#define PN532_MOSI (6)
#define PN532_SS (7)
#define PN532_MISO (5)
Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS);
But as I iterated through these ESP32 variants it became quite a pain adjusting those pins in the firmware and flashing it. Eventually I realized what would simplify this: I could have a single firmware that will work with everything:
#include <Wire.h>
Adafruit_PN532 nfc(SCK, MISO, MOSI, SS);
These pins, SCK, MISO are just like another constant:
LED_BUILTIN, each Arduino board that doesn't use default pin 13,
defines it in their pins_arduino.h header. Similarly all the
variants have their own respective pins_arduino.h file with right
pins. As I select the board inside Arduino IDE, these variables are
always available. Further this pattern isn't limited to NFC readers,
all the SPI peripheral using those pins would work.