Skip to Content

← Hardware Guide | Contents | Next: Commissioning →

2. Compilation

ACRouter v2.0 builds with ESP-IDF 5.5 using idf.py. It runs on two targets and ships in one of three compile profiles — pick the one that matches your chip and how you want to control the device.


2.1 Toolchain

  • ESP-IDF 5.5 (5.5.1) — the firmware is built with ESP-IDF (idf.py), not the Arduino IDE or PlatformIO.
  • Python 3.8+ and CMake 3.16+ (bundled with the ESP-IDF installer).
  • Managed components are resolved automatically by the IDF Component Manager from main/idf_component.yml on the first set-target / reconfigure — notably Arduino Core 3.x (espressif/arduino-esp32) and ArduinoJson v7 (bblanchon/arduinojson). ACRouter uses the Arduino API (String, millis(), …) on top of the ESP-IDF build system.

Install ESP-IDF

bash
mkdir -p ~/esp && cd ~/esp
git clone -b v5.5.1 --recursive https://github.com/espressif/esp-idf.git
cd esp-idf
./install.sh esp32,esp32c2      # install both target toolchains
. ~/esp/esp-idf/export.sh       # activate the environment (each shell)

Then clone the firmware and enter it:

bash
git clone https://github.com/robotdyn-dimmer/ACRouter.git
cd ACRouter

On Windows, use the ESP-IDF PowerShell/CMD environment and export.ps1.


2.2 Two Targets, Three Profiles

Target Chip Cores Default profile
esp32 ESP32 (WROOM/WROVER) dual-core ESP32 full
esp32c2 ESP32-C2 / ESP8684 single-core, RAM-limited one interface per build

Each build carries exactly one compile profile:

Profile Target HTTP/REST + WS MQTT OTA For
ESP32 full esp32 Full build: web + MQTT + OTA, dual-core, ESP-NOW
C2-HTTP esp32c2 Web control on the C2 (REST/WS); no MQTT/OTA
C2-MQTT esp32c2 Headless: MQTT only, provisioned over MQTT; no web server

🔴 Why the tiering? The ESP32-C2 has ~272 KB RAM — not enough to hold HTTP + MQTT + TLS at once. So a C2 build carries exactly one remote interface (HTTP xor MQTT), chosen at compile time. The ESP32 has the headroom to carry both. On C2-MQTT there is no HTTP server at all — the device is reached only through the broker.


2.3 Profile Flags (Kconfig)

A profile is a set of Kconfig options, resolved from an sdkconfig.defaults layer:

Option Meaning
CONFIG_ACROUTER_HTTP_SERVER HTTP/REST + WebSocket server
CONFIG_ACROUTER_MQTT_CLIENT MQTT client
CONFIG_ACROUTER_OTA OTA update subsystem
CONFIG_ACROUTER_RBAMP_SOURCE rbAmp I2C sensing source
CONFIG_ACROUTER_MQTT_BOOTSTRAP config-over-MQTT provisioning (C2-MQTT)

On the C2 the HTTP-on / MQTT-off / OTA-off defaults are applied automatically (default n if IDF_TARGET_ESP32C2).

🔴 Gotcha — keep profile flags in an sdkconfig.defaults layer, not in a hand-edited sdkconfig. idf.py set-target regenerates sdkconfig from the defaults and discards manual edits. That is exactly why the headless profile ships as a separate sdkconfig.defaults.c2mqtt layer.


2.4 Build & Flash

Use a separate build directory per target so the ESP32 and C2 builds don't clobber each other. <PORT> is COM3 (Windows) or /dev/ttyUSB0 (Linux).

ESP32 full

bash
idf.py set-target esp32
idf.py build
idf.py -p <PORT> flash

C2-HTTP

bash
idf.py -B build_c2 -D SDKCONFIG=sdkconfig.c2 set-target esp32c2
idf.py -B build_c2 -D SDKCONFIG=sdkconfig.c2 build
idf.py -B build_c2 -D SDKCONFIG=sdkconfig.c2 -p <PORT> flash

C2-MQTT (headless)

bash
idf.py -B build_c2mqtt \
  -D SDKCONFIG_DEFAULTS="sdkconfig.defaults;sdkconfig.defaults.c2mqtt" \
  set-target esp32c2
idf.py -B build_c2mqtt -D SDKCONFIG_DEFAULTS="sdkconfig.defaults;sdkconfig.defaults.c2mqtt" build
idf.py -B build_c2mqtt -D SDKCONFIG_DEFAULTS="sdkconfig.defaults;sdkconfig.defaults.c2mqtt" -p <PORT> flash

Large OTA-over-WiFi is impractical on the C2 — flash the C2 over serial.

Monitor

bash
idf.py -p <PORT> monitor     # picks the correct baud automatically; Ctrl-] to exit

Partitions & OTA

The flash layout is dual-OTA — two app slots (app0, app1) so firmware can update over the air, plus nvs (configuration) and otadata (which slot is active). There is no SPIFFS/web-UI partition — the UI is external in v2.0. Exact slot sizes vary by target; the layout is defined in the repo's partitions.csv.


2.5 Capability-Aware Runtime

A build advertises what it carries at runtime — GET /api/info returns a features object (http, mqtt, ota, github_ota, tls). The same web app works against every profile and simply shows only what the build supports. Gate features on these flags, never on the chip name.

json
{ "chip": "ESP32-C2", "features": { "http": true, "mqtt": false, "ota": false, "github_ota": false, "tls": false } }

2.6 Manual Flashing (esptool)

For normal flashing use idf.py -p <PORT> flash — it already knows the right offsets. To flash without idf.py (e.g. from another machine), match --chip to your target (esp32 or esp32c2) and use the artifacts from the corresponding build directory:

bash
esptool.py --chip esp32 --port <PORT> --baud 921600 \
  --before default_reset --after hard_reset write_flash -z \
  0x0     build/bootloader/bootloader.bin \
  0x8000  build/partition_table/partition-table.bin \
  0xf000  build/ota_data_initial.bin \
  0x20000 build/ACRouter-project.bin

The app binary is ACRouter-project.bin at offset 0x20000 (custom partition table). Rather than copy offsets by hand, take the exact esptool.py write_flash … line that idf.py build prints at the end of a build for your target.


2.7 Common Build Issues

  • Wrong target / stale sdkconfig. If a C2 build behaves like an ESP32 build (or vice-versa), your sdkconfig was regenerated from the wrong defaults — see the §2.3 gotcha. Use the right -B <dir> + SDKCONFIG_DEFAULTS and re-run set-target.
  • ESP-IDF version mismatch. idf.py --version must report v5.5.x. Re-install 5.5.1 if it differs.
  • Dependency not found. Run idf.py reconfigure to re-resolve managed components.
  • App partition too small. Ensure your build directory matches the target; a C2 image flashed against an ESP32 partition layout (or vice-versa) will not fit.

2.8 Pre-Built Binaries

Planned. Pre-built v2.0 binaries are not published yet — for now, build from source as above. When v2.0 is released, per-target/profile archives (ESP32 / C2-HTTP / C2-MQTT) with a flash script will be posted on the GitHub Releases page.


← Hardware Guide | Contents | Next: Commissioning →