Board Reference Matrix

This document is the ground truth for all CeresFlows firmware documentation. Every code example and warning in other chapters references the information here.

Before you write a single line of firmware, identify your board in the table below and understand its constraints. Ignoring these constraints is the most common cause of firmware failures.


Supported Boards

CeresFlows supports controllers in two tiers:

TierPurposeExamples
Main ControllerFull-featured, all commands, WiFiArduino UNO R4 WiFi, ESP32 WROOM-32
Satellite ControllerSubset of commands, cheaper, specializedESP8266 NodeMCU, Arduino Nano

[!NOTE] A “Satellite” controller is not a limitation of CeresFlows — it is a valid architectural choice. A cheap ESP8266 dedicated to a single humidity sensor is often the right engineering decision.


Board Overview

Arduino UNO R4 WiFiESP32 WROOM-32ESP8266 NodeMCUArduino Nano (Classic)
ChipRenesas RA4M1Espressif ESP32Espressif ESP8266ATmega328P
ArchitectureARM Cortex-M4Xtensa LX6 (dual-core)Xtensa LX106 (single-core)AVR 8-bit
Flash Memory256 KB4 MB4 MB32 KB ⚠️
RAM (SRAM)32 KB320 KB80 KB2 KB 🔴
Clock Speed48 MHz240 MHz80/160 MHz16 MHz
TierMainMainSatelliteSatellite
Firmware Status✅ Tested⚠️ Theoretical⚠️ Theoretical⚠️ Theoretical

[!CAUTION] The Arduino Nano has only 2 KB of RAM and 32 KB of Flash. A full-featured firmware with WiFi, ArduinoJson, and all bus commands will not fit. You must compile a stripped-down version. See the memory budget section below.


Transport Layer

How the board receives commands from the CeresFlows backend.

TransportArduino UNO R4 WiFiESP32 WROOM-32ESP8266 NodeMCUArduino Nano
UDP (WiFi)✅✅✅❌ No WiFi
MQTT (WiFi)✅✅✅❌ No WiFi
Serial (USB/UART)✅ Always active✅ Always active✅ Always active✅ Only option

[!IMPORTANT] Arduino Nano has no WiFi hardware. It can only receive commands via the USB Serial port. This means it cannot be used as a standalone networked controller — it must be connected directly to the computer running CeresFlows.

WiFi Library (Critical — Wrong Library = Compile Error)

BoardRequired #includeCommon Mistake
Arduino UNO R4 WiFi#include <WiFiS3.h>Using <WiFi.h> — will not compile
ESP32 WROOM-32#include <WiFi.h>Using <WiFiS3.h> or <ESP8266WiFi.h>
ESP8266 NodeMCU#include <ESP8266WiFi.h>Using <WiFi.h>
Arduino Nano❌ No WiFi library appliesN/A

[!WARNING] <WiFi.h> on the Arduino IDE resolves to different libraries depending on which board is selected in the Board Manager. Do not copy-paste WiFi code between board types without checking the include.


Hardware Capabilities

Analog Input

Arduino UNO R4 WiFiESP32 WROOM-32ESP8266 NodeMCUArduino Nano
Available pinsA0–A5 (6 pins)GPIO34, 35, 36, 39 (4 dedicated input-only pins)A0 (1 pin only)A0–A5 (6 pins)
ADC resolution10-bit (0–1023)12-bit (0–4095)10-bit (0–1023)10-bit (0–1023)
Max input voltage5V (AREF)3.3V1.0V 🔴5V (AREF)

[!CAUTION] ESP8266 has a single analog input (A0) with a maximum input voltage of 1.0V. Connecting a standard 0–5V sensor directly to A0 will damage the ESP8266. A voltage divider is required. Additionally, there is only one analog pin — you cannot read two analog sensors simultaneously on an ESP8266.

