Codebeispiele
Direkt einsetzbare Snippets
Kopieren, anpassen, flashen — jedes Beispiel läuft auf einem Standard ESP32.
inference_main.cpp
#include "tensorflow/lite/micro/all_ops_resolver.h" #include "tensorflow/lite/micro/micro_interpreter.h" #include "tensorflow/lite/schema/schema_generated.h" #include "model_data.h" // xxd-konvertiertes .tflite namespace { const int TENSOR_ARENA_SIZE = 60 * 1024; // 60 KB Arena uint8_t tensor_arena[TENSOR_ARENA_SIZE]; tflite::AllOpsResolver resolver; const tflite::Model* model = nullptr; tflite::MicroInterpreter* interpreter = nullptr; } void setup() { Serial.begin(115200); // Modell aus Flash-Array laden model = tflite::GetModel(g_model_data); if (model->version() != TFLITE_SCHEMA_VERSION) { Serial.println("Modell-Schema veraltet!"); while (true); } // Interpreter initialisieren interpreter = new tflite::MicroInterpreter( model, resolver, tensor_arena, TENSOR_ARENA_SIZE ); TfLiteStatus status = interpreter->AllocateTensors(); if (status != kTfLiteOk) { Serial.println("Tensor-Allokierung fehlgeschlagen"); while (true); } Serial.printf("Arena genutzt: %d Bytes\n", interpreter->arena_used_bytes()); } void loop() { TfLiteTensor* input = interpreter->input(0); TfLiteTensor* output = interpreter->output(0); // Eingabedaten normalisieren [-1.0, 1.0] fillInputFromSensor(input->data.f); // Inferenz ausführen TfLiteStatus invoke_status = interpreter->Invoke(); if (invoke_status != kTfLiteOk) return; // Klasse mit höchster Konfidenz ermitteln float max_conf = 0.0f; int max_idx = -1; for (int i = 0; i < output->dims->data[1]; i++) { if (output->data.f[i] > max_conf) { max_conf = output->data.f[i]; max_idx = i; } } Serial.printf("Klasse %d — Konfidenz %.2f%%\n", max_idx, max_conf * 100.0f); delay(200); }
wakeword.cpp
#include "driver/i2s.h" #include "esp_dsp.h" #include "wakeword_model.h" // TFLite INT8 Modell // I²S-Konfiguration für INMP441 MEMS-Mikrofon const i2s_config_t i2s_config = { .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX), .sample_rate = 16000, .bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT, .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT, .communication_format = I2S_COMM_FORMAT_STAND_I2S, .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, .dma_buf_count = 4, .dma_buf_len = 512, }; // MFCC-Extraktion: 40 Koeffizienten, 25ms Fenster, 10ms Hop const int N_MFCC = 40; const int FRAME_LEN = 400; // 25ms @ 16kHz const int HOP_LEN = 160; // 10ms @ 16kHz const int N_FRAMES = 49; // 1s Audio float mfcc_buffer[N_FRAMES * N_MFCC]; bool detectWakeword() { // 1. PCM-Daten per DMA lesen int32_t raw[FRAME_LEN]; size_t bytes_read; i2s_read(I2S_NUM_0, raw, sizeof(raw), &bytes_read, 100); // 2. Normalisieren & MFCC berechnen (esp-dsp) compute_mfcc_frame(raw, mfcc_buffer, N_MFCC); // 3. TFLite Inferenz TfLiteTensor* in = interpreter->input(0); memcpy(in->data.f, mfcc_buffer, sizeof(mfcc_buffer)); interpreter->Invoke(); TfLiteTensor* out = interpreter->output(0); float confidence = out->data.f[1]; // Klasse "Hey ESP" return confidence > 0.85f; }
vision_classify.cpp
#include "esp_camera.h" #include "img_converters.h" #include "mobilenet_model.h" // ESP32-CAM AI Thinker Pinout const camera_config_t cam_config = { .pin_pwdn = 32, .pin_reset = -1, .pin_xclk = 0, .pin_sscb_sda = 26, .pin_sscb_scl = 27, .xclk_freq_hz = 20000000, .pixel_format = PIXFORMAT_GRAYSCALE, // Graustufen spart RAM .frame_size = FRAMESIZE_96X96, // MobileNet Eingabegröße .fb_count = 1, }; void classifyFrame() { camera_fb_t* fb = esp_camera_fb_get(); if (!fb) return; // Pixelwerte normalisieren: [0,255] → [-1.0, 1.0] TfLiteTensor* input = interpreter->input(0); for (int i = 0; i < 96 * 96; i++) { input->data.f[i] = (fb->buf[i] / 127.5f) - 1.0f; } // Inferenz (~55ms bei 240MHz) interpreter->Invoke(); // Top-1 Klasse ermitteln TfLiteTensor* out = interpreter->output(0); int best_cls = 0; float best_conf = out->data.f[0]; for (int c = 1; c < NUM_CLASSES; c++) { if (out->data.f[c] > best_conf) { best_conf = out->data.f[c]; best_cls = c; } } Serial.printf("%s (%.1f%%)\n", labels[best_cls], best_conf * 100.0f); esp_camera_fb_return(fb); }
anomaly_imu.cpp
#include "MPU6050.h" #include "autoencoder_model.h" // INT8 Autoencoder const int WINDOW = 128; // 128 Samples @ 200 Hz = 640ms const int FEATURES = 6; // ax,ay,az, gx,gy,gz float window_buf[WINDOW * FEATURES]; float reconstructionError() { // Input-Tensor befüllen TfLiteTensor* in = interpreter->input(0); memcpy(in->data.f, window_buf, sizeof(window_buf)); interpreter->Invoke(); // MSE zwischen Eingabe und Rekonstruktion TfLiteTensor* out = interpreter->output(0); float mse = 0.0f; int n = WINDOW * FEATURES; for (int i = 0; i < n; i++) { float diff = window_buf[i] - out->data.f[i]; mse += diff * diff; } return mse / n; } void loop() { collectIMUWindow(window_buf, WINDOW); float err = reconstructionError(); const float THRESHOLD = 0.032f; // Aus Validierungsdaten ermittelt if (err > THRESHOLD) { Serial.printf("[ALARM] Anomalie! MSE=%.4f\n", err); sendMQTTAlert(err); // IoT-Backend benachrichtigen triggerWarningLED(); } else { Serial.printf("[OK] MSE=%.4f\n", err); } }
platformio.ini
; PlatformIO-Konfiguration für ESP32 TinyML Projekt ; Stand: Juli 2026 — ESP-IDF 5.4 / arduino-esp32 3.x [env:esp32dev] platform = espressif32 board = esp32dev framework = arduino ; Empfohlene Partition: 4 MB Flash für Modell + OTA board_build.partitions = huge_app.csv monitor_speed = 115200 upload_speed = 921600 ; TensorFlow Lite Micro + DSP Bibliotheken lib_deps = tensorflow/TensorFlowLite_ESP32 espressif/esp-dsp lorol/LittleFS_esp32 ; Modell aus SPIFFS laden ; Optimierungsstufe für Inferenzgeschwindigkeit build_flags = -O3 -DCORE_DEBUG_LEVEL=0 -DESP_NN ; Espressif Neural Network Ops -DTFLITE_SCHEMA_VERSION=3 ; Konvertierungsbefehl (auf Host-Maschine ausführen): ; tflite_convert --output_format=TFLITE \ ; --post_training_quantize \ ; --input_file=model.h5 \ ; --output_file=model.tflite ; ; xxd -i model.tflite > model_data.h