Mit diesem ESP32-C6-MQTT-Tutorial veröffentlicht ein C6-Board in etwa fünfzehn Minuten Telemetriedaten und empfängt Befehle. Sie installieren den passenden Arduino-Core, veröffentlichen die interne Temperatur des Chips an broker.connectmq.com, schalten die Onboard-RGB-LED von Ihrem Laptop aus und erfahren, welche Gewohnheiten vom klassischen ESP32 nicht mehr gelten.
Was den ESP32-C6 anders macht
Der ESP32-C6 ist nicht einfach ein neuerer ESP32. Er nutzt eine andere CPU-Architektur und andere Funkmodule, und einige dieser Änderungen machen sich in Arduino-Sketches sofort bemerkbar.
| Merkmal | Klassischer ESP32 | ESP32-C6 |
|---|---|---|
| CPU | Dual-Core Xtensa LX6, bis 240 MHz | Single-Core RISC-V, bis 160 MHz, plus ein stromsparender RISC-V-Kern |
| WLAN | 802.11 b/g/n, 2,4 GHz | 802.11ax (Wi-Fi 6), nur 2,4 GHz |
| Bluetooth | Classic und BLE 4.2 | Nur BLE 5, kein Classic |
| 802.15.4 | Nein | Ja (Thread, Zigbee) |
| Arduino-Core | 2.x und 3.x | Nur 3.x |
| USB | Externer USB-UART-Chip | Natives USB Serial/JTAG plus UART auf den meisten DevKits |
| Onboard-LED (DevKitC-1) | Meist eine einfache LED an GPIO 2 | Adressierbare RGB-LED an GPIO 8 |
Für MQTT ergeben sich daraus folgende praktische Konsequenzen:
- Sie brauchen Arduino Core 3.x. Der C6 ist in den 2.x-Board-Paketen nicht verfügbar.
- Es gibt nur einen Anwendungskern. Code, der Tasks auf Core 1 pinnt, muss auf Core 0 umgestellt werden.
- Die serielle Schnittstelle kann an einem anderen Port erscheinen. Wenn nichts ausgegeben wird, aktivieren Sie „USB CDC On Boot“ oder stecken Sie das Kabel am UART-Port ein.
- Wi-Fi 6 ist optional, keine Voraussetzung. Der C6 verbindet sich auch mit gewöhnlichen 802.11n-Access-Points. 5-GHz-Netze sieht er weiterhin nicht.
Dem MQTT-Protokoll selbst ist all das egal. Derselbe PubSubClient-Code, der auf einem ESP32 läuft, läuft auch auf einem C6 – deshalb konzentriert sich dieses Tutorial auf die Einrichtungsdetails, über die man leicht stolpert.
Voraussetzungen
- Ein ESP32-C6-Board. Die Schritte gehen vom Espressif ESP32-C6-DevKitC-1 aus; andere C6-Boards funktionieren mit kleinen Pin-Änderungen.
- Arduino IDE 2.x.
- Das esp32-Board-Paket von Espressif Systems in Version 3.0 oder neuer aus dem Boardverwalter.
- Die Bibliothek PubSubClient von Nick O'Leary aus dem Bibliotheksverwalter.
- Die Mosquitto-Kommandozeilen-Clients auf Ihrem Rechner.
Arduino für den ESP32-C6 einrichten
- Öffnen Sie den Boardverwalter, suchen Sie nach
esp32und installieren oder aktualisieren Sie das Espressif-Paket auf eine 3.x-Version. - Wählen Sie Werkzeuge > Board > esp32 > ESP32C6 Dev Module.
- Verbinden Sie am DevKitC-1 für den einfachsten Einstieg den USB-C-Port mit der Beschriftung UART. Wenn Sie den Port mit der Beschriftung USB verwenden, setzen Sie Werkzeuge > USB CDC On Boot > Enabled, damit
Serialauf das native USB abgebildet wird. - Wählen Sie den passenden COM-Port und laden Sie einmal einen leeren Sketch hoch, um zu prüfen, ob die Toolchain funktioniert.
Schlägt der Upload mit einem Verbindungs-Timeout fehl, halten Sie BOOT gedrückt, tippen Sie kurz auf RESET, lassen Sie BOOT los und versuchen Sie es erneut. So erzwingen Sie den ROM-Bootloader.
Der ESP32-C6-MQTT-Sketch
Der Sketch veröffentlicht alle zehn Sekunden den Wert des internen Temperatursensors, die WLAN-Signalstärke und den freien Heap, abonniert ein Befehls-Topic für die LED und meldet den LED-Zustand als Retained Message.
#include <WiFi.h>
#include <PubSubClient.h>
const char* WIFI_SSID = "YOUR_WIFI_SSID";
const char* WIFI_PASSWORD = "YOUR_WIFI_PASSWORD";
const char* MQTT_HOST = "broker.connectmq.com";
const uint16_t MQTT_PORT = 1883;
const char* PREFIX = "connectmq/demo/c6x41z"; // durch eine eigene zufällige ID ersetzen
WiFiClient net;
PubSubClient mqtt(net);
String clientId;
String topicTelemetry, topicLedSet, topicLedState, topicStatus;
unsigned long lastPublish = 0;
uint8_t ledR = 0, ledG = 0, ledB = 0;
void setLed(uint8_t r, uint8_t g, uint8_t b) {
ledR = r; ledG = g; ledB = b;
rgbLedWrite(RGB_BUILTIN, r, g, b); // API von Arduino Core 3.x
char state[40];
snprintf(state, sizeof(state), "{\"r\":%u,\"g\":%u,\"b\":%u}", r, g, b);
mqtt.publish(topicLedState.c_str(), state, true);
}
void onMessage(char* topic, byte* payload, unsigned int length) {
String msg;
for (unsigned int i = 0; i < length; i++) msg += (char)payload[i];
msg.trim();
msg.toUpperCase();
Serial.printf("Command on %s: %s\n", topic, msg.c_str());
if (msg == "OFF") setLed(0, 0, 0);
else if (msg == "RED") setLed(40, 0, 0);
else if (msg == "GREEN") setLed(0, 40, 0);
else if (msg == "BLUE") setLed(0, 0, 40);
else if (msg == "WHITE") setLed(30, 30, 30);
}
void connectWifi() {
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
Serial.print("Connecting to Wi-Fi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.printf("\nIP %s, RSSI %d dBm\n", WiFi.localIP().toString().c_str(), WiFi.RSSI());
}
void connectMqtt() {
while (!mqtt.connected()) {
Serial.print("Connecting to MQTT... ");
if (mqtt.connect(clientId.c_str(), topicStatus.c_str(), 1, true, "offline")) {
Serial.println("connected");
mqtt.publish(topicStatus.c_str(), "online", true);
mqtt.subscribe(topicLedSet.c_str(), 1);
} else {
Serial.printf("failed, state %d, retrying in 5 s\n", mqtt.state());
delay(5000);
}
}
}
void setup() {
Serial.begin(115200);
delay(500);
clientId = "esp32c6-" + String((uint32_t)ESP.getEfuseMac(), HEX);
topicTelemetry = String(PREFIX) + "/telemetry";
topicLedSet = String(PREFIX) + "/led/set";
topicLedState = String(PREFIX) + "/led/state";
topicStatus = String(PREFIX) + "/status";
connectWifi();
mqtt.setServer(MQTT_HOST, MQTT_PORT);
mqtt.setCallback(onMessage);
mqtt.setBufferSize(512);
connectMqtt();
setLed(0, 0, 0);
}
void loop() {
if (WiFi.status() != WL_CONNECTED) connectWifi();
if (!mqtt.connected()) connectMqtt();
mqtt.loop();
if (millis() - lastPublish >= 10000) {
lastPublish = millis();
char payload[160];
snprintf(payload, sizeof(payload),
"{\"chipTemp\":%.1f,\"rssi\":%d,\"freeHeap\":%lu,\"uptime\":%lu}",
temperatureRead(), WiFi.RSSI(),
(unsigned long)ESP.getFreeHeap(), millis() / 1000);
mqtt.publish(topicTelemetry.c_str(), payload);
Serial.println(payload);
}
}
Der interne Temperatursensor misst den Chip selbst, nicht den Raum, rechnen Sie also mit Werten einige Grad über der Umgebungstemperatur. Als Zustandssignal und als Demowert ganz ohne Verdrahtung ist er dennoch nützlich.
ESP32-C6-MQTT-Nachrichten testen
Öffnen Sie ein Terminal und abonnieren Sie alles unterhalb Ihres Präfixes:
mosquitto_sub -h broker.connectmq.com -p 1883 -i c6-viewer-x41z -t "connectmq/demo/c6x41z/#" -v
Sie sollten status online, den gespeicherten LED-Zustand und alle zehn Sekunden eine Telemetrie-Nachricht sehen. Senden Sie in einem zweiten Terminal einen Befehl:
mosquitto_pub -h broker.connectmq.com -p 1883 -i c6-cmd-x41z -t "connectmq/demo/c6x41z/led/set" -m "green" -q 1
Die RGB-LED leuchtet grün, und ein neuer gespeicherter Zustand erscheint. Weil der Zustand retained ist, erfährt jeder Client, der sich später anmeldet, sofort die aktuelle Farbe. Der öffentliche MQTT-Broker von ConnectMQ braucht kein Konto, ist aber für alle sichtbar – verwenden Sie also nur Demodaten und keine produktiven Daten. Die Seite zum öffentlichen MQTT-Broker erklärt seine Grenzen, darunter 10 Nachrichten pro Sekunde und Client.
Klassischen ESP32-Code auf den C6 portieren
Die meisten Sketches kompilieren unverändert. Diese Anpassungen benötigen Sie am wahrscheinlichsten:
- Task-Pinning. Ersetzen Sie
xTaskCreatePinnedToCore(..., 1)durch Core 0 oder rufen SiexTaskCreateauf. Die Anleitung zu ESP32 FreeRTOS MQTT zeigt eine Task-Aufteilung, die mit dieser einen Änderung auf beiden Chipfamilien funktioniert. - LED-Pins.
digitalWrite(2, HIGH)bringt auf einem DevKitC-1 nichts zum Leuchten. Verwenden SiergbLedWrite(RGB_BUILTIN, r, g, b). - ADC-Pins. Der C6 hat einen einzigen ADC an GPIO 0 bis 6. Pin-Nummern wie 34 oder 36 aus Beispielen für den klassischen ESP32 gibt es nicht.
- Veraltete APIs. Core 3.x hat mehrere Funktionen umbenannt oder entfernt, zum Beispiel wurde aus
neopixelWritenunrgbLedWrite, und die LEDC-PWM-API wurde aufledcAttachumgestellt. Gleichen Sie Compiler-Fehler mit den Migrationshinweisen in der Arduino-ESP32-Dokumentation ab. - Bluetooth Classic.
BluetoothSerialwird nicht unterstützt. Verwenden Sie stattdessen BLE.
Wenn Sie mit PlatformIO bauen, wählen Sie eine Plattformversion, die Arduino Core 3.x für den C6 mitbringt; das PlatformIO-MQTT-Setup führt durch eine reproduzierbare Projektdatei.
Fehlerbehebung
mqtt.state()liefert -2. Die TCP-Verbindung ist fehlgeschlagen. Prüfen Sie, ob das Board tatsächlich eine IP-Adresse hat und ob Ihr Netzwerk ausgehende Verbindungen auf Port 1883 erlaubt. Manche Gastnetze blockieren ihn; versuchen Sie es stattdessen mit Port 8883 und TLS.mqtt.state()liefert 2. Der Broker hat die Client ID abgelehnt. Auf dem öffentlichen MQTT-Broker muss sie nicht leer und eindeutig sein, was das Suffix aus der eFuse-MAC sicherstellt.- Verbindet sich und bricht dann alle paar Sekunden ab. Zwei Geräte verwenden dieselbe Client ID, und jede neue Verbindung wirft die andere hinaus. Das passiert häufig, wenn Sie dieselbe fest eingetragene ID auf zwei Boards flashen.
- WLAN verbindet sich nie mit einem Wi-Fi-6-Router. Stellen Sie sicher, dass das 2,4-GHz-Band aktiviert ist und nicht durch eine Band-Steering-Einstellung verdeckt wird, die Clients ausschließlich ins 5-GHz-Band drängt. Auch reine WPA3-Netze können Probleme verursachen; probieren Sie den gemischten Modus WPA2/WPA3.
- Keine serielle Ausgabe. Schalten Sie USB CDC On Boot um oder wechseln Sie zum UART-Port.
Mit einem Cloud-Broker in die Produktion
Für echte Geräte wechseln Sie auf TLS über Port 8883 mit Zugangsdaten. Erstellen Sie einen Broker unter app.connectmq.com und kopieren Sie den generierten Benutzernamen, das Passwort und die Client ID. Ersetzen Sie WiFiClient durch WiFiClientSecure, laden Sie das Zertifikat ISRG Root X1 mit net.setCACert(...), setzen Sie den Port auf 8883 und übergeben Sie die Zugangsdaten an mqtt.connect("YOUR_CLIENT_ID", "YOUR_USERNAME", "YOUR_PASSWORD", ...). Der C6 bewältigt den TLS-Handshake problemlos, auch wenn er etwas länger dauert als auf einem klassischen ESP32 mit 240 MHz.
Anschließend zeigt der Live-Topic-Explorer im Portal die Nachrichten Ihres C6 beim Eintreffen an, und die Geräteansicht gruppiert Boards nach Standort und Linie, wenn Sie Topic-Namen im ISA-95-Stil verwenden. Diese Hierarchie aus Enterprise, Site, Area, Line und Cell bildet zugleich die Struktur eines Unified Namespace (UNS), etwa acme/werk-muenchen/montage/linie-1/zelle-3/temperatur; der Beitrag zu Sparkplug B und dem Unified Namespace erklärt das Konzept. Wenn Sie neu bei Brokern sind, bietet die Aufgaben eines MQTT Brokers eine kurze Einführung, und das ESP32-IoT-Tutorial listet alle Projekte dieser Reihe auf.
Betreiben Sie Ihre ESP32-C6-Flotte mit ConnectMQ
Der ESP32-C6 ist eine starke Wahl für neue Designs: Wi-Fi-6-Effizienz, BLE 5 und eine moderne Toolchain. Kombinieren Sie ihn mit einem Cloud-MQTT-Broker, den Sie nicht selbst betreiben müssen. ConnectMQ bietet Ihnen TLS auf Port 8883, MQTT 3.1.1 und 5.0 sowie einen kostenlosen Serverless-Plan ohne Kreditkarte, sodass Sie in wenigen Minuten vom öffentlichen MQTT-Broker zu authentifizierten Geräten wechseln. Wenn Sie MQTT-5-Properties auf dem C6 nutzen möchten, ist ESP-IDF der richtige Weg; lesen Sie dazu esp-mqtt mit MQTT 5.
Häufig gestellte Fragen
Unterstützt der ESP32-C6 MQTT über Wi-Fi 6?
Ja. MQTT läuft über TCP und funktioniert daher mit jedem WLAN-Standard, den der C6 unterstützt, einschließlich 802.11ax im 2,4-GHz-Band. Wi-Fi 6 hilft vor allem bei der Energieeffizienz und in überfüllten Netzen.
Kann ich auf dem C6 Thread oder Zigbee nutzen, um einen MQTT Broker zu erreichen?
Das Funkmodul des C6 unterstützt 802.15.4, doch MQTT benötigt einen IP-Pfad zum Broker. Ein Thread-Netz braucht einen Border Router, und Zigbee-Geräte benötigen meist ein Gateway, das nach MQTT übersetzt.
Warum kompiliert mein alter ESP32-Sketch nicht für den C6?
Der C6 erfordert Arduino Core 3.x, in dem sich mehrere APIs geändert haben, und ihm fehlen Bluetooth Classic und der zweite Kern. Aktualisieren Sie umbenannte Funktionen und entfernen Sie das Pinning auf Core 1.
Ist der interne Temperatursensor genau genug für die Raumtemperatur?
Nein. Er misst den Chip und ist wärmer als der Raum. Verwenden Sie für Umgebungswerte einen externen Sensor wie DHT22 oder BME280.