[!WARNING] ESP32 ADC returns 0–4095, not 0–1023. If your backend template or calibration is configured for a 10-bit range, readings will appear 4× higher than expected. Always configure your device template with the correct ADC resolution for your board.

Digital I/O

Arduino UNO R4 WiFiESP32 WROOM-32ESP8266 NodeMCUArduino Nano
Digital pinsD0–D13GPIO0–GPIO39 (not all usable)GPIO0–GPIO16D0–D13
PWM pinsD3, D5, D6, D9, D10, D11Most GPIO (ledc)GPIO4, GPIO5, GPIO12, GPIO13, GPIO14, GPIO15D3, D5, D6, D9, D10, D11
analogWrite()✅ Standard⚠️ Requires ESP32 Arduino core ≥ 3.x✅ Standard✅ Standard

[!WARNING] ESP32 does not support the standard analogWrite() function in older Arduino core versions (< 3.x). If you are using an older ESP32 board package, you must use ledcWrite() instead. Always check your installed ESP32 Arduino core version before using PWM commands.

I2C Bus

Arduino UNO R4 WiFiESP32 WROOM-32ESP8266 NodeMCUArduino Nano
Hardware I2C✅ 1×✅ 2× (configurable pins)✅ 1×✅ 1×
Default SDA pinA4 (pin 18)GPIO21GPIO4A4
Default SCL pinA5 (pin 19)GPIO22GPIO5A5
Library<Wire.h><Wire.h><Wire.h><Wire.h>

[!NOTE] The Wire.h library is consistent across all boards. However, the physical pin numbers differ. I2C_TRANSFER commands always specify the I2C device address — the SDA/SCL pins are fixed by the board and cannot be changed at runtime without modifying the firmware.

UART / Serial Bus

Arduino UNO R4 WiFiESP32 WROOM-32ESP8266 NodeMCUArduino Nano
Hardware UART ports1 (Serial1: pins 0/1)3 (Serial, Serial1, Serial2)1 (Serial: pins 1/3)1 (Serial: pins 0/1, shared with USB)
SoftwareSerial✅ Available⚠️ Unofficial support✅ Available✅ Available
UART + Modbus simultaneously⚠️ Only via SoftwareSerial (risk of conflict)✅ Yes — different hardware UARTs⚠️ Only via SoftwareSerial⚠️ Only via SoftwareSerial

[!WARNING] On all boards except ESP32, running UART_TRANSFER and MODBUS_RTU at the same time on different sensors requires two SoftwareSerial instances — which is unreliable above 9600 baud and can cause data corruption. The ESP32 is the only recommended board for simultaneous UART + Modbus use due to its multiple hardware UART ports.

SPI Bus

Arduino UNO R4 WiFiESP32 WROOM-32ESP8266 NodeMCUArduino Nano
Hardware SPI✅ (pins 11/12/13)✅ (GPIO23/19/18)✅ (GPIO13/12/14)✅ (pins 11/12/13)
Library<SPI.h><SPI.h><SPI.h><SPI.h>
CS pinManual (any digital pin)Manual (any digital pin)Manual (any digital pin)Manual (any digital pin)

System Functions

Critical functions that differ between chips. Getting these wrong causes silent failures or compiler errors.

FunctionArduino UNO R4 WiFi (RA4M1)ESP32ESP8266Arduino Nano (ATmega328P)
Software resetNVIC_SystemReset()esp_restart()ESP.restart()wdt_enable(WDTO_15MS); while(1);
Free memoryStack/heap pointer arithmeticESP.getFreeHeap()ESP.getFreeHeap()Stack/heap pointer arithmetic
EEPROM writeEEPROM.write(addr, val)Preferences library (NVS) or EEPROM.begin(N)EEPROM.begin(N); EEPROM.write(...)EEPROM.write(addr, val)
EEPROM readEEPROM.read(addr)Preferences library or EEPROM.read() after begin(N)EEPROM.read(addr) after begin(N)EEPROM.read(addr)

