Hoy en Chile es normal tener un parlante con Alexa, un Google Nest o un iPhone con la app Casa, y casi siempre cada uno vive en su propio mundo: la ampolleta que compraste para Google no aparece en Alexa y viceversa. Matter es el estándar que rompe ese encierro, y lo mejor es que un ESP32 de bajo costo puede hablarlo sin librerías extra. En esta guía vas a convertir un ESP32 en una luz Matter de encendido y apagado que responde a Alexa, Apple Home, Google Home, Home Assistant y SmartThings al mismo tiempo.

Al terminar vas a saber qué chip ESP32 conviene para Matter y por qué, cómo funciona el sketch oficial de Espressif línea por línea, cómo emparejar (comisionar) el dispositivo con un código QR y cómo compartirlo entre varias plataformas. También vas a tener una lista de las fallas típicas de las redes domésticas chilenas que impiden que el emparejamiento termine.

El concepto: Matter en cinco palabras

Antes de tocar código conviene manejar el vocabulario, porque los mensajes del monitor serial y de las apps lo usan todo el tiempo.

  • Nodo: el dispositivo físico. En este proyecto, tu ESP32.
  • Endpoint: una función dentro del nodo. Un mismo ESP32 podría exponer una luz y un sensor de temperatura como dos endpoints distintos.
  • Cluster: el grupo de atributos y comandos de una función. La luz usa el cluster On/Off, con el atributo OnOff y los comandos On, Off y Toggle.
  • Fabric: la red lógica que arma cada controlador (Alexa, Apple Home, Google Home) cuando acepta tu dispositivo. Un nodo puede pertenecer a varios fabrics a la vez.
  • Comisionar: el proceso de sumar el nodo a un fabric, con un código QR o un código manual de 11 dígitos.

Topología general de Matter con un ESP32 como nodo y varios controladores

Lo que hace distinto a Matter de las soluciones de cada marca es que el control es local: la orden de encender viaja por tu red WiFi sobre IPv6, cifrada, sin pasar por un servidor en el extranjero. Si se cae internet, la luz sigue respondiendo desde la app mientras el controlador y el ESP32 estén en la misma red. La nube queda para el acceso remoto y las rutinas.

El ciclo de vida de un dispositivo Matter

El dispositivo pasa por cinco estados, y entenderlos te ahorra horas cuando algo falla:

  1. Sin comisionar: primer arranque o después de un reseteo. El ESP32 imprime su QR y su código manual.
  2. Comisionando: el controlador abre una sesión segura (PASE), confirma que es un dispositivo Matter y le entrega las credenciales WiFi, normalmente por Bluetooth LE.
  3. En la red: el ESP32 se conecta al WiFi y se anuncia por mDNS con una dirección IPv6.
  4. Operación normal: los controladores lo descubren y lo controlan con mensajes cifrados.
  5. Multiadmin (opcional): desde la primera app generas un código temporal nuevo y sumas el mismo nodo a otra plataforma.

Diagrama del flujo típico de un dispositivo Matter, desde sin comisionar hasta multiadmin

Qué ESP32 elegir (y por qué el C6 es la mejor opción)

No todos los ESP32 hacen lo mismo con Matter. La diferencia clave es CHIPoBLE: la capacidad de recibir las credenciales WiFi por Bluetooth desde la app, que es como funciona cualquier ampolleta Matter comercial. Con el núcleo Arduino precompilado, el ESP32 clásico y el S2 no lo tienen, así que en esas placas escribes el nombre y la clave de tu red en el sketch.

Chip Cómo se comisiona CHIPoBLE
ESP32 WiFi, red escrita en el sketch No
ESP32-S2 WiFi, red escrita en el sketch No
ESP32-S3 WiFi, credenciales desde el controlador Sí
ESP32-C3 WiFi, credenciales desde el controlador Sí
ESP32-C5 WiFi, credenciales desde el controlador Sí
ESP32-C6 WiFi, credenciales desde el controlador Sí
ESP32-H2 Thread, credenciales desde el controlador Sí

