Skip to content

Commit de2cd4a

Browse files
authored
feat(zigbee): Window covering tilt support and fixes
1 parent e5aeb58 commit de2cd4a

File tree

4 files changed

+452
-268
lines changed

4 files changed

+452
-268
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
// Copyright 2025 Espressif Systems (Shanghai) PTE LTD
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
/**
16+
* @brief This example demonstrates Zigbee Window Covering.
17+
*
18+
* The example demonstrates how to use Zigbee library to create a end device window covering device.
19+
* The window covering is a Zigbee end device, which is moving the blinds (lift+tilt) and reporting
20+
* its current position to the Zigbee network.
21+
*
22+
* Use setCoveingType() to set the type of covering (blind, shade, etc.).
23+
*
24+
* The example also demonstrates how to use the button to manually control the lift position.
25+
*
26+
* Proper Zigbee mode must be selected in Tools->Zigbee mode
27+
* and also the correct partition scheme must be selected in Tools->Partition Scheme.
28+
*
29+
* Please check the README.md for instructions and more detailed description.
30+
*
31+
* Created by hennikul and Jan Procházka (https://github.com/P-R-O-C-H-Y/)
32+
*/
33+
34+
#ifndef ZIGBEE_MODE_ED
35+
#error "Zigbee end device mode is not selected in Tools->Zigbee mode"
36+
#endif
37+
38+
#include "ZigbeeCore.h"
39+
#include "ep/ZigbeeWindowCovering.h"
40+
41+
42+
#define ZIGBEE_COVERING_ENDPOINT 10
43+
#define BUTTON_PIN 9 // ESP32-C6/H2 Boot button
44+
45+
#define MAX_LIFT 200 // centimeters from open position (0-900)
46+
#define MIN_LIFT 0
47+
48+
#define MAX_TILT 40 // centimeters from open position (0-900)
49+
#define MIN_TILT 0
50+
51+
uint16_t currentLift = MAX_LIFT;
52+
uint8_t currentLiftPercentage = 100;
53+
54+
uint16_t currentTilt = MAX_TILT;
55+
uint8_t currentTiltPercentage = 100;
56+
57+
ZigbeeWindowCovering zbCovering = ZigbeeWindowCovering(ZIGBEE_COVERING_ENDPOINT);
58+
59+
void setup() {
60+
Serial.begin(115200);
61+
62+
// Init button for factory reset
63+
pinMode(BUTTON_PIN, INPUT_PULLUP);
64+
65+
// Optional: set Zigbee device name and model
66+
zbCovering.setManufacturerAndModel("Espressif", "WindowBlinds");
67+
68+
// Set proper covering type, it defines which attributes are available
69+
zbCovering.setCoveringType(BLIND_LIFT_AND_TILT);
70+
71+
// Set configuration: operational, online, not commands_reversed, lift / tilt closed_loop, lift / tilt encoder_controlled
72+
zbCovering.setConfigStatus(true, true, false, true, true, true, true);
73+
74+
// Set mode: not motor_reversed, calibration_mode, not maintenance_mode, not leds_on
75+
zbCovering.setMode(false, true, false, false);
76+
77+
// Set limits of motion
78+
zbCovering.setLimits(MIN_LIFT, MAX_LIFT, MIN_TILT, MAX_TILT);
79+
80+
// Set callback function for open, close, filt and tilt change, stop
81+
zbCovering.onOpen(fullOpen);
82+
zbCovering.onClose(fullClose);
83+
zbCovering.onGoToLiftPercentage(goToLiftPercentage);
84+
zbCovering.onGoToTiltPercentage(goToTiltPercentage);
85+
zbCovering.onStop(stopMotor);
86+
87+
// Add endpoint to Zigbee Core
88+
Serial.println("Adding ZigbeeWindowCovering endpoint to Zigbee Core");
89+
Zigbee.addEndpoint(&zbCovering);
90+
91+
// When all EPs are registered, start Zigbee. By default acts as ZIGBEE_END_DEVICE
92+
Serial.println("Calling Zigbee.begin()");
93+
if (!Zigbee.begin()) {
94+
Serial.println("Zigbee failed to start!");
95+
Serial.println("Rebooting...");
96+
ESP.restart();
97+
}
98+
Serial.println("Connecting to network");
99+
while (!Zigbee.connected()) {
100+
Serial.print(".");
101+
delay(100);
102+
}
103+
Serial.println();
104+
105+
// Set initial position
106+
zbCovering.setLiftPercentage(currentLiftPercentage);
107+
zbCovering.setTiltPercentage(currentTiltPercentage);
108+
}
109+
110+
void loop() {
111+
// Checking button for factory reset
112+
if (digitalRead(BUTTON_PIN) == LOW) { // Push button pressed
113+
// Key debounce handling
114+
delay(100);
115+
int startTime = millis();
116+
while (digitalRead(BUTTON_PIN) == LOW) {
117+
delay(50);
118+
if ((millis() - startTime) > 3000) {
119+
// If key pressed for more than 3secs, factory reset Zigbee and reboot
120+
Serial.printf("Resetting Zigbee to factory settings, reboot.\n");
121+
Zigbee.factoryReset();
122+
delay(30000);
123+
}
124+
}
125+
// Manual lift controll simulation by pressing button
126+
manualControl();
127+
}
128+
delay(500);
129+
}
130+
131+
void fullOpen(){
132+
/* This is where you would trigger your motor to go to full open state, currentLift should
133+
be updated until full open has been reached in order to provide feedback to controller of actual position
134+
The stop can be always called, so the movement can be stopped at any time */
135+
136+
// Our cover updates instantly!
137+
currentLift = MAX_LIFT;
138+
currentLiftPercentage = 100;
139+
Serial.println("Opening cover");
140+
// Update the current position
141+
zbCovering.setLiftPercentage(currentLiftPercentage);
142+
}
143+
144+
void fullClose(){
145+
/* This is where you would trigger your motor to go to full close state, currentLift should
146+
be updated until full close has been reached in order to provide feedback to controller of actual position
147+
The stop can be always called, so the movement can be stopped at any time */
148+
149+
// Our cover updates instantly!
150+
currentLift = MIN_LIFT;
151+
currentLiftPercentage = 0;
152+
Serial.println("Closing cover");
153+
// Update the current position
154+
zbCovering.setLiftPercentage(currentLiftPercentage);
155+
}
156+
157+
void goToLiftPercentage(uint8_t liftPercentage) {
158+
/* This is where you would trigger your motor to go towards liftPercentage, currentLift should
159+
be updated until liftPercentage has been reached in order to provide feedback to controller */
160+
161+
// Our simulated cover updates instantly!
162+
currentLift = (liftPercentage * MAX_LIFT) / 100;
163+
currentLiftPercentage = liftPercentage;
164+
Serial.printf("New requsted lift from Zigbee: %d (%d)\n", currentLift, liftPercentage);
165+
166+
//Update the current position
167+
zbCovering.setLiftPercentage(currentLiftPercentage); //or setLiftPosition()
168+
}
169+
170+
void goToTiltPercentage(uint8_t tiltPercentage) {
171+
/* This is where you would trigger your motor to go towards tiltPercentage, currentTilt should
172+
be updated until tiltPercentage has been reached in order to provide feedback to controller */
173+
174+
// Our simulated cover updates instantly!
175+
currentTilt = (tiltPercentage * MAX_TILT) / 100;
176+
currentTiltPercentage = tiltPercentage;
177+
Serial.printf("New requsted tilt from Zigbee: %d (%d)\n", currentTilt, tiltPercentage);
178+
179+
//Update the current position
180+
zbCovering.setTiltPercentage(currentTiltPercentage); //or setTiltPosition()
181+
}
182+
183+
184+
void stopMotor() {
185+
// Motor can be stopped while moving cover toward current target, when stopped the actual position should be updated
186+
Serial.println("Stopping motor");
187+
// Update the current position of both lift and tilt
188+
zbCovering.setLiftPercentage(currentLiftPercentage);
189+
zbCovering.setTiltPercentage(currentTiltPercentage);
190+
}
191+
192+
void manualControl() {
193+
// Simulate lift percentage move by increasing it by 20% each time
194+
currentLiftPercentage += 20;
195+
if(currentLiftPercentage > 100) {
196+
currentLiftPercentage = 0;
197+
}
198+
zbCovering.setLiftPercentage(currentLiftPercentage);
199+
// Also setLiftPosition() can be used to set the exact position instead of percentage
200+
}

libraries/Zigbee/examples/Zigbee_Window_Covering/Zigbee_Window_Covering.ino.ino

-113
This file was deleted.

0 commit comments

Comments
 (0)