arduino-esp32 core does not define a 'custom' PartitionScheme menu option on
any board. The core's prebuild hook already copies partitions.csv from next
to the .ino file into the build dir when present, so no menu override is
needed.
Web assets only use ~489 KB but the default 1.375 MB spiffs
partition wasted the rest. Rebalance to 768 KB spiffs / 1.56 MB
per app slot (was 1.25 MB), giving the tight esp32 build real
headroom (99.6% -> 79.7% flash used) while preserving dual-slot
OTA. Wire the custom layout into both the local PlatformIO build
(new partitions.csv + platformio.ini) and the Arduino-CLI CI/release
pipeline (PartitionScheme=custom, matching littlefs image size and
merge_bin offset).
getNextShadeId() and getNextGroupId() capped usable IDs at
SOMFY_MAX_SHADES-1/SOMFY_MAX_GROUPS-1, so the top 2 shade IDs
(31, 32) and top 2 group IDs (15, 16) could never be allocated
even though the backing arrays support the full range.
Documents the drum-radius problem, the four calibration fields
(upMidTime, downMidTime, descendTime, upSlatTime), the two-phase
shutter model, and the special 1% blade-expanded boundary.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The four non-linear calibration fields were persisted to NVS and returned
via the JSON API but were missing from the binary config file (ShadeConfigFile).
Bump SHADE_HDR_VER to 25 and SHADE_REC_SIZE to 320, add read/write for the
four fields. Old backups (version ≤ 24) load cleanly with defaults of 0
(linear behaviour).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
moveToTarget() silently dropped commands when pos == currentPos,
which prevented position recalibration via slider, MQTT, or Home
Assistant when the shade was already at 0% or 100%. Physical
end-stops are ground truth — always send the command so the motor
can jog to the hard stop and self-correct any position drift.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Introduces descendTime and upSlatTime to model the two motion phases:
- Descent (slats unrolling) followed by blade tilt to fully close
- Blade opening followed by ascent when raising
Both fields are user-measured timestamps from the movement start,
making them easy to determine with a stopwatch. alphaDown and alphaUp
are now computed against the pure descent/ascent duration only,
excluding the linear blade-tilt phase at each end.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaced fixed max-width:127px on Up/Down Time and 50% mid-time fields
with calc(50% - 10px) / 50% so each pair fills the container width.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Motor speed varies with drum radius as shade material winds/unwinds,
causing linear time-interpolation to misestimate position. Adds two
optional calibration fields (upMidTime, downMidTime) that let users
provide the elapsed time at 50% travel. A logarithmic model (alpha
ratio solved via Newton's method) then replaces the linear formula.
Falls back to existing linear behaviour when mid-time fields are zero.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>