← Blog Cloud

TinyML auf dem ESP32-S3: TensorFlow Lite Micro für Edge-KI-Inferenz

Das Verkaufsargument für Edge-ML war früher eine vage Handbewegung: geringere Latenz, besserer Datenschutz, weniger Bandbreite. Heute ist das Verkaufsargument ein Datenblatt. Ein ESP32-S3 mit Vektorbefehlen und 8 MB PSRAM kann ein quantisiertes Faltungsmodell in wenigen zehn Millisekunden ausführen und dabei im Durchschnitt nur einstellige Milliampere verbrauchen. Das verändert, was Sie in einen batteriebetriebenen Sensor, ein Yacht-Kabinenpanel oder einen Hotel-Zutrittstoken packen können. Dieser Artikel ist ein praxisorientierter Leitfaden für Ingenieure zum Einsatz von TensorFlow Lite Micro auf dem ESP32-S3 – mit zwei echten Beispielen, Keyword-Spotting und Beschleunigungssensor-Anomalieerkennung, und Benchmarks, an denen Sie sich messen können.

Warum Edge-ML jetzt wichtig ist

Vier Randbedingungen verlagern die Inferenz an den Rand des Netzwerks. Latenz, weil das Hin- und Herschicken von Audio- oder Vibrationsdaten an ein Cloud-Modell 200-2000 ms hinzufügt, die Sie für eine geschlossene Regelschleife nicht haben. Datenschutz, weil der sauberste Weg zur Einhaltung der DSGVO oder der Datennormen im Gastgewerbe darin besteht, das Rohsignal niemals zu bewegen. Bandbreite, weil eine Flotte von zehntausend Vibrationssensoren, die Roh-IMU-Daten mit 1 kHz streamen, jede vernünftige Rückführung sättigt. Und Offline-Betrieb, weil Boote, Fabriken und abgelegene Installationen keine Konnektivität voraussetzen können.

Der Gegendruck war immer die Rechenleistung. Der klassische ESP32 konnte Spielzeugmodelle bewältigen. Der ESP32-S3 hat die Rechnung verändert. Der S3 fügte einen Vektorbefehlssatz hinzu (PIE – Processor Instruction Extension), der die Multiply-Accumulate-Operationen beschleunigt, die im Kern jedes neuronalen Netzes stehen, und unterstützt bis zu 8 MB oktalen PSRAM für Modell- und Tensor-Arena-Speicher. Wir setzen inzwischen routinemäßig Modelle von 200-500 kB ein, die auf dem ursprünglichen ESP32 lächerlich gewesen wären, und führen sie schnell genug aus, dass das Funkmodul der dominierende Stromverbraucher ist, nicht die Rechenleistung.

ESP32-S3-Fähigkeiten, die man kennen sollte

  • Zwei Xtensa-LX7-Kerne mit 240 MHz, jeweils mit der PIE-Vektoreinheit.
  • Bis zu 8 MB oktaler PSRAM mit 80 MHz, adressierbar für Tensor-Arena und Modellgewichte.
  • Bis zu 16 MB Flash für Modellspeicherung und OTA-Partitionen.
  • USB-OTG für die direkte Host-Verbindung ohne externe Bridge – nützlich für die Entwicklung und für Produkte, die als USB-Peripheriegeräte ausgeliefert werden.
  • Hardwarebeschleunigtes SHA, AES, RSA und ECC – dieselben Engines, die Ihre TLS-Sitzungen absichern, lassen sich für Modell-Integritätsprüfungen wiederverwenden.

Die zwei Kerne sind entscheidend. Wir binden die TFLite-Micro-Inferenz typischerweise an Kern 1 und lassen Kern 0 für Networking, Sensorabtastung und das Betriebssystem frei. Diese Trennung verhindert, dass Inferenz-Jitter Ihre TLS-Handshakes oder Ihre MQTT-Keepalives durcheinanderbringt. Wenn Sie eine Auffrischung zur Wahl zwischen den ESP32-Familienmitgliedern und STM32 benötigen, behandelt unser ESP32-vs-STM32-Leitfaden die Abwägungen ausführlich.

Framework-Wahl: TFLite Micro, Edge Impulse, ONNX

