XIAO ESP32C6 Zigbee Guía de Inicio Rápido (Arduino)
Overview
Este tutorial te gúíará a través de la implementación de Zigbee en la XIAO ESP32C6 de Seeed Studio. Impulsada por el chip ESP32-C6, esta placa combina conectividad Wi-Fi, Bluetooth Low Energy (BLE) y Zigbee, lo que la hace ideal para aplicaciones IoT. Los ejemplos en esta guía utilizan el SDK esp-arduino Zigbee para dar vida a la funcionalidad Zigbee.

Lo que aprenderás
Si aún no has preparado tu Arduino IDE, consulta la Guía de inicio. Asegúrate de que la versión de la placa esp-arduino sea v3.0.6 o posterior, ya que esta versión admite la funcionalidad Zigbee.
Esta guía se centra en lo esencial para utilizar Zigbee con la XIAO ESP32C6, garantizando una comprensión clara de sus aplicaciones prácticas:
- Descripción general de Zigbee: Comprende el protocolo Zigbee y su estructura de red.
- Ejemplos de Zigbee en Arduino: Implementa ejemplos como bombillas e interruptores en el ESP32-C6.
Descripción general de Zigbee
Zigbee es un protocolo de comunicación inalámbrica de bajo consumo y bajo ancho de banda, basado en el estándar IEEE 802.15.4. Está diseñado para escenarios de IoT, como automatización del hogar, ciudades inteligentes y control industrial, ofreciendo capacidades de redes en malla robustas para una comunicación confiable en entornos dinámicos.
Modelo de datos de Zigbee
La comunicación en Zigbee se basa en la Zigbee Cluster Library (ZCL), que define cómo los dispositivos organizan sus funciones e interactúan. Sus principales componentes incluyen:
Tipos de dispositivos
Los dispositivos Zigbee (p. ej., interruptores, sensores, luces) tienen comportamientos predefinidos y se agrupan en Clusters funcionales.Clusters
Son agrupaciones lógicas de:- Atributos: Representan estados del dispositivo, como brillo o temperatura.
- Comandos: Activan acciones, como encender una luz o ajustar el brillo al 50 %.
Ejemplos:
- On/Off Cluster: Controla estados binarios, como encendido/apagado.
- Level Control Cluster: Ajusta la intensidad o el brillo.
- Temperature Measurement Cluster: Envía lecturas de temperatura.
- Scenes Cluster: Guarda y recupera configuraciones predefinidas.
Atributos y comandos
Los atributos almacenan datos del dispositivo (estado, configuración), mientras que los comandos inician acciones.