¿Por qué recomendamos el ESP32-C6? Porque combina WiFi 6 en 2,4 GHz, Bluetooth LE 5 y una radio 802.15.4, la misma que usa Thread. Hoy lo usas por WiFi, pero el día que tengas un border router Thread (un HomePod mini, un Nest Hub de segunda generación o un Echo de cuarta generación cumplen ese rol) la misma placa puede pasar a Thread y consumir bastante menos. El ESP32 clásico funciona, pero te obliga a dejar la clave del WiFi escrita en el código y no te deja ese camino abierto.

Un detalle de memoria que explica un paso posterior: la pila de Matter es pesada. Entre el protocolo, el cifrado y el Bluetooth, el binario supera con facilidad los 1,3 MB de la partición por defecto de Arduino, y por eso hay que elegir el esquema de particiones "Huge APP".

Hardware: el LED de la placa o uno externo

El sketch controla un pin digital, así que el montaje mínimo es la placa sola conectada por USB: usa el LED que trae incorporado (LED_BUILTIN) y el botón BOOT como interruptor local. No necesitas instalar ninguna librería: desde la versión 3.1.0 del núcleo ESP32 para Arduino, la librería Matter viene incluida.

Si quieres ver una luz de verdad sobre la mesa, agrega un LED de 5 mm en la protoboard: el ánodo (pata larga) va al pin que elijas a través de una resistencia de 220 Ω, y el cátodo va a GND. Con 3,3 V de salida y un LED rojo (unos 2 V de caída), esa resistencia deja pasar del orden de 6 mA, que el GPIO entrega sin problema.

Ojo con el LED incorporado de la Seeed Studio XIAO ESP32-C6: está cableado en lógica inversa (se enciende con nivel bajo). Con el sketch tal como viene vas a ver la luz apagada cuando la app dice "encendida". Tienes dos salidas: usar el LED externo o cambiar las escrituras del callback para invertir el nivel. Para usar el LED externo, reemplaza el bloque #ifdef LED_BUILTIN por una sola línea con tu pin fijo, por ejemplo const uint8_t ledPin = D2;.

Software: el sketch de luz On/Off

El ejemplo se basa en la librería oficial Matter de Espressif para Arduino. Convierte la placa en un nodo con un endpoint de luz On/Off, guarda el último estado en memoria no volátil y permite controlar la luz con el botón BOOT.

C++
/*
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete project details at https://RandomNerdTutorials.com/esp32-matter-on-off-light/

  Copyright 2025 Espressif Systems (Shanghai) PTE LTD. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
*/
#include <Arduino.h>
#include <Matter.h>
#include <Preferences.h>

// Wi-Fi credentials for this sketch. Fill these in when the board cannot commission over BLE (Arduino prebuild on ESP32 / ESP32-S2): the sketch
// joins the AP itself. When Matter commissions over BLE (CHIPoBLE), the hub sends SSID and password — leave the placeholders; they are unused.
#define WIFI_SSID     "your-ssid"
#define WIFI_PASSWORD "your-password"

// List of Matter Endpoints for this Node
// On/Off Light Endpoint
MatterOnOffLight OnOffLight;

// it will keep last OnOff state stored, using Preferences
Preferences matterPref;
const char *onOffPrefKey = "OnOff";

// set your board LED pin here
#ifdef LED_BUILTIN
  const uint8_t ledPin = LED_BUILTIN;
#else
  const uint8_t ledPin = 2;  // Set your pin here if your board has not defined LED_BUILTIN
  #warning "Do not forget to set the LED pin"
#endif

// set your board USER BUTTON pin here
const uint8_t buttonPin = BOOT_PIN;  // Set your pin here. Using BOOT Button.
MatterButton button;

// Matter Protocol Endpoint Callback
bool setLightOnOff(bool state) {
  Serial.printf("User Callback :: New Light State = %s\r\n", state ? "ON" : "OFF");
  if (state) {
    digitalWrite(ledPin, HIGH);
  } else {
    digitalWrite(ledPin, LOW);
  }
  // store last OnOff state for when the Light is restarted / power goes off
  matterPref.putBool(onOffPrefKey, state);
  // This callback must return the success state to Matter core
  return true;
}

