On RP2040, get_mac_address_raw() only queried WiFi.macAddress(). When
ethernet is configured without WiFi, the MAC address was left
uninitialized, causing get_mac_address() and get_mac_address_pretty()
to return all zeros. This affects device identification (API, mDNS,
unique ID).
Unlike ESP32 which reads from eFuse (always available regardless of
network interface), RP2040 must query the actual network driver.
Fall back to ethernet::global_eth_component->get_eth_mac_address_raw()
when USE_ETHERNET is defined and USE_WIFI is not.
Per swoboda1337's suggestion, run the heater after the measurement
read instead of before. This maximizes cooldown time before the
next reading and avoids skipping any measurement cycles.
Only advance last_heater_millis_ after the heater command succeeds
so a failed write retries on the next cycle instead of silently
skipping.
Add heater settings to the test YAML to ensure CI exercises the
heater code path.
When heater_interval < update_interval, the heater would fire on
nearly every update cycle, skipping almost all real measurements.
Push the next eligible heater time forward by at least one
update_interval to guarantee at least one ambient reading between
heater activations.
Integrate heater activation into the measurement cycle instead of
running it on an independent timer. The separate heater interval
could overlap with measurement polling, causing readings to be
taken while the sensor was still hot.
Now the heater fires during update() when due, skipping that
measurement cycle. The next regular update() takes an ambient
reading after the sensor has cooled.
Also replace magic numbers with named constexpr constants for
the datasheet conversion formulas.
Closes https://github.com/esphome/esphome/issues/15011
The intr_type field of ledc_channel_config_t was deprecated in
ESP-IDF 6.0 as the driver now handles interrupts internally.
Guard the assignment with a version check to silence the warning.
ESP-IDF 6.0 switched from Newlib to PicolibC. The Newlib compatibility
shim (CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY) provides thread-local
stdin/stdout/stderr and getreent() for code compiled against Newlib.
ESPHome doesn't link against Newlib-built libraries that use stdio,
so the shim is unnecessary overhead. The cost is small (a few dozen
bytes of TLS per FreeRTOS task) but there's no reason to carry it.
Users linking precompiled Newlib binaries can re-enable via:
sdkconfig_options:
CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY: "y"
Symbols declared with extern "C" linkage (like resetPins in esp8266/core.cpp)
lack C++ namespace prefixes, causing them to fall through to "other" in the
memory analysis. This adds source-file-based attribution by scanning ESPHome
object files with nm to build a symbol-to-component map.
Also removes resetPins from the arduino_core heuristic pattern since it's
an ESPHome function, not an Arduino one.
Replace three separate equality comparisons with a single bitmask
shift-and-test. This compiles to fully branchless code and halves
the function size on Xtensa (38 → 19 bytes, 14 → 7 instructions).
Only one preferences backend is ever compiled per binary, so the
platform prefix is redundant. Shorten all TAG strings from
"<platform>.preferences" to just "preferences".
Saves 4-8 bytes of RAM per platform (tag string stored in .rodata
on ESP8266).
Move LOG_LEVEL_COLOR_DIGIT and LOG_LEVEL_LETTER_CHARS arrays from
.rodata (RAM) to PROGMEM (flash) on ESP8266. These small lookup
tables were consuming 16 bytes of RAM unnecessarily.
Results on a minimal ESP8266 config:
- RAM: -16 bytes (.rodata 948 → 932 bytes)
- Flash: +32 bytes (PROGMEM access code)
Extract cycle_or_clamp_ helper and simplify the increment/decrement
branches by flattening nested conditionals. Use LOG_STR_LITERAL for
cycling log strings.
ESP32 modules like the ESP32-PICO-V3-02 use a different flash pin
configuration where GPIO7 and GPIO8 are freely usable. The existing
ignore_pin_validation_error option allows bypassing this check but
the error message did not mention it, making it hard to discover.