Arquitectura de la red Zigbee
Una red Zigbee está compuesta por tres tipos principales de nodos:
Coordinador Zigbee (ZC)
- Actúa como el núcleo central de la red.
- Gestiona la creación de la red, la autenticación de dispositivos y la asignación de direcciones.
- Es responsable de inicializar y administrar la red.
- Cada red Zigbee solo puede tener un Coordinador.
Router Zigbee (ZR)
- Extiende el alcance de la red retransmitiendo mensajes entre dispositivos.
- Permite que nuevos dispositivos se unan a la red.
- Generalmente está alimentado por la red eléctrica para garantizar un funcionamiento constante y una retransmisión confiable de mensajes.
- Existen Routers alimentados por batería, pero son menos comunes debido a su mayor consumo energético.
Dispositivo Final Zigbee (ZED)
- Dispositivos ligeros y eficientes en consumo de energía que se comunican con un nodo padre (Coordinador o Router).
- No retransmiten mensajes a otros dispositivos.
- Optimizados para operar con batería y suelen entrar en modos de suspensión para ahorrar energía.
:::nota
Direcciones y Enrutamiento:
- Zigbee utiliza un esquema de direccionamiento de 16 bits. Los dispositivos se comunican mediante direccionamiento directo e indirecto.
- Las decisiones de enrutamiento las toman los Routers mediante algoritmos como AODV (Ad hoc On-demand Distance Vector).
Gestión de Energía:
- Los Dispositivos Finales Zigbee están optimizados para un bajo consumo de energía, operando en modo de suspensión y despertando solo cuando es necesario.
- Los Routers y el Coordinador suelen estar conectados a la corriente para asegurar disponibilidad constante.
:::
Topologías de red
Zigbee admite tres principales topologías de red, dependiendo de los requisitos de la aplicación y el entorno:
1. Topología en Malla
Un Coordinador y múltiples Routers forman una red robusta y auto-reparable.
Los dispositivos pueden redirigir dinámicamente los mensajes si una ruta de comunicación se interrumpe, asegurando alta fiabilidad.
Ideal para redes de gran escala que requieren amplia cobertura y redundancia.
Características clave:
- El redireccionamiento dinámico garantiza alta fiabilidad.
- Soporta redes grandes con cobertura escalable.
- Los mecanismos de autorrecuperación aumentan la tolerancia a fallos.
2. Topología en Árbol
El Coordinador actúa como la raíz de una estructura jerárquica, con Routers formando ramas.
Cada rama puede contener múltiples Dispositivos Finales o Routers adicionales, creando una estructura similar a un árbol.
La comunicación depende de rutas jerárquicas, lo que puede generar puntos únicos de fallo.
Características clave:
- Fácil de configurar y gestionar.
- Escalabilidad limitada debido a restricciones de alcance y capacidad de dispositivos.
- La dependencia del Coordinador para toda la comunicación reduce la tolerancia a fallos.
Después de esta visión general de los conceptos clave, pasemos al desarrollo con Zigbee en la XIAO ESP32C6.
Ejemplos en Arduino
Consulta los Ejemplos de Zigbee - Arduino.
Ejemplo 1: Bombilla e Interruptor Zigbee
Primero, prepara dos XIAO ESP32C6, una como Bombilla Zigbee y otra como Interruptor Zigbee.
Usa los ejemplos Zigbee_On_Off_Light
y Zigbee_On_Off_Switch
para comprender cómo interactúan los dispositivos habilitados con Zigbee en escenarios reales. ¿Listo para comenzar? ¡Vamos al desarrollo!
Bombilla Zigbee
Asegúrate de seleccionar Zigbee ED (end device)
como el modo de operación Zigbee.
Algunas constantes:
#define LED_PIN LED_BUILTIN
#define BUTTON_PIN 9 // ESP32-C6/H2 Boot button
#define ZIGBEE_LIGHT_ENDPOINT 10
LED_PIN
se usa para controlar el LED incorporado.BUTTON_PIN
es para el botón de restablecimiento de fábrica.ZIGBEE_LIGHT_ENDPOINT
representa el endpoint Zigbee de la bombilla, funcionando como un identificador de servicio en la red.
Definir el Dispositivo de Luz Zigbee
ZigbeeLight zbLight = ZigbeeLight(ZIGBEE_LIGHT_ENDPOINT);
Esta línea define un objeto ZigbeeLight
con un ID de endpoint. Los endpoints se utilizan para representar diferentes funcionalidades dentro de un dispositivo Zigbee.
Función de Control del Estado del Dispositivo
La función setLED()
controla el estado del LED.
void setLED(bool value) {
digitalWrite(LED_PIN, value);
}
La función setLED() acepta un valor booleano y ajusta el estado del LED en consecuencia, encendiéndolo o apagándolo según el valor de entrada.
Función setup()
La función setup() inicializa el dispositivo, incluyendo el LED, el botón y la configuración de Zigbee.
void setup() {
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
Primero, configuramos el pin para el LED como salida y lo apagamos inicialmente.
pinMode(BUTTON_PIN, INPUT_PULLUP);
El pin del botón está configurado como una entrada con una resistencia pull up.
zbLight.setManufacturerAndModel("Espressif", "ZBLightBulb");
Esto establece el fabricante y el nombre del modelo para el dispositivo, lo que ayuda a identificarlo en la red Zigbee.
zbLight.onLightChange(setLED);
Esto registra setLED()
como una función de callback, que se ejecutará cada vez que haya un cambio en el estado de la luz.
Zigbee.addEndpoint(&zbLight);
Añadimos zbLight
como un endpoint al núcleo de Zigbee. Esto permite que otros dispositivos Zigbee interactúen con este endpoint.
Zigbee.begin();
Finalmente, llamamos a Zigbee.begin() para inicializar la pila Zigbee y empezar el dispositivo como un dispositivo final en la red.
Función loop()
El bucle principal maneja las presiones del botón para realizar un restablecimiento de fábrica:
void loop() {
if (digitalRead(BUTTON_PIN) == LOW) {
delay(100); // Key debounce handling
int startTime = millis();
while (digitalRead(BUTTON_PIN) == LOW) {
delay(50);
if ((millis() - startTime) > 3000) {
Serial.printf("Resetting Zigbee to factory settings, reboot.\n");
Zigbee.factoryReset();
}
}
}
delay(100);
}
Este código verifica si el botón está presionado:
- Si se presiona, espera 100 ms (para manejar el rebote del botón).
- Si el botón permanece presionado durante más de 3 segundos, se activa un restablecimiento de fábrica llamando a
Zigbee.factoryReset()
.
Esta función es útil para los usuarios cuando necesitan reconfigurar el dispositivo debido a problemas de red o emparejamiento.
Las rutinas oficiales siguen siendo actualizadas continuamente, por lo que nuestra documentación puede no estar sincronizada con los programas más recientes en todo momento. Si hay alguna discrepancia, consulta los ejemplos de programas de Espressif.**.
#ifndef ZIGBEE_MODE_ED
#error "No se ha seleccionado el modo de dispositivo final Zigbee en Herramientas->Modo Zigbee"
#endif
#include "ZigbeeCore.h"
#include "ep/ZigbeeLight.h"
#define LED_PIN LED_BUILTIN
#define BUTTON_PIN 9 // Botón de arranque ESP32-C6/H2
#define ZIGBEE_LIGHT_ENDPOINT 10
ZigbeeLight zbLight = ZigbeeLight(ZIGBEE_LIGHT_ENDPOINT);
/********************* Funciones del LED RGB **************************/
void setLED(bool value) {
digitalWrite(LED_PIN, value);
}
/********************* Funciones de Arduino **************************/
void setup() {
// Inicializa el LED y apágalo (si LED_PIN == RGB_BUILTIN, rgbLedWrite() se usará automáticamente)
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
// Inicializa el botón para el restablecimiento de fábrica
pinMode(BUTTON_PIN, INPUT_PULLUP);
// Opcional: establece el nombre y modelo del dispositivo Zigbee
zbLight.setManufacturerAndModel("Espressif", "ZBLightBulb");
// Establece la función de callback para el cambio de luz
zbLight.onLightChange(setLED);
// Añade el endpoint al núcleo Zigbee
log_d("Añadiendo el endpoint ZigbeeLight al núcleo Zigbee");
Zigbee.addEndpoint(&zbLight);
// Cuando todos los endpoints están registrados, inicia Zigbee. Por defecto, actúa como ZIGBEE_END_DEVICE
log_d("Llamando a Zigbee.begin()");
Zigbee.begin();
}
void loop() {
// Verifica el botón para el restablecimiento de fábrica
if (digitalRead(BUTTON_PIN) == LOW) { // El botón está presionado
// Manejo del rebote de la tecla
delay(100);
int startTime = millis();
while (digitalRead(BUTTON_PIN) == LOW) {
delay(50);
if ((millis() - startTime) > 3000) {
// Si la tecla está presionada por más de 3 segundos, restablece Zigbee a la configuración de fábrica y reinicia
Serial.printf("Restableciendo Zigbee a la configuración de fábrica, reiniciando.\n");
Zigbee.factoryReset();
}
}
}
delay(100);
}
Interruptor Zigbee
Aquí, el XIAO ESP32C6 funciona como el Coordinador Zigbee, encargado de controlar otros dispositivos Zigbee. En este caso, el Interruptor Zigbee actúa como el controlador, que se vincula a un dispositivo de luz Zigbee y lo controla a través de comandos, como encender o apagar la luz.
Inclusiones y Definiciones
#include "ZigbeeCore.h"
#include "ep/ZigbeeLight.h"
#define SWITCH_ENDPOINT_NUMBER 5
#define GPIO_INPUT_IO_TOGGLE_SWITCH 9
#define PAIR_SIZE(TYPE_STR_PAIR) (sizeof(TYPE_STR_PAIR) / sizeof(TYPE_STR_PAIR[0]))
SWITCH_ENDPOINT_NUMBER
se define como5
. Representa el endpoint del interruptor. Al igual que en el ejemplo de la bombilla, el número de endpoint se usa para definir la función específica dentro de un dispositivo Zigbee.GPIO_INPUT_IO_TOGGLE_SWITCH
se refiere al pin GPIO9
, que actúa como el botón del interruptor.PAIR_SIZE()
es una macro utilizada para calcular el tamaño de un arreglo dado, que se utiliza aquí para manejar las configuraciones del botón.
Tipos de Configuración del Interruptor y Funciones
El código define varias enumeraciones y estructuras de datos relacionadas con la funcionalidad del interruptor:
typedef enum {
SWITCH_ON_CONTROL,
SWITCH_OFF_CONTROL,
SWITCH_ONOFF_TOGGLE_CONTROL,
SWITCH_LEVEL_UP_CONTROL,
SWITCH_LEVEL_DOWN_CONTROL,
SWITCH_LEVEL_CYCLE_CONTROL,
SWITCH_COLOR_CONTROL,
} SwitchFunction;
typedef struct {
uint8_t pin;
SwitchFunction func;
} SwitchData;
typedef enum {
SWITCH_IDLE,
SWITCH_PRESS_ARMED,
SWITCH_PRESS_DETECTED,
SWITCH_PRESSED,
SWITCH_RELEASE_DETECTED,
} SwitchState;
SwitchFunction
enumera las diferentes funciones que el interruptor puede realizar, como encender la luz, apagarla, alternar el estado, ajustar el brillo, etc.SwitchData
es una estructura que empareja un pin GPIO con una función específica, lo que permite una mejor organización al agregar múltiples botones con diferentes funcionalidades.SwitchState
representa los diferentes estados del interruptor durante la interacción con el usuario (por ejemplo, inactivo, presionado, liberado).
Instanciando el Interruptor Zigbee
static SwitchData buttonFunctionPair[] = {{GPIO_INPUT_IO_TOGGLE_SWITCH, SWITCH_ONOFF_TOGGLE_CONTROL}};
ZigbeeSwitch zbSwitch = ZigbeeSwitch(SWITCH_ENDPOINT_NUMBER);
buttonFunctionPair
es un arreglo que define las funciones de los botones. Aquí, el botón conectado alGPIO 9
se utilizará para alternar la luz encendida o apagada.zbSwitch
crea una instancia deZigbeeSwitch
, con el número de endpoint5
.
Funciones Zigbee y Manejo de Interrupciones GPIO
static void onZbButton(SwitchData *button_func_pair) {
if (button_func_pair->func == SWITCH_ONOFF_TOGGLE_CONTROL) {
zbSwitch.lightToggle(); // Sends a toggle command to the light.
}
}
onZbButton()
se llama cada vez que un botón es presionado. En este caso, envía un comando Zigbee para alternar la luz.
Manejo de Eventos GPIO
static void IRAM_ATTR onGpioInterrupt(void *arg) {
xQueueSendFromISR(gpio_evt_queue, (SwitchData *)arg, NULL);
}
onGpioInterrupt()
es la rutina de servicio de interrupción (ISR) para manejar las interrupciones del pin GPIO. Coloca un evento en una cola cada vez que el botón es presionado.
static void enableGpioInterrupt(bool enabled) {
for (int i = 0; i < PAIR_SIZE(buttonFunctionPair); ++i) {
if (enabled) {
enableInterrupt((buttonFunctionPair[i]).pin);
} else {
disableInterrupt((buttonFunctionPair[i]).pin);
}
}
}
enableGpioInterrupt()
habilita o deshabilita la interrupción del GPIO, dependiendo de si el parámetro enabled
es true
o false
.
Función Setup
void setup() {
Serial.begin(115200);
while (!Serial) {
delay(10);
}
zbSwitch.setManufacturerAndModel("Espressif", "ZigbeeSwitch");
zbSwitch.allowMultipleBinding(true);
Zigbee.addEndpoint(&zbSwitch);
Zigbee.setRebootOpenNetwork(180);
for (int i = 0; i < PAIR_SIZE(buttonFunctionPair); i++) {
pinMode(buttonFunctionPair[i].pin, INPUT_PULLUP);
gpio_evt_queue = xQueueCreate(10, sizeof(SwitchData));
if (gpio_evt_queue == 0) {
log_e("Queue was not created and must not be used");
while (1);
}
attachInterruptArg(buttonFunctionPair[i].pin, onGpioInterrupt, (void *)(buttonFunctionPair + i), FALLING);
}
Zigbee.begin(ZIGBEE_COORDINATOR);
Serial.println("Waiting for Light to bound to the switch");
while (!zbSwitch.isBound()) {
Serial.printf(".");
delay(500);
}
std::list<zb_device_params_t *> boundLights = zbSwitch.getBoundDevices();
for (const auto &device : boundLights) {
Serial.printf("Device on endpoint %d, short address: 0x%x\n", device->endpoint, device->short_addr);
Serial.printf(
"IEEE Address: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", device->ieee_addr[0], device->ieee_addr[1], device->ieee_addr[2], device->ieee_addr[3],
device->ieee_addr[4], device->ieee_addr[5], device->ieee_addr[6], device->ieee_addr[7]
);
Serial.printf("Light manufacturer: %s", zbSwitch.readManufacturer(device->endpoint, device->short_addr));
Serial.printf("Light model: %s", zbSwitch.readModel(device->endpoint, device->short_addr));
}
Serial.println();
}
- Inicialización de Comunicación Serial: Inicializa la comunicación serial para depuración.
- Información del Dispositivo: Establece el fabricante y el modelo, permite que múltiples dispositivos se vinculen y agrega un endpoint al núcleo Zigbee.
- Inicialización de la Red: Abre la red Zigbee durante
180
segundos después del reinicio para permitir que los dispositivos se unan. - Inicialización de Botones: Configura los pines GPIO para los botones, crea una cola para manejar las interrupciones GPIO y asigna interrupciones a los botones.
- Esperar Vinculación: El coordinador espera hasta que se vincule con un dispositivo de luz antes de continuar. Una vez vinculado, imprime la información del dispositivo vinculado.
Función Loop
void loop() {
uint8_t pin = 0;
SwitchData buttonSwitch;
static SwitchState buttonState = SWITCH_IDLE;
bool eventFlag = false;
if (xQueueReceive(gpio_evt_queue, &buttonSwitch, portMAX_DELAY)) {
pin = buttonSwitch.pin;
enableGpioInterrupt(false);
eventFlag = true;
}
while (eventFlag) {
bool value = digitalRead(pin);
switch (buttonState) {
case SWITCH_IDLE: buttonState = (value == LOW) ? SWITCH_PRESS_DETECTED : SWITCH_IDLE; break;
case SWITCH_PRESS_DETECTED: buttonState = (value == LOW) ? SWITCH_PRESS_DETECTED : SWITCH_RELEASE_DETECTED; break;
case SWITCH_RELEASE_DETECTED:
buttonState = SWITCH_IDLE;
(*onZbButton)(&buttonSwitch);
break;
default: break;
}
if (buttonState == SWITCH_IDLE) {
enableGpioInterrupt(true);
eventFlag = false;
break;
}
vTaskDelay(10 / portTICK_PERIOD_MS);
}
static uint32_t lastPrint = 0;
if (millis() - lastPrint > 10000) {
lastPrint = millis();
zbSwitch.printBoundDevices();
}
}
- La función loop gestiona las presiones de los botones leyendo desde la cola de interrupciones (
gpio_evt_queue
) y actualizando elbuttonState
en consecuencia. - Cuando el botón es presionado y liberado (
SWITCH_RELEASE_DETECTED
), se invoca la función de callbackonZbButton()
para alternar la luz. - Cada 10 segundos, se imprime la información de las luces vinculadas con fines de monitoreo.
Las rutinas oficiales siguen siendo actualizadas continuamente, por lo que nuestra documentación puede no estar sincronizada con los programas más recientes en todo momento. Si hay alguna discrepancia, por favor consulta los ejemplos de programas de Espressif.
#ifndef ZIGBEE_MODE_ZCZR
#error "No se ha seleccionado el modo coordinador Zigbee en Herramientas->Modo Zigbee"
#endif
#include "ZigbeeCore.h"
#include "ep/ZigbeeLight.h"
#define SWITCH_ENDPOINT_NUMBER 5
/* Configuración del interruptor */
#define GPIO_INPUT_IO_TOGGLE_SWITCH 9
#define PAIR_SIZE(TYPE_STR_PAIR) (sizeof(TYPE_STR_PAIR) / sizeof(TYPE_STR_PAIR[0]))
typedef enum {
SWITCH_ON_CONTROL,
SWITCH_OFF_CONTROL,
SWITCH_ONOFF_TOGGLE_CONTROL,
SWITCH_LEVEL_UP_CONTROL,
SWITCH_LEVEL_DOWN_CONTROL,
SWITCH_LEVEL_CYCLE_CONTROL,
SWITCH_COLOR_CONTROL,
} SwitchFunction;
typedef struct {
uint8_t pin;
SwitchFunction func;
} SwitchData;
typedef enum {
SWITCH_IDLE,
SWITCH_PRESS_ARMED,
SWITCH_PRESS_DETECTED,
SWITCH_PRESSED,
SWITCH_RELEASE_DETECTED,
} SwitchState;
static SwitchData buttonFunctionPair[] = {{GPIO_INPUT_IO_TOGGLE_SWITCH, SWITCH_ONOFF_TOGGLE_CONTROL}};
ZigbeeSwitch zbSwitch = ZigbeeSwitch(SWITCH_ENDPOINT_NUMBER);
/********************* Funciones Zigbee **************************/
static void onZbButton(SwitchData *button_func_pair) {
if (button_func_pair->func == SWITCH_ONOFF_TOGGLE_CONTROL) {
// Enviar comando de alternancia a la luz
zbSwitch.lightToggle();
}
}
/********************* Funciones GPIO **************************/
static QueueHandle_t gpio_evt_queue = NULL;
static void IRAM_ATTR onGpioInterrupt(void *arg) {
xQueueSendFromISR(gpio_evt_queue, (SwitchData *)arg, NULL);
}
static void enableGpioInterrupt(bool enabled) {
for (int i = 0; i < PAIR_SIZE(buttonFunctionPair); ++i) {
if (enabled) {
enableInterrupt((buttonFunctionPair[i]).pin);
} else {
disableInterrupt((buttonFunctionPair[i]).pin);
}
}
}
/********************* Funciones de Arduino **************************/
void setup() {
Serial.begin(115200);
while (!Serial) {
delay(10);
}
// Opcional: configurar nombre y modelo del dispositivo Zigbee
zbSwitch.setManufacturerAndModel("Espressif", "ZigbeeSwitch");
// Opcional para permitir que varias luces se vinculen al interruptor
zbSwitch.allowMultipleBinding(true);
// Agregar el endpoint al Zigbee Core
log_d("Agregando el endpoint ZigbeeSwitch al Zigbee Core");
Zigbee.addEndpoint(&zbSwitch);
// Abrir la red durante 180 segundos después del reinicio
Zigbee.setRebootOpenNetwork(180);
// Inicializar el interruptor de botón
for (int i = 0; i < PAIR_SIZE(buttonFunctionPair); i++) {
pinMode(buttonFunctionPair[i].pin, INPUT_PULLUP);
/* crear una cola para manejar el evento GPIO desde ISR */
gpio_evt_queue = xQueueCreate(10, sizeof(SwitchData));
if (gpio_evt_queue == 0) {
log_e("No se pudo crear la cola, no se debe usar");
while (1);
}
attachInterruptArg(buttonFunctionPair[i].pin, onGpioInterrupt, (void *)(buttonFunctionPair + i), FALLING);
}
// Cuando todos los EPs estén registrados, iniciar Zigbee en modo ZIGBEE_COORDINATOR
log_d("Llamando a Zigbee.begin()");
Zigbee.begin(ZIGBEE_COORDINATOR);
Serial.println("Esperando que la luz se vincule al interruptor");
// Esperar a que el interruptor se vincule a una luz:
while (!zbSwitch.isBound()) {
Serial.printf(".");
delay(500);
}
// Opcional: leer el nombre del fabricante y el modelo de la luz vinculada
std::list<zb_device_params_t *> boundLights = zbSwitch.getBoundDevices();
// Listar todas las luces vinculadas
for (const auto &device : boundLights) {
Serial.printf("Dispositivo en el endpoint %d, dirección corta: 0x%x\n", device->endpoint, device->short_addr);
Serial.printf(
"Dirección IEEE: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", device->ieee_addr[0], device->ieee_addr[1], device->ieee_addr[2], device->ieee_addr[3],
device->ieee_addr[4], device->ieee_addr[5], device->ieee_addr[6], device->ieee_addr[7]
);
Serial.printf("Fabricante de la luz: %s", zbSwitch.readManufacturer(device->endpoint, device->short_addr));
Serial.printf("Modelo de la luz: %s", zbSwitch.readModel(device->endpoint, device->short_addr));
}
Serial.println();
}
void loop() {
// Manejar el interruptor de botón en loop()
uint8_t pin = 0;
SwitchData buttonSwitch;
static SwitchState buttonState = SWITCH_IDLE;
bool eventFlag = false;
/* verificar si hay alguna cola recibida, si es así leer el buttonSwitch */
if (xQueueReceive(gpio_evt_queue, &buttonSwitch, portMAX_DELAY)) {
pin = buttonSwitch.pin;
enableGpioInterrupt(false);
eventFlag = true;
}
while (eventFlag) {
bool value = digitalRead(pin);
switch (buttonState) {
case SWITCH_IDLE: buttonState = (value == LOW) ? SWITCH_PRESS_DETECTED : SWITCH_IDLE; break;
case SWITCH_PRESS_DETECTED: buttonState = (value == LOW) ? SWITCH_PRESS_DETECTED : SWITCH_RELEASE_DETECTED; break;
case SWITCH_RELEASE_DETECTED:
buttonState = SWITCH_IDLE;
/* callback a button_handler */
(*onZbButton)(&buttonSwitch);
break;
default: break;
}
if (buttonState == SWITCH_IDLE) {
enableGpioInterrupt(true);
eventFlag = false;
break;
}
vTaskDelay(10 / portTICK_PERIOD_MS);
}
// imprimir las luces vinculadas cada 10 segundos
static uint32_t lastPrint = 0;
if (millis() - lastPrint > 10000) {
lastPrint = millis();
zbSwitch.printBoundDevices();
}
}
Demostración
¡Felicitaciones por haber completado con éxito tu proyecto de iluminación controlada por Zigbee! Hay muchas más aplicaciones emocionantes de Zigbee esperando ser exploradas. ¡Sigue con el gran trabajo!
Referencias
- Ejemplos de Zigbee - Arduino
- ESP Zigbee SDK
- La biblioteca wrapper de Zigbee para el Arduino Core de ESP32
Soporte Técnico y Discusión de Productos
¡Gracias por elegir nuestros productos! Estamos aquí para brindarte el soporte necesario para garantizar que tu experiencia con nuestros productos sea lo más fluida posible. Ofrecemos varios canales de comunicación para adaptarnos a diferentes preferencias y necesidades.