Drei ernstzunehmende Optionen für ESP32-Klasse-Ziele. Sie schließen sich nicht gegenseitig aus – wir haben Produkte ausgeliefert, die Edge Impulse für die Entwicklung und TFLite Micro für den Produktiveinsatz verwenden.

  • TensorFlow Lite Micro ist die Option auf der untersten Ebene. Sie bringen ein .tflite-Modell mit, binden die Laufzeit ein, registrieren Ihren Op-Resolver und rufen Invoke() auf. Maximale Kontrolle, maximaler Boilerplate-Code, kleinster Footprint. Das setzen wir in der Produktion für performancekritische Pfade ein.
  • Edge Impulse verpackt TFLite Micro (und andere Backends) in einen vollständigen MLOps-Workflow – Datenerfassung, Labeling, Training, Deployment als C++-Bibliothek. Hervorragend, um in Tagen statt Wochen vom Sensor zum Modell zu gelangen. Etwas größerer Binär-Footprint und eine vorgegebene Struktur.
  • ONNX Runtime für Embedded ist der neueste Zugang auf dieser Hardwareklasse. Nützlich, wenn Ihr Data-Science-Team in PyTorch lebt und ONNX exportiert. Die Operator-Abdeckung ist auf Xtensa noch schmaler als bei TFLite.

Für neue Projekte mit interner ML-Kapazität setzen wir standardmäßig auf TFLite Micro. Für Teams ohne dedizierte ML-Ingenieure zahlt sich Edge Impulse aus. Das Deployment-Artefakt ist in beiden Fällen eine statische Bibliothek, die Sie in Ihren Firmware-Build einbinden, genauso wie Sie jede andere Komponente in Ihrem Connected-Devices-Projekt einbinden würden.

Modellgrößen-Budgets

Drei Zahlen bestimmen, was Sie ausliefern können: Flash für das Modell, RAM für die Tensor-Arena und Millisekunden pro Inferenz. Realistische Budgets auf dem ESP32-S3 mit PSRAM:

  • Modellgewichte: 50-500 kB im Flash für INT8-Modelle, mehr, wenn Sie freie Partitionen haben.
  • Tensor-Arena: 30-300 kB im PSRAM für Aktivierungstensoren. Verwenden Sie MicroInterpreter::arena_used_bytes() nach dem ersten Invoke(), um präzise zu dimensionieren.
  • Inferenzzeit: 5-150 ms je nach Modellarchitektur. Alles über 200 ms legt nahe, dass Sie die Modelltopologie überdenken sollten, nicht die Hardware.

Die Tensor-Arena ist die Variable, die die Leute überrascht. Allokieren Sie sie im PSRAM, nicht im internen SRAM, es sei denn, die Inferenzzeit wird durch die Speicherbandbreite dominiert und Sie haben es gemessen. PSRAM-Zugriff ist langsamer als SRAM, aber in Bezug auf die verfügbare Kapazität deutlich günstiger. Die Einbuße ist real, aber vorhersehbar, und sie verliert fast immer gegen das Ausgehen des internen RAM zum denkbar schlechtesten Zeitpunkt.

Quantisierung: INT8 ist der Standard, INT4 ist die Grenze

Float32-Modelle sind auf dieser Hardwareklasse nicht einsetzbar. INT8-Quantisierung, mit repräsentativen Daten durchgeführt, kostet typischerweise 1-3 Prozentpunkte an Genauigkeit im Austausch gegen 4x kleinere Modelle und 2-4x schnellere Inferenz. Wir verwenden TensorFlows Post-Training-Quantisierung mit einem repräsentativen Datensatz von 100-500 Samples aus der tatsächlichen Einsatzverteilung.

# Python: post-training INT8 quantization with representative data
converter = tf.lite.TFLiteConverter.from_saved_model("saved_model")
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.representative_dataset = lambda: (
    [sample.astype(np.float32)] for sample in calibration_samples
)
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.int8
converter.inference_output_type = tf.int8
tflite_model = converter.convert()
open("model_int8.tflite", "wb").write(tflite_model)

INT4-Quantisierung ist real und wird 2026 ausgeliefert, aber die Operator-Abdeckung auf TFLite Micro ist noch teilweise. Wir setzen INT4 selektiv für sehr große Modelle ein, bei denen der Größengewinn den Engineering-Aufwand wert ist. Für den Keyword-Spotter und den Anomaliedetektor unten ist INT8 die richtige Antwort.

Beispiel eins: Keyword-Spotting

Wake-Word-Erkennung ist die kanonische TinyML-Demo, weil sie die vollständige Pipeline durchläuft – Audioaufnahme, Merkmalsextraktion, neuronales Netz, Entprellung – in einem Footprint, der überall passt. Unsere Referenzarchitektur für einen Sprachsteuerungs-Puck im Hotelzimmer:

  1. I2S-Mikrofon-Abtastung mit 16 kHz, 16 Bit mono.
  2. Gleitendes Fenster von 1 Sekunde, das alle 200 ms weiterspringt.
  3. MFCC-Merkmalsextraktion: 40 Mel-Bins, 49 Frames pro Fenster.
  4. Kleines CNN: 4 tiefentrennbare Faltungsblöcke, ~80 kB INT8.
  5. Posterior-Glättung über 3 Fenster, Schwellwert 0,85.

Der Inferenzaufruf selbst ist unkompliziert, sobald das Modell und die Ops registriert sind:

// Setup, called once
static constexpr int kArenaSize = 96 * 1024;
static uint8_t *arena = (uint8_t*)heap_caps_malloc(kArenaSize, MALLOC_CAP_SPIRAM);

const tflite::Model* model = tflite::GetModel(g_kws_model);
static tflite::MicroMutableOpResolver<8> resolver;
resolver.AddDepthwiseConv2D();
resolver.AddConv2D();
resolver.AddFullyConnected();
resolver.AddSoftmax();
resolver.AddReshape();
resolver.AddAveragePool2D();
resolver.AddQuantize();
resolver.AddDequantize();

static tflite::MicroInterpreter interp(model, resolver, arena, kArenaSize);
interp.AllocateTensors();
TfLiteTensor* input = interp.input(0);
TfLiteTensor* output = interp.output(0);

// Hot loop, called every 200 ms
void run_inference(const int8_t* mfcc) {
    memcpy(input->data.int8, mfcc, input->bytes);
    int64_t t0 = esp_timer_get_time();
    if (interp.Invoke() != kTfLiteOk) return;
    int64_t t1 = esp_timer_get_time();
    ESP_LOGD(TAG, "infer %lld us", t1 - t0);

    int8_t score = output->data.int8[KEYWORD_INDEX];
    if (score > kThresholdInt8) on_keyword_detected();
}

Gemessen auf einem ESP32-S3 mit 240 MHz und PSRAM mit 80 MHz: Die Inferenz dauert 18-22 ms pro Fenster, die MFCC-Extraktion weitere 4-6 ms, was mehr als 170 ms Spielraum pro Sprung für Funk, App-Logik und OS-Overhead lässt. Der durchschnittliche Strom wird vom Mikrofon und Verstärker dominiert, nicht von der Rechenleistung.

Beispiel zwei: Beschleunigungssensor-Anomalieerkennung

Für die vorausschauende Wartung an der Wasserpumpe einer Yacht oder dem Kühler eines Hotels ist das kanonische Modell ein 1D-Faltungs-Autoencoder, der auf gesunden Vibrationssignaturen trainiert wird. Anomalien zeigen sich als erhöhter Rekonstruktionsfehler. Das Deployment ähnelt dem Keyword-Spotting, ist aber kleiner und schneller.

  1. 3-Achsen-Beschleunigungssensor mit 800 Hz über SPI.
  2. Gleitendes Fenster von 256 Samples pro Achse (320 ms), 50 % überlappend.
  3. Normalisierung pro Achse auf Mittelwert null, Einheitsvarianz.
  4. 1D-Faltungs-Autoencoder, 4 Schichten, ~35 kB INT8, Latent-Dimension 16.
  5. Rekonstruktions-MSE verglichen mit rollierender Baseline; Alarm, wenn der Fehler den gelernten Schwellwert für 5 aufeinanderfolgende Fenster überschreitet.

Die Inferenz kommt bei etwa 6-8 ms pro Fenster heraus. Der gesamte Detektor – Abtastung, Normalisierung, Inferenz, Schwellwertlogik – nutzt unter 5 % eines Kerns und lässt Spielraum, damit das Gerät auch Roh-Telemetrie zur Neu-Trainings an die Cloud veröffentlichen kann. Erkannte Anomalien lösen eine reichhaltigere Nutzlast aus: die Spur des Rekonstruktionsfehlers, das Rohfenster und einen Modellversions-Stempel, damit das Cloud-Team echte Positive rückwirkend bewerten kann. Diese Rückkopplungsschleife verwandelt ein einmaliges Deployment in ein System, das sich verbessert; sie ist Teil des Grundes, warum wir Edge Computing als untrennbar von der Cloud-Strategie behandeln und nicht als deren Ersatz.

Deployment-Workflow

Das Ausliefern eines TinyML-Modells ist kein einmaliger Akt. Es ist ein versioniertes Artefakt wie jedes andere. Unser Standard-Workflow:

  1. Trainieren und quantisieren in Python; Ausgabe von model_int8.tflite und einem Metadaten-JSON mit Eingabeform, Klassen und Schwellwert.
  2. Umwandlung in ein C-Array per xxd -i oder dem ESP-IDF-Modell-Einbettungs-Flow.
  3. In die Firmware einbacken mit einer Modellversions-Konstante; CI-Builds hängen die Metadaten an das Release an.
  4. Auslieferung per OTA mit derselben Partitionsstrategie wie die Firmware. Wir trennen Modell-Partitionen von Code-Partitionen, damit ein Modell-Update keinen vollständigen Firmware-Push erfordert.
  5. Beobachten: Jede Inferenz protokolliert die Modellversion, den Score und die ergriffene Aktion. Diese Telemetrie speist den nächsten Trainingszyklus.