void setup() {
  // Initialize the USER BUTTON (Boot button) GPIO that will act as a toggle switch
  button.begin(buttonPin);
  // Initialize the LED (light) GPIO and Matter End Point
  pinMode(ledPin, OUTPUT);

  Serial.begin(115200);

// CONFIG_ENABLE_CHIPOBLE=n: sketch starts Wi-Fi here; with CHIPoBLE the hub delivers credentials.
#if !CONFIG_ENABLE_CHIPOBLE
  matterConnectWiFi(WIFI_SSID, WIFI_PASSWORD);
#endif

  // Initialize Matter EndPoint
  matterPref.begin("MatterPrefs", false);
  bool lastOnOffState = matterPref.getBool(onOffPrefKey, true);
  OnOffLight.begin(lastOnOffState);
  OnOffLight.onChange(setLightOnOff);

  // Matter beginning - Last step, after all EndPoints are initialized
  Matter.begin();
  matterWaitUntilReady();
  Serial.printf("Initial state: %s\r\n", OnOffLight.getOnOff() ? "ON" : "OFF");
  OnOffLight.updateAccessory();
}

void loop() {
  matterRestartIfNoFabric();

  matterButtonEvent_t ev;
  while ((ev = button.poll()) != MATTER_BUTTON_NONE) {
    if (ev == MATTER_BUTTON_CLICK) {
      Serial.println("User button released. Toggling Light!");
      OnOffLight.toggle();
    } else if (ev == MATTER_BUTTON_LONG_HOLD) {
      Serial.println("Decommissioning the Light Matter Accessory. It shall be commissioned again.");
      OnOffLight.setOnOff(false);
      Matter.decommission();
    }
  }
}

Qué hace cada parte

Las librerías. Matter.h trae toda la pila del protocolo. Preferences.h guarda el último estado en la NVS, la zona de la flash que sobrevive a los reinicios, para que la luz vuelva como estaba después de un corte de luz.

Las credenciales. Solo se usan si la placa no puede comisionar por Bluetooth (ESP32 clásico o S2 con el núcleo precompilado). En ese caso, completa estas dos líneas con el nombre y la clave de tu red de 2,4 GHz:

C++
#define WIFI_SSID "REPLACE_WITH_YOUR_SSID";
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD";

Con CHIPoBLE (C3, C6, S3), la app le pasa la red al ESP32 y estas líneas quedan sin uso.

El endpoint. MatterOnOffLight OnOffLight; crea el endpoint que implementa el cluster On/Off estándar. Es lo que Alexa o Google ven como "una luz".

El callback setLightOnOff(). Cada vez que un controlador cambia el estado, Matter llama a esta función con el valor nuevo. Ahí se escribe el pin y se guarda el estado con matterPref.putBool(). Que devuelva true es importante: le confirma a la pila que el cambio se aplicó; si devolviera false, el controlador mostraría un error.

El orden dentro de setup(). Primero se inicializan el botón, el pin y el puerto serial. Después se lee el último estado guardado (por defecto encendido), se arranca el endpoint con ese estado y se registra el callback. Matter.begin() va al final, cuando ya existen todos los endpoints, porque la pila anuncia al mundo lo que el nodo tiene en ese momento. matterWaitUntilReady() espera a que todo esté listo y updateAccessory() sincroniza el LED con el estado.

El loop(). matterRestartIfNoFabric() revisa si el nodo sigue perteneciendo a algún fabric; si no, reinicia la pila para que vuelva a anunciarse y lo puedas comisionar de nuevo. Después, button.poll() lee el botón sin bloquear: un clic corto alterna la luz y avisa del nuevo estado a todos los controladores, y mantenerlo apretado más de 5 segundos apaga la luz y ejecuta Matter.decommission(), que borra los fabrics (un reseteo de fábrica).

Subir el código a la placa

  1. En Herramientas > Placa > ESP32 Arduino elige tu placa (por ejemplo, ESP32C6 Dev Module o XIAO_ESP32C6).
  2. En Herramientas > Partition Scheme selecciona "Huge APP (3MB No OTA/1MB SPIFFS)". Sin este paso la compilación falla por tamaño.

