Skip to content

Latest commit

 

History

History
94 lines (80 loc) · 5.24 KB

File metadata and controls

94 lines (80 loc) · 5.24 KB

Roller Blind — ESPHome firmware

ESPHome firmware for motorizing a cardboard roller blind with a NEMA-17 stepper on the Valar VAL3000 board (ESP32-C3 + TMC2209). It is a fork of Valar Systems' Ropener curtain firmware, adapted for a D-shaft insert that direct-drives the blind tube (no rope, no gear). Upstream Ropener is licensed under the Open Community License (OCL v1) — a non-commercial, share-alike license — so this fork is distributed under the same terms. See LICENSE.

Layout

File Purpose
VAL3000/rollerblind-VAL3000.yml Per-board wrapper: ESP32-C3 chip variant + GPIO pin map, then includes the core. This is the file you build.
common/rollerblind-core.yaml All device behaviour (board-independent).

Build / flash

ESPHome isn't required to be installed locally — most people build from the ESPHome dashboard or Home Assistant add-on. From the CLI it's:

esphome run VAL3000/rollerblind-VAL3000.yml

First flash over USB (with Improv for Wi-Fi), then OTA from the ESPHome dashboard thereafter. On first boot the device makes a rollerblind-XXXXXX Wi-Fi hotspot / captive portal for network setup; find XXXXXX (MAC suffix) in the serial boot log, then reach it at http://rollerblind-XXXXXX.local.

What changed vs. upstream Ropener

  1. Travel model: rope-cm → tube revolutions. Ropener measured travel as cm of rope through an MK7 gear. This direct-drive blind has no gear, so travel is set in tube revolutions via the "Travel (revolutions)" number (global_distance_rev, default 10 rev). global_distance_steps = revolutions × 1600. The gear_distance_cm constant and the "Centimeters" entity are gone. Caveat: as fabric winds onto the tube its diameter grows, so drop-per-rev isn't perfectly linear — intermediate 0..1 positions are approximate.
  2. Rebrand. Device rollerblind / "Roller Blind", project aplaceforfacts.roller-blind, cover device_class: shade, hostname rollerblind-XXXXXX.local. Version reset to 0.1.0-rb.
  3. Removed the "Update Firmware (GitHub)" button (and its http_request OTA platform + client). That button pulled Valar's stock Ropener release and would overwrite this custom build. Update via the ESPHome dashboard/CLI OTA instead (ota: - platform: esphome, still present).
  4. Position-aware standstill hold. Upstream idled in open freewheel (ihold: 0), so the blind was unheld and crept/fell. This fork holds the motor at standstill with a reduced IHOLD via apply_standstill_current, gated by a position band (Hold Band Min/Max). Default: band 0–100 % = hold everywhere, IHOLD 6 — the config proven on this blind (no falls). A low 6/31 hold is a small fraction of run current, so standstill heat stays mild (and the vented bracket/shroud handle it). The band is a general mechanism: if a blind genuinely only sags over part of its travel you can narrow it to reclaim idle power at the free ends, where the code instead applies a coil-short passive brake (standstill_mode: coil_short_ls, ihold: 0). On this blind that outside-band branch is dormant (it back-drives everywhere). Gotcha, still relevant if you use coil-short: the slimcdk StandstillMode enum is mis-valued, so coil_short_hs silently truncates to NORMAL (no brake) — coil_short_ls is the string that writes a real coil-short. Caveat: IHOLD holds only while powered; a mains cut drops the blind (a mechanical / EM power-off brake is the only fix for that, not fitted).

Unchanged from Ropener (by design, per project decisions):

  • StallGuard sensorless homing kept, plus manual limits (two-button hold = set home/0; "Travel (revolutions)" = open end). Both paths available.

First-run calibration checklist

  1. Direction — if open/close are reversed, flip the "Motor Direction" select (Normal ↔ Reversed).
  2. Home (position 0) — decide which end is "closed/0". Either tune StallGuard to home against a hard stop, or jog there and set home (hold both buttons 3 s).
  3. StallGuard retune — SGTHRS/TCOOLTHRS default to 0 and must be tuned for this drivetrain: drive under load, watch the SG_RESULT sensor, set SGTHRS ≈ ½ of the loaded reading. The rope-pull load signature does not carry over to a direct tube drive.
  4. Travel — jog to fully open and set "Travel (revolutions)" so 100% maps to the open end.
  5. Speed / Acceleration / IRUN — tune for quiet, reliable motion under the blind's torque.

Open items / TODO

  • RESOLVED — the blind back-drives at every position (fell at both fully open and fully closed), so the hold band now defaults to full range (0–100 %) with IHOLD 6, which holds it with no falls. The narrow-sag-band idea is retired. Remaining gap: this holds only while powered — a mains cut still drops it (would need a mechanical / EM power-off brake).
  • Tune StallGuard for the tube drive; pick the home end.
  • Optional: rename the internal ropener_cover entity id (left as-is to avoid a wide rename; it's not user-visible).
  • VAL3100 (ESP32-C6) wrapper not ported — this fork targets the VAL3000 only.