Skip to content

Latest commit

 

History

25 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

marquee-zigbee-controller

Zigbee firmware for an ESP32-C6 that turns a wired Somfy awning ("marquee") motor into a Zigbee Home Automation cover, controllable from Zigbee2MQTT, ZHA, or any other Zigbee 3.0 coordinator.

The awning has no position feedback and can also be driven by its original remote, so this firmware deliberately does not try to track or report a position — it exposes Open / Close / Stop plus a live motor-status sensor, which is the most that can be reported honestly. See Design notes for the reasoning.

Status: LED test mode. The relay outputs are not wired up yet, so movement is currently indicated on the board's onboard RGB LED instead of switching relays. Everything else — the Zigbee endpoint, command handling, mutual exclusion and the safety timeout — is the real implementation. See Switching to relays.

Hardware

Signal GPIO Notes
Extend (Down/Close) 2 Relay 1 — Somfy yellow wire to ground. Active high. Not driven in LED test mode.
Retract (Up/Open) 3 Relay 2 — Somfy green wire to ground. Active high. Not driven in LED test mode.
Button 9 Onboard BOOT button, active low. Long press = factory reset.
Status LED 8 Onboard addressable RGB LED.
  • Board: ESP32-C6 DevKitC (4 MB flash — see the note in sdkconfig.defaults; some variants ship 8 MB, and flashing an 8 MB image to a 4 MB part panics at boot).
  • Motor interface: Somfy 1822609. White wire is common ground; shorting yellow to ground extends, green to ground retracts. Hold-to-move — the motor runs only while the contact is closed, and stops itself at its end limits.
  • The two relay outputs are mutually exclusive in software; they are never energised at the same time.

LED test mode colours

LED Meaning
Green Extending (Down/Close)
Blue Retracting (Up/Open)
Off Stopped

Zigbee model

Single HA endpoint (ID 1), device type Window Covering, joining as an End Device.

Cluster Role
Basic (0x0000) Manufacturer Crunchypancake, model MarqueeCover
Identify (0x0003) Standard identify
Window Covering (0x0102) WindowCoveringType = Awning. Handles Up/Open, Down/Close, Stop. No lift-percentage attributes — the device cannot measure position, so it does not advertise one.
Multistate Input (0x0012) PresentValue reports live motor status: 0 stopped, 1 opening (retracting), 2 closing (extending). NumberOfStates = 3.

Command mapping: Up/Open → retract (roll in), Down/Close → extend (roll out).

A safety timeout of 12 s (SAFETY_TIMEOUT_MS) force-releases the outputs and reports stopped if no Stop command arrives. The motor's own end-limit switches are the primary protection; this is the backstop.

Building and flashing

Requires ESP-IDF v5.2 or newer (developed against v5.4.1). Zigbee dependencies are pulled automatically by the IDF Component Manager.

. $HOME/esp/esp-idf/export.sh

idf.py set-target esp32c6
idf.py build
idf.py -p /dev/ttyACM0 flash monitor

If your board has 8 MB of flash, change CONFIG_ESPTOOLPY_FLASHSIZE_4MB to CONFIG_ESPTOOLPY_FLASHSIZE_8MB in sdkconfig.defaults and delete sdkconfig before rebuilding.

Pairing

  1. Put your coordinator into "permit join" mode.
  2. Power on the device. A factory-new device starts network steering automatically and retries every second until it joins.
  3. On success the log prints the PAN ID, channel and short address.

Factory reset

Hold the BOOT button (GPIO 9) for 5 seconds or more and release. The device leaves the network, clears its Zigbee persistent data and reboots into pairing mode. Short presses do nothing.

Zigbee2MQTT

The device uses only standard clusters, so a coordinator will pair it without help — but Z2M needs a small external converter to expose the motor-status sensor as an entity. Copy docs/zigbee2mqtt/marquee-cover.mjs into your Z2M external_converters directory and restart Z2M.

It exposes the standard cover controls plus a motor_status enum (stopped / opening / closing) reported independently of the commanded state.

Switching to relays

The LED indicator lives entirely in set_outputs() in main/app_driver.c. To drive real relays:

  1. Replace the led_strip_* calls in set_outputs() with gpio_set_level() on GPIO_EXTEND / GPIO_RETRACT, and configure those pins as outputs in driver_init().
  2. Move the safety cut back into safety_timer_cb()gpio_set_level() is safe to call there, which drops the queue round-trip.
  3. Drop the espressif/led_strip dependency from main/idf_component.yml.

Repository layout

CMakeLists.txt          ESP-IDF project definition
partitions.csv          Partition table (OTA + Zigbee storage)
sdkconfig.defaults      Target, flash size, Zigbee End Device config
main/
  app_main.c            Zigbee stack init, endpoint/cluster setup, ZCL handlers
  app_driver.c/.h       Output control, mutual exclusion, safety timer
  app_button.c/.h       Debounced long-press factory-reset button
docs/plans/             Design and implementation notes (incl. the earlier
                        Matter-over-Thread design this replaced)
docs/zigbee2mqtt/       External converter for Zigbee2MQTT

Known limitations

  • No position reporting. The cover appears as open/close/stop only. Sliders in some dashboards will not be available. This is intentional.
  • Attribute reporting for the motor status has to be configured by the coordinator after binding; the supplied Z2M converter does this.
  • A factory reset performed while the device is not joined to a network may not reboot the device — it is already in pairing mode, so this is harmless.

License

MIT — see LICENSE.

About

Zigbee end device (ESP32-C6) that drives a Somfy marquee/awning motor over a Window Covering cluster

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages