Anwendungen Workflow Code Hardware Bibliotheken Ressourcen People First PPP Kontakt → Einstieg

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