[!CAUTION] ESP32 does not have a traditional EEPROM. The EEPROM.h library on ESP32 emulates EEPROM in flash. You must call EEPROM.begin(size) before any read/write operations, and EEPROM.commit() after writes — otherwise data is lost on reboot. Forgetting EEPROM.commit() is a very common bug.

[!CAUTION] ESP8266 also requires EEPROM.begin(N) where N is the number of bytes you intend to use. Without this call, all reads return 0xFF and writes are silently ignored.


Interrupt-Capable Pins (for PULSE_COUNT)

The PULSE_COUNT command uses hardware interrupts. Not all pins support interrupts.

BoardInterrupt-capable pins
Arduino UNO R4 WiFiD2, D3 (primary) + others via attachInterrupt
ESP32 WROOM-32Any GPIO (except input-only pins in some configurations)
ESP8266 NodeMCUGPIO0–GPIO15 (GPIO16 does NOT support interrupts)
Arduino NanoD2, D3 only

[!WARNING] On Arduino Nano, only pins D2 and D3 support hardware interrupts. If you connect a flow meter or pulse sensor to any other pin and use PULSE_COUNT, no pulses will be counted and the command will always return 0.


Memory Budget (Arduino Nano)

The Nano’s 2 KB RAM and 32 KB Flash impose hard limits. Here is what fits:

FeatureFlash cost (approx.)RAM cost (approx.)Include?
Core firmware loop~6 KB~200 B✅ Always
ArduinoJson (StaticDoc 128B)~8 KB128 B static✅ Yes — use StaticJsonDocument only
ArduinoJson (DynamicDoc 512B)~8 KB512 B heap❌ No — heap too small
Wire.h (I2C)~2 KB~50 B✅ If needed
SPI.h~1 KB~30 B✅ If needed
SoftwareSerial~2 KB~64 B⚠️ One instance max
WiFi* any library+40–80 KB+20–50 KB❌ Impossible — no WiFi hardware

[!CAUTION] On Arduino Nano, never use DynamicJsonDocument. Its heap allocation will collide with the stack. Use only StaticJsonDocument<N> with N ≤ 128. For complex commands like I2C_TRANSFER or MODBUS_RTU that require parsing multi-field JSON, the Nano may not have sufficient RAM — test carefully.


Command Compatibility Summary

CommandArduino UNO R4 WiFiESP32 WROOM-32ESP8266 NodeMCUArduino Nano
PING✅✅✅✅
STATUS✅✅✅✅
INFO✅✅✅✅
RESET✅✅✅✅ (watchdog)
HYDROPONICS_DISCOVERY✅✅✅❌ No WiFi
ANALOG✅ (6 pins)✅ (4 pins, 12-bit)⚠️ (1 pin, max 1V)✅ (6 pins)
DIGITAL_READ✅✅✅✅
DIGITAL_WRITE / RELAY_SET✅✅✅✅
PWM_WRITE✅⚠️ (core ≥ 3.x)✅✅
SERVO_WRITE✅✅⚠️ Limited✅
DHT_READ✅✅✅✅
ONEWIRE_READ_TEMP✅✅✅✅
ONEWIRE_SCAN✅✅✅✅
ULTRASONIC_TRIG_ECHO✅✅✅✅
HX711_READ✅✅✅✅
PULSE_COUNT✅✅✅ (not GPIO16)⚠️ D2/D3 only
I2C_TRANSFER✅✅✅⚠️ RAM limited
UART_TRANSFER✅✅✅⚠️ Shares USB port
MODBUS_RTU✅✅✅⚠️ RAM limited
SPI_TRANSFER✅✅✅⚠️ RAM limited
TTL Watchdog✅✅✅✅
EEPROM persistence✅⚠️ EEPROM.begin(N) + .commit()⚠️ EEPROM.begin(N) + .commit()✅

This document is the reference baseline for all CeresFlows firmware documentation. All board-specific warnings in other chapters derive from the constraints listed here.