Skip to content

Adding New Settings

Relevant source files

This guide explains how to add new persistent settings to the Pibot CNC Pendant firmware using the X-macro based settings system. Settings are stored in NVS (Non-Volatile Storage) and can optionally be configured via INI files during firmware updates.


The settings system uses X-macros for compile-time code generation, producing type-safe enums, metadata tables, and validation checks from a single definition. Settings are categorized into:

All settings are managed by the ESP3DSettings class (main/core/esp3d_settings.cpp#180-181) with automatic NVS persistence and schema versioning. The global instance is named esp3dXsettings (main/core/esp3d_settings.cpp#62).

Sources:main/core/includes/esp3d_settings.h#107-113main/core/esp3d_settings.cpp#62main/core/esp3d_settings.cpp#127-130


The X-macro pattern allows defining each setting once using the ESP3D_SET_DEF macro, which expands multiple times during compilation to generate different code artifacts.

Natural Language to Code Entity Mapping (Architecture)

Section titled “Natural Language to Code Entity Mapping (Architecture)”

Title: Settings System Entity Mapping

Definition Layer (Natural Language Space)

Code Entity Space (Implementation)

ESP3DSettingIndex (Type-safe identifier)

ESP3DSettingDescription (Metadata struct)

ESP3DSettingsData[] (Lookup table)

nvs_handle (Storage engine)

ESP3D_SET_DEF macro (The 'Source of Truth')

Sources:main/core/includes/esp3d_settings.h#102-113main/core/esp3d_settings.cpp#115-125main/core/esp3d_settings.cpp#156-160


ESP3D_SET_DEF(enum_name, // Identifier used in code (e.g., esp3d_baud_rate)
"nvs_key", // NVS storage key (max 15 chars, e.g., "sys_baud")
type, // byte_t, integer_t, string_t, ip_t, float_t
size, // Max size (bytes for byte/int, string length)
"default_value", // Default as string
ini_info) // INI_ENTRY("section", "key") or NO_INI

Add to main/target/cnc/fluidnc/esp3d_target_settings_defs.inc:

ESP3D_SET_DEF(esp3d_new_feature_enabled,
"tgt_new_feat",
byte_t,
1,
"1",
INI_ENTRY("pendant", "New_feature_enabled"))

Sources:main/core/includes/esp3d_settings_defs.inc#34-40main/core/includes/esp3d_settings.h#168-178main/target/cnc/fluidnc/esp3d_target_settings_defs.inc#39-44


RuleRequirementRationale
Maximum length15 charactersESP-IDF NVS API limitation (main/core/esp3d_settings.cpp#158-159)
UniquenessMust be globally uniquePrevents storage collisions
Naming conventionUse prefixessys_, net_, tgt_, jog_ (main/core/includes/esp3d_settings_defs.inc#15main/target/cnc/fluidnc/esp3d_target_settings_defs.inc#15)

The system automatically validates NVS keys at compile time using static_assert within an anonymous namespace in the implementation file (main/core/esp3d_settings.cpp#157-159):

#define ESP3D_SET_DEF_VALIDATE(enum_name, nvs_key, type, size, default_val, ini_section, ini_key) \
static_assert(const_strlen(nvs_key) <= NVS_KEY_MAX_LEN, \
"NVS key '" nvs_key "' exceeds 15 character limit");

Sources:main/core/esp3d_settings.cpp#145-174main/core/includes/esp3d_settings_defs.inc#12-16


TypeC TypeSize FieldUse Case
byte_tuint8_t1Boolean flags, small enums
integer_tuint32_t4Baud rates, ports, intervals
string_tchar[]Max lengthSSIDs, passwords, hostnames
ip_tuint32_t4IPv4 addresses (main/core/includes/esp3d_settings.h#156)
float_tchar[]15Floating point values (stored as string)

Sources:main/core/includes/esp3d_settings.h#151-162main/core/includes/esp3d_settings.h#171-173


Settings are accessed via the global esp3dXsettings instance (main/core/esp3d_settings.cpp#62).

Title: Setting Access Flow

Application Logic

Settings Service (ESP3DSettings)

Storage (NVS)

NVS Flash Partition (ESP3D_X)

readByte / readUint32 / readString

writeByte / writeUint32 / writeString

Screen/Service

#include "esp3d_settings.h"
// Reading an integer setting
uint32_t baud = esp3dXsettings.readUint32(ESP3DSettingIndex::esp3d_baud_rate);
// Writing a string setting
esp3dXsettings.writeString(ESP3DSettingIndex::esp3d_sta_ssid, "MyNetwork");

Sources:main/core/esp3d_settings.cpp#57main/core/esp3d_settings.cpp#62main/core/esp100.cpp#80-82main/core/esp100.cpp#208-209


The [ESP400] command exports settings to external clients (WebUI, Serial) in JSON or text format (main/core/commands/esp400.cpp#98-100). To include your setting:

  1. Define Labels/Values: Add string arrays for the UI labels if it’s a list-type setting (main/core/commands/esp400.cpp#32-36).
  2. Dispatch: Call dispatchSetting() in the ESP400 function (main/core/commands/esp400.cpp#128-134).
// Example in esp400.cpp for a list setting
if (!dispatchSetting(json, "system/system",
ESP3DSettingIndex::esp3d_baud_rate, "baud", BaudRateList,
BaudRateList, sizeof(BaudRateList) / sizeof(char*), -1,
-1, -1, nullptr, true, target, requestId)) {
esp3d_log_e("Error sending response to clients");
}

Sources:main/core/commands/esp400.cpp#32-36main/core/commands/esp400.cpp#128-134main/core/commands/esp400.cpp#160-166


Step 6: Implementing Manual Command Handlers

Section titled “Step 6: Implementing Manual Command Handlers”

For settings that require immediate action (like changing baud rates or themes), specific ESP commands are implemented in the ESP3DCommands class (main/core/includes/esp3d_commands.h#34).

Title: ESP Command to Settings Update Flow

ESP3DMessage (e.g. [ESP281]2)

ESP3DCommands::process()

ESP3DCommands::execute_internal_command()

ESP3DCommands::ESP281()

esp3dXsettings.isValid*()

esp3dXsettings.write*()

ui_manager.setTheme() (Immediate Action)

ESP3DCommands::dispatchAnswer()

Sources:main/core/esp3d_commands.cpp#135-142main/core/commands/esp281.cpp#31-108main/core/commands/esp132.cpp#29-86


When adding or modifying settings, you must update the versioning system to ensure NVS is correctly initialized.

  • Major Version: Increment in ESP3D_SETTINGS_VERSION_MAJOR if you change the size or type of an existing setting. This triggers a full reset of all settings to defaults during checkSchemaVersion() (main/core/esp3d_settings.cpp#240-244).
  • Minor Version: Increment in ESP3D_SETTINGS_VERSION_MINOR if you add a new setting. This preserves existing settings while initializing the new one (main/core/esp3d_settings.cpp#248-251).

Sources:main/core/esp3d_settings.cpp#233-257main/core/includes/esp3d_settings_version.h#1-10