Skip to content
Buy 10+ on select items — save 10% auto-applied
Free US shipping on orders $35+
Order by 3pm ET — ships same-day from the US
Skip to main content

ESP32-C6 Zigbee: Build a Wireless Light Switch | ShillehTek

July 30, 2026 2 views

ESP32-C6 Zigbee: Build a Wireless Light Switch | ShillehTek
Project

Build a two-node ESP32-C6 Zigbee network where a wireless switch toggles a remote LED light, using Arduino IDE settings, binding, and endpoints from ShillehTek.

1 hr Intermediate5 parts

Project Overview

ESP32-C6 Zigbee light and switch: Use two ESP32-C6 boards with their native IEEE 802.15.4 radio to build a real Zigbee network where a wireless switch toggles a remote LED light.

The ESP32-C6 is special: alongside WiFi 6 and BLE it includes an 802.15.4 radio, which means it can run Zigbee without an external module. In this project you flash two C6 boards: one becomes a Zigbee light (end device) and the other becomes a Zigbee switch (coordinator). Press the switch board button and the light board LED toggles over the Zigbee network you created.

  • Time: 1 to 2 hours
  • Skill level: Intermediate
  • What you will build: A two-node Zigbee network (wireless light and switch) using only ESP32-C6 boards and the Arduino IDE.
Two ESP32-C6 development boards used to create a Zigbee light and Zigbee switch network
Two ESP32-C6 boards, one Zigbee network.

Parts List

From ShillehTek

External

  • One LED and two USB cables

Note: Zigbee mesh networking, low power, AES-128 security, and large network size are enabled by the ESP32-C6 802.15.4 radio. No extra Zigbee module is required.

Step-by-Step Guide

Step 1 - Set up the Arduino IDE for the C6

Goal: Get ESP32-C6 and Zigbee build support installed.

What to do: In the Arduino IDE, add the Espressif board manager URL in Preferences:

https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json

Install the esp32 package, then select your board (for example, ESP32C6 Dev Module or your specific ESP32-C6 variant). You should now see Zigbee examples under File > Examples > Zigbee.

Expected result: ESP32-C6 boards are selectable and Zigbee examples are visible.

Step 2 - Wire the light node

Goal: Connect one LED to GPIO4.

What to do: On the board that will be the light, connect an LED through a 220 ohm resistor from GPIO4 to GND. The BOOT button on the board doubles as the factory-reset and local toggle control, so no extra button wiring is required.

Expected result: Light node hardware is complete (an LED and resistor on GPIO4).

Step 3 - Flash the Zigbee light (end device)

Goal: Make board #1 behave like a Zigbee light bulb.

What to do: Set these critical Arduino IDE options for the light board:

  • Zigbee Mode: Zigbee ED (end device)
  • Partition Scheme: Zigbee 4MB with spiffs

Upload the light sketch from the Espressif Zigbee examples (Apache 2.0). The core of it is shown below.

#ifndef ZIGBEE_MODE_ED
#error "Zigbee end device mode is not selected in Tools->Zigbee mode"
#endif
#include "Zigbee.h"

#define ZIGBEE_LIGHT_ENDPOINT 10
uint8_t led = 4;
uint8_t button = BOOT_PIN;
ZigbeeLight zbLight = ZigbeeLight(ZIGBEE_LIGHT_ENDPOINT);

void setLED(bool value) {
  digitalWrite(led, value);
}

void setup() {
  Serial.begin(115200);
  pinMode(led, OUTPUT);
  digitalWrite(led, LOW);
  pinMode(button, INPUT_PULLUP);

  zbLight.setManufacturerAndModel("Espressif", "ZBLightBulb");
  zbLight.onLightChange(setLED);   // callback drives the LED

  Serial.println("Adding ZigbeeLight endpoint to Zigbee Core");
  Zigbee.addEndpoint(&zbLight);

  if (!Zigbee.begin()) {           // starts as an end device
    Serial.println("Zigbee failed to start! Rebooting...");
    ESP.restart();
  }
  Serial.println("Connecting to network");
  while (!Zigbee.connected()) {
    Serial.print(".");
    delay(100);
  }
  Serial.println();
}

void loop() {
  // Hold BOOT 3s = Zigbee factory reset; quick press = local toggle
  if (digitalRead(button) == LOW) {
    delay(100);
    int startTime = millis();
    while (digitalRead(button) == LOW) {
      delay(50);
      if ((millis() - startTime) > 3000) {
        Serial.println("Resetting Zigbee to factory and rebooting in 1s.");
        delay(1000);
        Zigbee.factoryReset();
      }
    }
    zbLight.setLight(!zbLight.getLightState());
  }
  delay(100);
}

Expected result: The light boots and prints dots in Serial while it waits to join a Zigbee network.

Step 4 - Flash the Zigbee switch (coordinator)

Goal: Make board #2 form the Zigbee network and control the light.

What to do: Switch the Arduino IDE settings for the second board to:

  • Zigbee Mode: Zigbee ZCZR (coordinator/router)
  • Partition Scheme: Zigbee 4MB with spiffs

Upload the switch sketch from the Zigbee examples. Key behaviors to confirm from the sketch:

  • It creates a ZigbeeSwitch endpoint and starts as ZIGBEE_COORDINATOR.
  • It opens the network for joining for 180 seconds after boot using Zigbee.setRebootOpenNetwork(180).
  • It waits until a light binds, then prints the light short address, IEEE address, manufacturer, and model.
  • The BOOT button uses an interrupt with a FreeRTOS queue, and each debounced press calls zbSwitch.lightToggle().
  • It re-lists bound devices every 10 seconds.

Expected result: The switch boots, forms the network, and reports when the light joins and binds.

Step 5 - Watch the network form, then toggle

Goal: Verify network formation, binding, and wireless control.

What to do: Power both boards, with the switch board first. The light should join during the 180-second open-network window (its Serial dots stop). The switch prints the bound device addresses when binding completes.

Press the BOOT button on the switch board. The LED on the light board should toggle wirelessly via a Zigbee toggle command. Discovery uses the Zigbee Device Object Match Descriptor Request, the same mechanism commercial hubs use.

Expected result: Pressing a button on one ESP32-C6 toggles an LED on the other through Zigbee.

Step 6 - Where to take it

Goal: Extend the two-node demo into a larger system.

What to do: The switch sketch already calls allowMultipleBinding(true), so more lights can bind to one switch. You can also swap the LED endpoint for a relay, add ESP32-C6 sensor nodes (temperature, occupancy), or join your devices to an existing Zigbee hub ecosystem.

Expected result: You have a clear path from a simple light and switch to a multi-device Zigbee setup.

Conclusion

You used the ESP32-C6 native 802.15.4 radio to build a working Zigbee light and switch pair, including the correct Arduino IDE Zigbee modes (ED vs ZCZR), Zigbee partition scheme, endpoint registration, network formation, binding, and wireless toggling.

Want the exact parts used in this build? Grab them from ShillehTek.com. If you want help customizing this project or building something for your product, check out our IoT consulting services.

Credits: Photos and reference credited to Hackster.io. Sketches are based on Espressif Systems Zigbee examples under Apache 2.0 (with Jan Prochazka), referenced via the original guide by Nickson Kiprotich.