Menú Herramientas del Arduino IDE con el esquema de particiones Huge APP seleccionado

  1. Antes de la primera carga activa Herramientas > Erase All Flash Before Sketch Upload: Enabled. Así borras credenciales WiFi y fabrics de pruebas anteriores. Repítelo cada vez que un comisionado falle a medias.

Opción Erase All Flash Before Sketch Upload activada en el Arduino IDE

  1. Con la placa conectada y el puerto correcto elegido, presiona Subir. Si tu placa no muestra el esquema "Huge APP" en el menú, elige la definición genérica del chip (ESP32C6 Dev Module) y vuelve a buscarlo.

Comisionar el ESP32

Abre el monitor serial a 115200 baudios y presiona el botón RST/EN. En el primer arranque, el ESP32 imprime el código manual de emparejamiento de 11 dígitos y una URL que genera el QR.

Monitor serial del Arduino IDE con el código manual de emparejamiento y la URL del código QR

Al abrir esa URL en el navegador ves el QR que vas a escanear desde la app.

Código QR de emparejamiento Matter abierto en el navegador

Con Amazon Alexa

  1. Abre la app Alexa y toca el ícono +.

App Alexa con el botón para agregar un dispositivo

  1. Elige Agregar dispositivo.

Menú de la app Alexa con la opción Agregar dispositivo

  1. Selecciona el logo de Matter o la opción Otro.

Pantalla de Alexa para elegir el tipo de dispositivo, con la opción Matter

  1. Cuando pregunte si el dispositivo tiene el logo de Matter, responde Sí, y escanea el QR o escribe el código manual.

Pantalla de Alexa que pregunta si el dispositivo tiene logo Matter

  1. Con el teléfono cerca del ESP32 (el primer tramo va por Bluetooth), toca Conectar.

Pantalla de Alexa con el botón Conectar para enlazar la placa

  1. La app avisa que el dispositivo no está certificado. Es normal en un proyecto propio: confirma con Sí para agregarlo igual.

Aviso de Alexa de dispositivo no certificado con la opción de agregarlo

  1. Cuando lo encuentre y conecte, toca Siguiente.

Pantalla de Alexa que confirma el dispositivo encontrado y conectado

En el monitor serial aparece el mensaje de que el nodo quedó comisionado y el LED refleja el estado actual.

Monitor serial con el mensaje de nodo Matter comisionado en Alexa

La luz queda en tu lista de dispositivos, lista para usarla desde la app o por voz.

Lista de dispositivos de Alexa con la luz Matter del ESP32

Con Apple Home, Google Home, Home Assistant o SmartThings

  • Apple Home: app Casa > + > Agregar accesorio > escanea el QR o toca "Más opciones" para el código manual.
  • Google Home: app Google Home > + > Configurar dispositivo > Dispositivo nuevo > Dispositivo Matter > QR o código manual.
  • Home Assistant: Configuración > Dispositivos y servicios > Agregar integración > Matter > QR o código manual.
  • SmartThings: app SmartThings > + > Dispositivos de socios > Matter > QR o código manual.

Para todos necesitas el controlador correspondiente funcionando en tu casa (un parlante Echo, un Nest, un HomePod o tu servidor de Home Assistant).

Multiadmin: el mismo ESP32 en dos plataformas

El QR original sirve una sola vez. Para sumar el ESP32 a una segunda plataforma, abre una ventana de comisionado nueva desde la app donde ya está (la opción se llama Compartir, Activar modo de emparejamiento o Vincular con otra plataforma, según la app). Esa app genera un código temporal, y con ese código lo agregas a la otra. El nodo queda en dos fabrics y responde a ambas.

Pruebas

Desde la app (o por voz: "Alexa, enciende la luz del escritorio") el GPIO cambia de estado y el cambio queda guardado aunque la placa se reinicie.

Control de la luz Matter del ESP32 con el botón de encendido de la app

