Make a Zigbee LED Strip with RGBIC effects using an M5Stack NanoC6 and A035 15 LED RGBIC strip
This is made possible by the hard work of @luar123 for the zigbee_esphome external component. (github://luar123/zigbee_esphome)
A lot of the code is based on examples in the github repo, but I was having some issues getting started. I thought I would share my configuration to save some folks time and effort. (This is so heckin’ cool!)
For this tutorial, you’ll need a working install of esphome 2025.7.5, an M5Stack NanoC6, an A035 LED Strip, and a Grove cable:
-
(Mouser) M5NanoC6 ~$6 before tax, shipping, and Trump Tariffs of about 50 cents.
-
(Mouser) M5Stack A035 - 15 LED 10CM RGBIC Strip ~$5 before tax, shipping, and Trump Tariffs of about 50 cents.
Mouser doesn’t ship any Grove cables with the LED strip (boo!), but they sell them if you need them:
*(Mouser) M5Stack Grove Cable ~$2 before tax, shipping, and Trump Tariffs of about 25 cents.
I recommend buying a bunch of modules to make the shipping from Mouser worth it. You can buy the C6 module from Amazon, but you’ll pay triple.
-
Once you have your materials, connect your LED strip to the Grove cable, and the cable to the module.
-
Go to github and download partitions_zb.csv
then place in /config/esphome -
Open ESPHome and prep a new device.
-
Once your device is online, replace your YAML code with:
esphome:
name: nanoc6-2
friendly_name: M5Stack NanoC6 Light Strip (ZB Only)
platformio_options:
platform: https://github.com/platformio/platform-espressif32/archive/refs/tags/v6.7.0.zip
board_build.f_cpu: 160000000L
board_build.f_flash: 80000000L
board_build.flash_size: 4MB
build_flags: "-DBOARD_HAS_PSRAM"
board_build.arduino.memory_type: qio_opi
esp32:
board: esp32-c6-devkitm-1
variant: esp32c6
partitions: partitions_zb.csv
framework:
type: esp-idf
version: 5.2.1
# version: "5.3.0"
platform_version: 6.8.1
sdkconfig_options:
CONFIG_ESPTOOLPY_FLASHSIZE_4MB: y
output:
- platform: ledc
pin: GPIO07
id: gpio_07
switch:
- platform: gpio
pin: GPIO19
id: gpio_19
restore_mode: ALWAYS_ON
binary_sensor:
- platform: gpio
name: "Button"
id: m5stack_button
pin:
number: GPIO9
inverted: true
on_press:
- light.turn_on:
id: ledstrip
effect: random
- light.turn_on:
id: button_light
effect: random
on_double_click:
- light.turn_on:
id: ledstrip
effect: rainbow
- light.turn_on:
id: button_light
effect: rainbow
on_multi_click:
- timing:
- ON for at most 1s
- OFF for at most 1s
- ON for at most 1s
- OFF for at most 1s
- ON for at most 1s
- OFF for at most 1s
then:
- light.turn_on:
id: ledstrip
effect: scan
- light.turn_on:
id: button_light
effect: rainbow
- timing:
- ON for at least 3s
- OFF for at least 1s
- ON for at least 3s
- OFF for at least 1s
then:
- zigbee.reset: zb
light:
- platform: esp32_rmt_led_strip
chipset: SK6812
pin: GPIO02
num_leds: 15
rgb_order: GRB
rmt_symbols: 48
name: "LED Strip"
id: "ledstrip"
effects:
- random:
- flicker:
- addressable_rainbow:
- addressable_color_wipe:
- addressable_scan:
- addressable_twinkle:
- addressable_random_twinkle:
- addressable_fireworks:
- addressable_flicker:
- platform: esp32_rmt_led_strip
rgb_order: GRB
pin: GPIO20
num_leds: 1
# rmt_channel: 0 ### this stopped working 2025/02
chipset: WS2812
rmt_symbols: 48
id: "button_light"
name: "Button LED"
icon: "mdi:led-outline"
effects:
- random:
- flicker:
- addressable_rainbow:
- platform: monochromatic
output: gpio_07
id: blueled
name: "Blue LED"
sensor:
- platform: internal_temperature
name: "Internal Temperature"
id: "i_temp"
filters:
- delta: 0.1
external_components:
- source: github://luar123/zigbee_esphome
components: [zigbee]
globals:
- id: color_x
type: float
restore_value: no
initial_value: '0'
- id: color_y
type: float
restore_value: no
initial_value: '0'
zigbee:
id: "zb"
router: true
endpoints:
- num: 1
device_type: COLOR_DIMMABLE_LIGHT
clusters:
- id: ON_OFF
attributes:
- attribute_id: 0
type: bool
on_value:
then:
- light.control:
id: ledstrip
state: !lambda "return (bool)x;"
- id: LEVEL_CONTROL
attributes:
- attribute_id: 0
type: U8
value: 255
on_value:
then:
- light.control:
id: ledstrip
brightness: !lambda "return ((float)x)/255;"
- id: COLOR_CONTROL
attributes:
- attribute_id: 3
type: U16
on_value:
then:
- lambda: id(color_x) = (float)x/65536;
- light.control:
id: ledstrip
red: !lambda "return zigbee::get_r_from_xy(id(color_x), id(color_y));"
green: !lambda "return zigbee::get_g_from_xy(id(color_x), id(color_y));"
blue: !lambda "return zigbee::get_b_from_xy(id(color_x), id(color_y));"
- attribute_id: 4
type: U16
on_value:
then:
- lambda: id(color_y) = (float)x/65536;
- light.control:
id: ledstrip
red: !lambda "return zigbee::get_r_from_xy(id(color_x), id(color_y));"
green: !lambda "return zigbee::get_g_from_xy(id(color_x), id(color_y));"
blue: !lambda "return zigbee::get_b_from_xy(id(color_x), id(color_y));"
- num: 2
device_type: COLOR_DIMMABLE_LIGHT
clusters:
- id: ON_OFF
attributes:
- attribute_id: 0
type: bool
on_value:
then:
- light.control:
id: button_light
state: !lambda "return (bool)x;"
- id: LEVEL_CONTROL
attributes:
- attribute_id: 0
type: U8
value: 255
on_value:
then:
- light.control:
id: button_light
brightness: !lambda "return ((float)x)/255;"
- id: COLOR_CONTROL
attributes:
- attribute_id: 3
type: U16
on_value:
then:
- lambda: id(color_x) = (float)x/65536;
- light.control:
id: button_light
red: !lambda "return zigbee::get_r_from_xy(id(color_x), id(color_y));"
green: !lambda "return zigbee::get_g_from_xy(id(color_x), id(color_y));"
blue: !lambda "return zigbee::get_b_from_xy(id(color_x), id(color_y));"
- attribute_id: 4
type: U16
on_value:
then:
- lambda: id(color_y) = (float)x/65536;
- light.control:
id: button_light
red: !lambda "return zigbee::get_r_from_xy(id(color_x), id(color_y));"
green: !lambda "return zigbee::get_g_from_xy(id(color_x), id(color_y));"
blue: !lambda "return zigbee::get_b_from_xy(id(color_x), id(color_y));"
- num: 3
device_type: DIMMABLE_LIGHT
clusters:
- id: ON_OFF
attributes:
- attribute_id: 0
type: bool
on_value:
then:
- light.control:
id: blueled
state: !lambda "return (bool)x;"
- id: LEVEL_CONTROL
attributes:
- attribute_id: 0
type: U8
value: 255
on_value:
then:
- light.control:
id: blueled
brightness: !lambda "return ((float)x)/255;"
- device_type: TEMPERATURE_SENSOR
num: 4
clusters:
- id: TEMP_MEASUREMENT
attributes:
- attribute_id: 0
type: S16
report: true
value: 100
device: i_temp
scale: 100
The device should then pair to ZHA right away. I don’t have Z2M, so you’ll have to test this, but I believe this would work just fine. This YAML configures your C6 module as a router, but you can disable that line and make this an end device, but that would be silly.
These work fine as repeaters, but their range isn’t great.
This code exposes:
- The LED strip as an RGB bulb,
- NanoC6 button as an RGB Bulb
- The blue LED as a standard ON/OFF bulb.
- The internal module temperature as a sensor
These can all be controlled via ZHA as any other LED devices. The Nano C6 Button does the following:
- One click: Hue-style color loop
- Double-click: RGBIC rainbow effect on the strip and button
- Triple-click: RGBIC chase effect on the strip and rainbow for the button
To Reset/Set to Pairing (Only needed if you fiddle with the code a bunch)
- Press the button for 3 seconds
- Release for 1 second
- Press for 3 seconds
- Release
The lights should turn off. Unplug/Plug in the NanoC6 and you’re back in pairing mode.
Feel free to adapt the code