Das Modell als Daten zu behandeln, nicht als Code, ist der Schlüssel zu schneller Iteration. Wir pushen in manchen Deployments wöchentlich neue Modell-Partitionen, während sich die zugrunde liegende Firmware in ihrem eigenen vierteljährlichen Zyklus bewegt. Diese Trennung erlaubt es dem Data-Science-Team auch, auszuliefern, ohne auf einen Firmware-Release-Zug zu warten.

Benchmarks, an denen man sich messen sollte

Zahlen aus unseren Referenz-Benchmarks auf dem ESP32-S3 mit 240 MHz, PSRAM mit 80 MHz, INT8-Modelle, ein Kern:

  • Keyword-Spotter (80 kB, 49x40x1 Eingabe): 19 ms Inferenz, 64 kB Arena.
  • Beschleunigungssensor-Autoencoder (35 kB, 256×3 Eingabe): 7 ms Inferenz, 22 kB Arena.
  • MobileNetV1 0,25x für 96×96 Graustufen (220 kB): 145 ms Inferenz, 180 kB Arena.
  • Personenerkennung (250 kB, 96×96): 175 ms Inferenz, 200 kB Arena.

Wenn Ihr Modell deutlich länger braucht, als diese Zahlen nahelegen, sind die üblichen Verdächtigen nicht unterstützte Ops, die auf Referenz-Implementierungen zurückfallen, eine Arena in langsamem Speicher oder eine Modelltopologie, die die Vektoreinheit ausbremst (viele winzige Ops, Kanalzahlen, die nicht auf 8 oder 16 ausgerichtet sind). Profilieren Sie, bevor Sie optimieren, und überprüfen Sie stets, welche Ops tatsächlich beschleunigt werden.

Plausibilitätsprüfung des Energiebudgets

Edge-ML ist nur nützlich, wenn das Gerät sein Batterieziel weiterhin erreicht. Die gute Nachricht: Mit ausgeschaltetem WLAN und einem durch Inferenzergebnisse gesteuerten Funkmodul verbringt der ESP32-S3 die meiste Zeit im Light-Sleep bei rund 0,8 mA, wacht für ein Mikrofonfenster auf, führt MFCC plus Inferenz in etwa 25 ms bei rund 35 mA aus und schläft wieder ein. Für einen Keyword-Spotter, der kontinuierlich mit einem 200-ms-Sprung abtastet, landet der durchschnittliche Strom bei 12-18 mA je nach Duty. Eine 2000-mAh-Zelle läuft bei kontinuierlichem Zuhören etwa vier Monate, länger, wenn Sie zuerst auf akustische Energie aufwachen.

Der Beschleunigungssensor-Detektor ist noch freundlicher. Wir wachen typischerweise bei einem Bewegungsschwellwert auf, führen ein 320-ms-Fenster aus und schlafen bis zur nächsten geplanten Prüfung. Der durchschnittliche Strom liegt im einstelligen Milliampere-Bereich, und eine CR123A-Primärzelle trägt das Gerät durch ein mehrjähriges Deployment. Messen Sie stets mit einem echten Coulomb-Zähler auf der Produktions-Leiterplatte; Simulation ist ein Ausgangspunkt, keine Antwort.

Was Edge-ML nicht löst

Edge-Inferenz macht die Cloud nicht überflüssig. Sie brauchen weiterhin zentralisiertes Training, Modellversionierung, Drift-Erkennung und eine Rückkopplungsschleife, die die Fälle erfasst, in denen das Edge-Modell falsch lag. Die Cloud bleibt auch der richtige Ort für jedes Schlussfolgern, das gerätübergreifenden Kontext benötigt – ein Gerät sieht eine Maschine, die Cloud sieht die Flotte. Unsere umfassendere KI-Plattform-Arbeit geht standardmäßig von Hybrid aus und verlagert die Inferenz je nach Anwendungsfall auf die Seite des Netzwerks, die Sinn ergibt.

Wenn Sie ein TinyML-Deployment abschätzen – ob es sich um einen Yacht-Kabinensensor, ein Hotel-Zutrittsgerät oder einen industriellen Vibrationsknoten handelt – wir bauen diese durchgängig auf dem ESP32-S3 und benachbartem Silizium. Beginnen Sie mit unserem Connected-Devices-Service oder durchstöbern Sie die umfassenderen IoT-Fähigkeiten, die wir anbieten.