El botón BOOT también funciona como interruptor local: un toque corto alterna la luz y todas las apps ven el cambio. Mantenlo más de 5 segundos y el ESP32 se resetea de fábrica: tendrás que comisionarlo de nuevo.

Demostración de la luz Matter del ESP32 controlada por voz, por la app y por el botón de la placa

Diagnóstico: lo que suele fallar

Síntoma Causa probable Qué hacer
"Sketch too large" al compilar Partición por defecto Elige "Huge APP" en Partition Scheme
Nunca aparece el código de emparejamiento Credenciales mal escritas (ESP32 clásico o S2) Revisa la red y la clave del sketch
Falla el comisionado después de un intento anterior Quedaron datos de un fabric viejo Mantén BOOT 5 segundos o borra la flash al subir
No sale nada por el monitor serial El mensaje se imprimió antes de abrir el monitor Presiona RST/EN con el monitor abierto a 115200
La app encuentra el dispositivo pero no termina Red de 5 GHz o router que bloquea mDNS/IPv6 Mira los consejos de abajo

Dos problemas de redes domésticas que el tutorial original no cubre y que en Chile aparecen seguido:

  • Router con una sola red para 2,4 y 5 GHz. Muchos routers de las compañías de internet juntan ambas bandas con el mismo nombre. El ESP32 solo usa 2,4 GHz. Si el comisionado se cae en el paso de red, separa las bandas desde la configuración del router o crea una red de invitados solo en 2,4 GHz.
  • IPv6 o multicast desactivado. Matter usa IPv6 de enlace local y mDNS para descubrir dispositivos. Si el router tiene apagado IPv6 en la red local o filtra el multicast (algunos lo llaman "aislamiento de clientes" o "AP isolation"), el controlador no encuentra al ESP32 después de entregarle la red.

Los mensajes como "sending failed", "transient send error" o "request on unknown cluster" en el monitor serial son normales durante el arranque y no indican un problema mientras el dispositivo responda.

Variantes y mejoras

  • Controlar una lámpara real con un relé. Cambia el LED por un módulo relé de 5 V con optoacoplador y tendrás un interruptor Matter para una lámpara de velador. Ojo: el relé maneja 220 V; si nunca has trabajado con red eléctrica, pide ayuda a alguien con experiencia y deja todo dentro de una caja cerrada.
  • Pasar a Thread. Con un ESP32-C6 o un ESP32-H2 y un border router Thread en casa, el mismo endpoint funciona por Thread y deja libre tu WiFi. Es el camino para un nodo a batería.
  • Sumar un segundo endpoint. Un mismo nodo puede exponer, además de la luz, un sensor de temperatura con un DHT22 o un BME280. En las apps aparecen como dos dispositivos, pero es un solo ESP32 y un solo comisionado.

Personalización para Chile

En Chile consigues todo lo necesario en MechatronicStore:

  • Seeed Studio XIAO ESP32-C6 (SKU GS3-5): la placa recomendada. Tiene WiFi 6, Bluetooth LE para CHIPoBLE y radio Thread, y cabe en cualquier caja de interruptor.
  • ESP32 con Wifi y Bluetooth ESP WROOM-32 Micro USB (SKU N-303): sirve si ya tienes uno; recuerda escribir la red en el sketch, porque el clásico no comisiona por Bluetooth.
  • Cable USB Tipo C a USB Tipo A 1mt (SKU B-101): para programar la XIAO. Tiene que ser de datos, no solo de carga.
  • LED 5mm rojo (SKU GA1-5) y Resistencias 1/4W 1 unidad 220Ω (SKU GK1-18): la luz externa, para ver el estado sin la lógica inversa del LED de la XIAO.
  • Breadboard / Protoboard 830 puntos MB102 (SKU C-302) y Cables macho macho 30cm (SKU C-417): para montar el LED sin soldar.

Si en el tutorial original usan un ESP32-S3 DevKit, la XIAO ESP32-C6 cumple la misma función y suma Thread. El controlador Matter (Echo, HomePod, Nest o Home Assistant) lo usas tal como ya lo tengas en casa.

Recursos

Versión chilena con componentes en stock local.