Motivation

Die ESP-Cam-Module eignen sich beispielsweise sehr gut, um Vogelnester zu beobachten. Als Bibliotheksbeispiel gibt es den WebCamServer. Dieser ist jedoch recht komplex und nicht für den Batteriebetrieb geeignet. Eine ausführliche Dokumentation für die ESP-Cam-Bibliothek habe ich nicht gefunden, und auch die Dokumentation des Source-Codes ist äußerst spärlich. Hier dokumentiere ich das, was ich zum Thema herausgefunden habe. Diese Dokumentation ist bei Weitem nicht vollständig. Sie enthält im Wesentlichen die Dinge, die für den Betrieb einer ESP32-Kamera vom Typ AI-Thinker mit dem Kamera-Modul OV2640 notwendig sind.

 

In­halts­ver­zeich­nis

Versionshistorie

Download

Hardware

ESP32-CAM-Pinbelegung

Schaltplan

Begriffe und Abkürzungen

Espressif Camera API

 High Level

struct camera_config_t

Zum Timing

Zum Frame-Buffer

Zum Aufnahmemodus (Grab-Mode)

struct camera_fb_t

Einstellungen dauerhaft speichern (NVS)

NVS-Fehlercodes

Sensor: Low Level

Datentypen

struct _sensor, sensor_t

struct camera_sensor_info_t

struct sensor_id_t

struct camera_status_t

Verwendung

Bibliothek UrsESP32Camera

Datentypen

Enumerationen

Basis-Klasse EspCamera

Kamera-Initialisierung

Flash-LED

Foto abrufen

Testprogramm

Links

Versionshistorie

Version Anpassungen
1.0 (2026-11-10) Basis-Version

Download

Das ZIP-Archiv für Bibliothek UrsESP32Camera zum Download. Die entpackten Dateien ins Verzeichnis <user>\Documents\Arduino\libraries kopieren (siehe Installing Additional Arduino Libraries).

Das enthalte Beispiel listet die Einstellungen des Camera-Moduls. Das Beispiel ist ein Visual Studio / Visual Micro Projekt. Benutzer der Arduino-IDE verwenden nur die Code-Dateien (Doppelklick auf die .ino-Dateien).

Hardware

Das ESP32-CAM ist ein leistungsstarkes Modul mit integrierter Kamera und WLAN-Unterstützung. Leider verfügt es nur über wenige E/A-Pins, von denen einige gemeinsam mit der SD-Karte genutzt werden und daher nicht verwendet werden können, wenn die Karte eingelegt ist.

ESP32-CAM-Pinbelegung

Das ESP32-CAM verfügt über insgesamt 16 Pins. Der Übersichtlichkeit halber sind Pins mit ähnlicher Funktion zusammengefasst. Die Pinbelegung sieht wie folgt aus:

ESP32-CAM-Pinout

Der ESP32-D0WDQ6-Chip verfügt insgesamt über 32 GPIO-Pins, doch da viele davon intern für die Kamera und den PSRAM genutzt werden, stehen beim ESP32-CAM nur 10 GPIO-Pins zur Verfügung. Diesen Pins können durch die Programmierung der entsprechenden Register verschiedene Peripheriefunktionen zugewiesen werden, wie beispielsweise UART, SPI, ADC und Touch.

Obwohl der ESP32-CAM über 10 GPIO-Pins mit verschiedenen Funktionen verfügt, sind einige davon möglicherweise nicht für eigene Projekte geeignet. Die folgende Tabelle zeigt, welche Pins bedenkenlos verwendet werden können und bei welchen Pins Vorsicht geboten ist.

Label GPIO Sicher? Grund Anmerkung
D0 0 Muss beim Booten auf HIGH und beim Flashen auf LOW stehen 10K gegen +3,3V
TX0 1 Tx-Pin, dient zum Flashen und Debuggen  
D2 2 Muss während des Bootvorgangs auf LOW stehen. Kann nicht verwendet werden, wenn eine microSD-Karte vorhanden ist. SD: DATA0
10K gegen +3,3V
RX0 3 Rx-Pin, dient zum Flashen und Debuggen  
D4 4 Mit der integrierten Flash-LED verbunden. Kann nicht verwendet werden, wenn eine microSD-Karte vorhanden ist. SD: DATA1
10K gegen +3,3V
D12 12 Muss während des Bootvorgangs auf LOW stehen. Kann nicht verwendet werden, wenn eine microSD-Karte vorhanden ist. SD: DATA2
10K gegen +3,3V
D13 13 Kann nicht verwendet werden, wenn eine microSD-Karte vorhanden ist. SD: DATA3
47K gegen +3,3V
D14 14 Kann nicht verwendet werden, wenn eine microSD-Karte vorhanden ist. SD: CLK
D15 15 Muss während des Bootvorgangs auf HIGH stehen, verhindert das Startprotokoll, wenn auf LOW gesetzt. Kann nicht verwendet werden, wenn eine microSD-Karte vorhanden ist. SD: CMD
10K gegen +3,3V
RX2 16  
D33 33 Built-In rote LED (auf der Chip-Seite)  

GPIO16 ist unbeschaltet und kann beliebig verwendet werden. GPIO14 ist der einzige unbeschaltete Pin, der als ADC geeignet ist. Bei Verwendung einer SD-Karte dient er als Taktsignalleitung (CLK). Das CLK-Signal wird vom μC erzeugt. Eine nicht aktive SD-Karte stört die Spannungsmessung nicht (getestet mit einer SanDisk-SD-Karte). GPIO14 ist dem ADC2 zugeordnet, der nicht bei aktivem WLAN benutzt werden kann. Wenn GPIO14 als ADC verwendet werden muss, sollte das WLAN kurzzeitig getrennt bzw. abgeschaltet werden (WiFi.disconnect() oder WiFi.mode(WIFI_OFF)). Anschließend den Sensorwert auslesen und danach das WLAN wieder verbinden.

Schaltplan

Schaltplan

Bildquelle: https://github.com/SeeedDocument/forum_doc/blob/master/reg/ESP32_CAM_V1.6.pdf

Begriffe und Abkürzungen

In der Bibliothek werden eine Reihe von Abkürzungen und Begriffen verwendet, die vielleicht nicht jedem vertraut sind. In der nachfolgenden Tabelle werden die wichtigsten Begriffe mit ihren Abkürzungen in deutscher und englischer Sprache genannt und kurz erklärt:

Bezeichnung Kürzel Funktion Wertebereich Std
Pixelformat   Das Pixelformat legt fest, wie die Farbinformationen jedes einzelnen Bildpunktes im Arbeitsspeicher (Framebuffer) abgelegt und übertragen werden. RGB565, 2 Byte per Pixel
YUV422, 2 Byte per Pixel
YUV420, 1.5 Byte per Pixel
GRAYSCALE, 1 Byte per Pixel
JPEG/ JPEG/COMPRESSED
RGB888  3 Byte per Pixel
RAW,
RGB444, 3 Byte per 2 Pixel
RGB555, 3 Byte per 2 Pixel
JPEG†)
Autofocus AF Der Autofokus (kurz AF) ist ein technisches System in Kameras oder optischen Geräten, das die Bildschärfe eines Motivs automatisch einstellt. Wird vom TYP AI-Thinker
mit OV2640 nicht unterstützt.
 
Automatic White Balance
Automatischer Weißabgleich
AWB Die Kamera misst das Licht der Szene selbst und passt die Farben so an, dass weiße Flächen im Bild auch wirklich weiß wirken. Das verhindert unnatürliche Farbstiche. ein / aus ein
Auto White Balance Gain
Verstärkung des automatischen Weißabgleichs
AWB-Gain Eine zusätzliche Verstärkung des AWB dient dazu, den automatischen Startpunkt der Farbanpassung dauerhaft wärmer oder kühler zu verschieben. ein / aus ein
WB Mode
Weißabgleichprofil
  Feste Programme für bestimmte Lichtsituationen wie Sonnig / Tageslicht, Bewölkt, Schatten, Wolfram / Kunstlicht oder Neonröhre.
0: Automatisch, 1: Sonnig, 2: Bewölkt, 3: Büro, 4: Haus
0 .. 4 0
White Point Correction
Weißpunkt-Korrektur
WPC Dient zum Ausgleich von Sensor-Fehler. Jede Kamera und jeder Bildsensor hat kleine, fertigungsbedingte Abweichungen. Die WPC korrigiert diese, damit weiße Flächen im Bild keinen störenden Farbstich (zum Beispiel ins Bläuliche oder Rötliche) aufweisen.
0 = aus, 1 = ein.
ein / aus ein
Raw Gamma Correction
Rohdaten-Gammakorrektur
Raw GMA Ist eine Kameraeinstellung, die die Gammakorrektur direkt auf die rohen Sensor-Bilddaten anwendet.
Ausgeschaltet: Das Bild zeigt die rein linearen Helligkeitswerte des Sensors, was oft sehr dunkel oder kontrastarm wirkt, aber für spezielle maschinelle Bildverarbeitung sinnvoll sein kann.
Eingeschaltet: Das Bild wirkt natürlicher, ausgeglichener und heller, da dunkle Bereiche aufgehellt werden.
0 = aus, 1 = ein.
ein / aus ein
Automatic Exposure Control
Automatische Belichtungssteuerung
AEC
(SENSOR)
Sie regelt den Betrieb des Sensorfeldes der Digitalkamera. Die Aufnahme von Bildern und Videos wird dadurch optimiert, dass die automatische Belichtungssteuerung die Belichtungszeit des Sensorfeldes festlegt, bevor eine digitale Bearbeitung des aufgenommenen Bildes erfolgt. Die automatische Belichtungssteuerung bestimmt den Belichtungswert, indem sie den mittleren Helligkeitswert in die Mitte des Dynamikbereichs verschiebt. ein / aus ein
AE Level
Belichtungsstufe
AEC Er legt fest, wie hell oder dunkel das Bild im automatischen Belichtungsmodus (AEC) sein soll. Er lässt sich in einem Bereich von -2 bis +2 einstellen. Negative Werte machen das Bild dunkler, positive Werte heller. -2 .. +2 0
Auto Exposure Control via Digital Signal Processor
AEC über den digitalen Signalprozessor
AECDSP
(aec2)
Die Belichtungskorrektur wird nicht direkt rein physikalisch auf dem Kamerasensor (AEC Sensor), sondern nachträglich digital durch den Prozessor berechnet und optimiert wird.
ein / aus aus
Automatic Gain Control
Automatische Verstärkungsregelung
AGC Es wird der Spannungsausgangspegel an der Kamera reguliert, sodass man bei schlechten Lichtverhältnissen noch brauchbare Bilder bekommt. Nachteil: Bei hoher Verstärkung nimmt auch das Bildrauschen zu und macht die Aufnahmen wieder unbrauchbar.
0 = aus, 1 = ein.
ein / aus ein
Gain Ceiling
Verstärkungsobergrenze
  Ist eine Sicherheitsfunktion in Kameras, die den maximalen Grad der elektronischen Signalverstärkung (Gain) begrenzt. Sie legt fest, bis zu welchem Wert die automatische Helligkeitsanpassung (AGC) bei Dunkelheit maximal hochfahren darf.
Da eine höhere Verstärkung das Bildrauschen und störende Artefakte stark erhöht, verhindert das Gain Ceiling, dass das Bild unbrauchbar verpixelt oder grieselig wird.
Ein niedrigerer Maximalwert sorgt für ein sauberes Bild, bedeutet bei absoluter Finsternis jedoch, dass dunkle Bereiche im Video dunkel oder unterbelichtet bleiben.
0 = 2-fach, 1 = 4-fach, 2= 8-fach, 3 = 16-fach, 4 = 32-fach, 5 = 64-fach, 6 = 128-fach
0 .. 6 0
Bad Pixel Correction
Black Pixel Correction

Fehlpixelkorrektur
BPC BPC ist eine Funktion der kamerainternen Bildverarbeitung (im sogenannten ISP-Prozess), die defekte, tote oder dauerhaft leuchtende Pixel (Hot Pixel) auf dem Bildsensor automatisch erkennt und kaschiert, indem sie deren Helligkeit anhand der umliegenden Pixel berechnet. 
0 = aus, 1 = ein.
ein / aus aus
Downsize-Kompensation DCW Die Downsize-Kompensation (oder Downsize EN) ist eine interne Funktion des Bildsensors, die das Bild direkt auf Hardware-Ebene verkleinert, bevor es an den Mikrocontroller übertragen wird.
Sie schützt den Mikrocontroller vor Überlastung, da weniger Pixel verarbeitet und übertragen werden müssen.
Sie spart wertvollen Arbeitsspeicher (RAM/PSRAM) bei der Live-Übertragung oder Bildverarbeitung.
0 = aus, 1 = ein.
ein / aus ein
Resolution, FrameSize
Auflösung, Bildgröße
  Bildgröße (Pixel x Pixel), bei der ESP21-CAM einstellbar. Werte zwischen 96x96 (0) und 2592x1944(24).
Die einfache Kamera vom Typ OV2640 schafft das Format UXGA mit 1600x1200 Pixeln.
0 .. 24 6*),  QVGA, 320x240
Quality
Qualität
  JPEG-Qualität: 0 (hoch) bis 63 (niedrig) 0 .. 63 10*)
Brightness
Helligkeit
  Ist oft ein rein digitaler oder elektronischer Eingriff, der die Pixelwerte im Nachhinein anhebt oder absenkt, ohne echtes Licht auf den Sensor zu lassen. Das kann bei zu starkem Einsatz zu Bildrauschen oder dem Verlust von Details in hellen/dunklen Bereichen führen. -2 .. +2 0
Contrast
Kontrast
  Der Kontrast beschreibt den Helligkeits- oder Farbunterschied zwischen den hellsten und dunkelsten Bereichen eines Bildes. Ein hoher Kontrast wirkt oft dramatisch und klar. Ein niedriger Kontrast (flaues Bild) wirkt weich oder trüb. -2 .. +2 0
Saturation
Sättigung
  Verstärkt oder schwächt jede Farbe im Bild gleichmäßig ab.
Hohe Sättigung: Die Farben wirken kräftig, lebendig und leuchtend. Bei einem extremen Wert kann das Bild jedoch unnatürlich oder übertrieben wirken.
Niedrige Sättigung: Die Farben werden blass und grau. Ist die Sättigung komplett auf null reduziert, entsteht ein reines Schwarz-Weiß-Bild.
-2 .. +2 0
Sharpness
Bildschärfe
  Schärfe (Kantenunschärfe/Nachschärfung) bezeichnet einen Software-Parameter im Kameratreiber (Sensor-Register), mit dem die Kontrastverstärkung an Bildkanten digital angepasst wird.
Eine höhere Schärfeeinstellung fügt dem Bild keine echten Details hinzu. Sie verstärkt lediglich den Kontrast an bestehenden Linien, wodurch das Bild für das Auge „knackiger“ oder schärfer wirkt.
Ein zu hoher Wert führt zu unnatürlichen Rändern (Artefakten) und verstärkt das Bildrauschen – was bei dem kleinen, lichtschwachen Sensor der ESP32-CAM schnell störend wirken kann. Ein zu niedriger Wert lässt das Bild weich oder verschwommen erscheinen.
-2 .. +2 0
Denoise
Rauschunterdrückung
  Reduzierung von Bildrauschen. Bildrauschen zeigt sich bei digitalen Fotos oder Videostreams als unruhiges Flimmern, störende Farbpunkte oder eine körnige Struktur im Bild. Es entsteht besonders dann, wenn die Kamera bei schlechten Lichtverhältnissen oder hoher Verstärkung betrieben wird.
Ein Denoise-Filter oder -Algorithmus glättet das Bild digital, um diese störenden Pixel-Artefakte zu entfernen. Das Bild wirkt zwar ruhiger und sauberer, allerdings geht durch die Glättung oft auch ein Teil der Bildschärfe und feiner Details verloren.
Da die ESP-CAM über einen im Vergleich schwachen Prozessor und begrenzten Arbeitsspeicher verfügt, kostet eine kamerainterne Nachbearbeitung Rechenleistung und kann die Bildrate (Framerate) des Live-Streams senken.
ein / aus  
Pixel binning
Pixel-Binning
  Kombiniert benachbarte Pixel für höhere Lichtempfindlichkeit bei geringerer Auflösung ein / aus aus
Special Effect
Spezialeffekt
  Verfremdung des Bildes
0 = kein Effekt, 1 = Negativ, 2 = Graustufen, 3 = Rotstich, 4 = Grünstich, 5 = Blaustich, 6 = Sepia
0 .. 6 0
Lens Correction
Linsenkorrektur
  Ist eine Funktion zur Korrektur von optischen Bildfehlern, die durch die kleine Weitwinkel- oder Fischauge-Linse der Kamera entstehen (meist mit dem Sensor OV2640).
0 = aus, 1 = ein.
ein / aus ein
Pseudo-Static Random Access Memory PSRAM Ist ein externer Zusatz-Arbeitsspeicher, den viele ESP32-Mikrocontroller anbinden können, um den internen RAM deutlich zu erweitern.
Dank einer integrierten Auffrischungsschaltung (Self-Refresh) verhält er sich nach außen hin wie ein einfacher statischer Speicher (SRAM).
   

†) Wird i.d.R. bei der Initialisierung festgelegt.

*) Wird i.d.R. in Abhängigkeit vom Vorhandensein eines PSRAMs unterschiedlich initialisiert (s. camera_config_t).

Espressif Camera API

 High Level

In der Header-Datei esp_camera.h werden High-Level-Typen und Funktionen  deklariert:

Funktion Wirkung Anmerkung
esp_err_t esp_camera_init(const camera_config_t* config) Diese Funktion erkennt und konfiguriert die Kamera über die I2C-Schnittstelle, weist Framebuffer- und DMA-Puffer zu, initialisiert den parallelen I2S-Eingang und richtet DMA-Deskriptoren ein.

Zu camera_config_t s.u.
Derzeit kann diese Funktion nur einmal aufgerufen werden und es gibt keine Möglichkeit, dieses Modul zu deaktivieren.
Liefert ESP_OK bei Erfolg.
esp_err_t esp_camera_deinit(void) Deaktiviert den Kameratreiber. Liefert ESP_OK bei Erfolg.
esp_err_t esp_camera_reconfigure(const camera_config_t *config) Initialisiert die Kamera mit einer neuen Konfiguration neu. Liefert ESP_OK bei Erfolg.
camera_fb_t* esp_camera_fb_get(void) Zeiger auf den Frame-Puffer abrufen.
Zu camera_fb_t
 
void esp_camera_fb_return(camera_fb_t * fb) s.u. Gibt den Frame-Buffer zurück, damit er erneut verwendet werden kann.  
void esp_camera_return_all Alle Frame-Puffer zurückgeben, damit sie erneut verwendet werden können.  
bool esp_camera_available_frames(void) Prüfen, ob verfügbare Frames vorhanden sind, die sofort abgerufen werden können.  
esp_err_t esp_camera_save_to_nvs(const char *key) Kameraeinstellungen in einem nichtflüchtigen Speicher (NVS) speichern.
key: ein eindeutiger NVS-Schlüsselname für die Kameraeinstellungen
Zum Speichern muss eine Partition mit der Bezeichnung nvs vorhanden sein. Bei den voreingestellten Schemata wird eine solche mit einer Größe von 20 KB angelegt. Dies muss bei benutzerdefinierten Partitionsschemata berücksichtigt werden.
Liefert ESP_OK bei Erfolg.
Fehlercodes bei Espressif IDF nvs_open und nvs_set_blob.
esp_err_t esp_camera_load_from_nvs(const char *key) Kameraeinstellungen aus dem nichtflüchtigen Speicher (NVS) laden
key: ein eindeutiger NVS-Schlüsselname für die Kameraeinstellungen
s.o.
esp_err_t esp_camera_set_psram_mode(bool enable) Aktiviert oder deaktiviert den PSRAM-DMA-Modus zur Laufzeit. true zum Aktivieren des PSRAM-DMA-Modus, false zum Deaktivieren.  
bool esp_camera_get_psram_mode(void) Ruft den aktuellen Status des PSRAM-DMA-Modus ab.  
sensor_t * esp_camera_sensor_get(void) Liefert einen Zeiger auf die Steuerstruktur des Bildsensors.
Zu sensor_t s.u.
Die Kamera muss initialisiert sein (s. esp_camera_init).

struct camera_config_t

Der Typ camera_config_t enthält die Parameter für die Initialisierung der Espressif IDF-Bibliothek.

typedef struct {

   // =========================================================================
   // 1. HARDWARE-PINS (Zuweisung an die GPIOs des ESP32)
   // =========================================================================
   int pin_pwdn;            // Pin für Power-Down
   int pin_reset;           // Reset-Pin (-1 bedeutet, kein Hardware-Reset-Pin verbunden)
   int pin_xclk;            // Liefert das externe Taktsignal für den Kamerasensor
   int pin_sccb_sda;        // I2C/SCCB Datenleitung für Kamera-Einstellungen 
   int pin_sccb_scl;        // I2C/SCCB Taktleitung für Kamera-Einstellungen
   int pin_d7;              // Bit 7 der parallelen Datenleitung (höchstwertiges Bit)
   int pin_d6;              // Bit 6 der parallelen Datenleitung
   int pin_d5;              // Bit 5 der parallelen Datenleitung
   int pin_d4;              // Bit 4 der parallelen Datenleitung
   int pin_d3;              // Bit 3 der parallelen Datenleitung
   int pin_d2;              // Bit 2 der parallelen Datenleitung
   int pin_d1;              // Bit 1 der parallelen Datenleitung
   int pin_d0;              // Bit 0 der parallelen Datenleitung (niederwertigstes Bit)
   int pin_vsync;           // Vertical Sync: Signalisiert das Ende eines kompletten Bildes
   int pin_href;            // Horizontal Reference: Signalisiert das Ende einer Bildzeile
   int pin_pclk;            // Pixel Clock: Taktet die Übertragung jedes einzelnen Daten-Bytes

   // =========================================================================
   // 2. SIGNAL- UND TAKT-EINSTELLUNGEN
   // =========================================================================
   int xclk_freq_hz;               // Frequenz des Taktsignals (20 MHz ist der Standard für stabile Bilder)
   ledc_timer_t ledc_timer;        // ESP32-Hardware-Timer für das XCLK-Signal
   ledc_channel_t ledc_channel;    // PWM - Kanal zur Erzeugung des XCLK - Signals

   // =========================================================================
   // 3. BILD- UND SPEICHER-EINSTELLUNGEN
   // =========================================================================
   pixformat_t pixel_format;       // Bildformat (JPEG komprimiert das Bild direkt auf der Kamera)
   framesize_t frame_size;         // Bildauflösung (VGA = 640x480 Pixel)

   int jpeg_quality;               // JPEG-Qualität: Bereich von 0 bis 63. Niedrigere Zahlen bedeuten BESSERE Qualität, aber auch GRÖSSERE Dateien.
   size_t fb_count;                // Anzahl der Bildpuffer im RAM. 
                                   // 1 = Spart RAM, wartet aber beim Fotografieren. 
                                   // 2 = Aktiviert Double-Buffering (Kamera schießt nächstes Bild, während das erste gesendet wird = höhere FPS).
   camera_fb_location_t fb_location; // Speicherort des Bildpuffers (PSRAM = externer Speicher, DRAM = interner Speicher)
   camera_grab_mode_t grab_mode;   // Timing-Modus für die Bildaufnahme
                                   // CAMERA_GRAB_WHEN_EMPTY: Wartet mit dem Füllen, bis der Puffer ausgelesen wurde (spart Energie)
                                   // CAMERA_GRAB_LATEST: Hält immer das allerneueste Bild im Puffer bereit (höhere FPS)
#if CONFIG_CAMERA_CONVERTER_ENABLED  // im Standard: False
   camera_conv_mode_t conv_mode;   /*!< RGB<->YUV Conversion mode */
#endif

   int sccb_i2c_port;              // hardwareseitige I2C-Schnittstelle(I2C - Port 0 oder 1), i.d.R. 0
                                   // Wenn „pin_sccb_sda“ den Wert -1 hat, wird der bereits konfigurierte I2C-Bus anhand seiner Nummer verwendet.
   size_t jpeg_buffer_size;        // Größe des JPEG-Bildpuffers in Byte. 0, um die Standardgröße zu verwenden.
} camera_config_t;

Zum Timing

Das Feld ledc_channel in der Konfigurationsstruktur camera_config_t bestimmt, welcher hardwarebasierte LEDC-PWM-Kanal (LED Control) des ESP32 für die Generierung des XCLK-Taktsignals (externer Takt) verwendet wird, den der Kamerasensor (z. B. OV2640) zum Betrieb benötigt.

Zweck: Der Kamerachip braucht einen permanenten Taktimpuls an seinem XCLK-Pin. Der ESP32 erzeugt diesen über seine internen PWM-/LED-Treibereinheiten (ledc), ohne die CPU zu belasten. Meistens wird hier LEDC_CHANNEL_0 zugewiesen.

ledc_channel  arbeitet eng mit ledc_timer (meist mit LEDC_TIMER_0 belegt) zusammen, um die Frequenz (standardmäßig 20 MHz) zu erzeugen.

Zum Frame-Buffer

Der Frame-Buffer ist ein Zwischenspeicher für Bilddaten: Der Sensor (z. B. OV2640) schreibt neue Bilddaten hinein, die dann vom ESP32 zur Verarbeitung ausgelesen werden. Die meisten ESP-CAM-Module besitzen ein zusätzlichen RAM-Speicher (PSRAM) zur Aufnahme der Bilddaten, da das interne RAM i.d.R. dafür nicht ausreicht.

Anzahl und Konfiguration des Frame-Buffers (Bildspeichers) bei einer ESP32-CAM entscheiden darüber, wie flüssig, stabil und hochauflösend die Kameraanwendungen laufen.

Zum Aufnahmemodus (Grab-Mode)

Der Grab-Mode (Aufnahmemodus) der esp32-camera-Bibliothek steuert, wie neue Bilddaten in die Frame-Buffer (Bildspeicher) geschrieben werden, wenn mehrere Buffer (fb_count > 1) verwendet werden.

Hinweis: Falls bei CAMERA_GRAB_WHEN_EMPTY mit mehreren Buffern ein aktuelles Bild erzwungen werden soll, müssen erst alte Bilder aus den Puffern abgerufen und verworfen werden.

struct camera_fb_t

Wenn die Kamera ein Foto aufnimmt, wird das Bild im RAM des ESP32 gespeichert. Die Struktur camera_fb_t enthält alle Daten und Metadaten dieses aufgenommenen Bildes.

typedef struct {
    uint8_t * buf;              // Zeiger auf die Pixeldaten
    size_t len;                 // Länge des Puffers in Bytes
    size_t width;               // Breite des Puffers in Pixeln
    size_t height;              // Höhe des Puffers in Pixeln
    pixformat_t format;         // Format der Pixeldaten
    struct timeval timestamp;   // Zeitstempel seit dem Systemstart für den ersten DMA-Puffer des Frames
}} camera_fb_t;

Einstellungen dauerhaft speichern (NVS)

Da der Kamerasensor bei jedem Neustart (Deep Sleep oder Reset) seine Einstellungen verliert, bietet der Treiber zwei Hilfsfunktionen an, um das gesamte camera_status_t-Paket im Flash-Speicher (Non-Volatile Storage) abzulegen (Die NVS-Bibliothek ersetzt die alte EEPROM-Bibliothek. Espressif-Doku: Non-Volatile Storage Library):

esp_camera_save_to_nvs("camera_settings"); Nimmt die aktuelle Struktur s->status und schreibt alle Bytes als Binärblock (Blob) in den NVS-Bereich unter dem Namen "camera_settings".

esp_camera_load_from_nvs("camera_settings"); Liest den Block beim Systemstart wieder aus und wendet alle Parameter nacheinander auf die Kamera-Hardware an.

NVS-Fehlercodes

Code Bedeutung (Englisch) Bedeutung (Deutsch)
ESP_OK The value was set successfully Die Einstellungen wurden erfolgreich gespeichert / geladen.
ESP_FAIL There is an internal error; most likely due to corrupted NVS partition (only if NVS assertion checks are disabled Es liegt ein interner Fehler; höchstwahrscheinlich aufgrund einer beschädigten NVS-Partition (nur wenn die NVS-Prüfungen deaktiviert sind)
ESP_ERR_NOT_ALLOWED The NVS partition is read-only and mode is NVS_READWRITE Die NVS-Partition ist schreibgeschützt und der Modus NVS_READWRITE lautet
ESP_ERR_NO_MEM Memory could not be allocated for the internal structures Für die internen Strukturen konnte kein Speicher zugewiesen werden.
ESP_ERR_NVS_INVALID_NAME Key name doesn't satisfy constraints Der Schlüsselname erfüllt die Einschränkungen nicht .
ESP_ERR_NVS_NOT_ENOUGH_SPACE There is not enough space in the underlying storage to save the value Im zugrunde liegenden Speicher ist nicht genügend Platz vorhanden, um die Da5en zu speichern
ESP_ERR_NVS_NOT_FOUND he requested key doesn't exist Der angeforderte Schlüssel existiert nicht.
ESP_ERR_NVS_NOT_INITIALIZED The storage driver is not initialized Der Speichertreiber ist nicht initialisiert.
ESP_ERR_NVS_PART_NOT_FOUND The partition with label "nvs" is not found Die Partition mit der Bezeichnung „nvs“ wurde nicht gefunden.
ESP_ERR_NVS_REMOVE_FAILED The value wasn't updated because flash write operation has failed. The value was written however, and update will be finished after re-initialization of nvs, provided that flash operation doesn't fail again. Der Wert wurde nicht aktualisiert, da der Flash-Schreibvorgang fehlgeschlagen ist. Der Wert wurde jedoch geschrieben und die Aktualisierung wird nach der Neuinitialisierung von NVS abgeschlossen, vorausgesetzt, der Flash-Vorgang schlägt nicht erneut fehl.
ESP_ERR_NVS_VALUE_TOO_LONG The value is too long Die zu speichernden Daten sind zu groß.

Sensor: Low Level

Datentypen

struct _sensor, sensor_t

Nachdem die esp_camera-Bibliothek über die Funktion esp_camera_init initialisiert wurde, kann man über die Funktion esp_camera_sensor_get einen Zeiger auf die Struktur _sensor (sensor_t) erhalten, die in der Header-Datei sensor.h deklariert ist:

typedef struct _sensor sensor_t;typedef struct _sensor {
    sensor_id_t id;             // Sensor ID (s. struct sensor_id_t).
    uint8_t  slv_addr;          // Sensor I2C Slave Adresse
    pixformat_t pixformat;
    camera_status_t status;
    int xclk_freq_hz;           // Taktfrequenz der Kamera
    int (*init_status) (sensor_t *sensor);
    int (*reset) (sensor_t *sensor); // Reset the configuration of the sensor, and return ESP_OK if reset is successful
    int (*set_pixformat) (sensor_t *sensor, pixformat_t pixformat);
    int (*set_framesize) (sensor_t *sensor, framesize_t framesize);
    int (*set_contrast) (sensor_t *sensor, int level);
    // ... Weitere Funktionszeiger zur Einstellung der Parameter wie Helligkeit, Sättigung, etc.
} sensor_t;

struct camera_sensor_info_t

Mit Hilfe des Zeigers auf sensor_t lassen sich über die Funktion camera_sensor_info_t *esp_camera_sensor_get_info(sensor_id_t *id) Basisinformationen über das angeschlossene Kameramodell erhalten:

typedef struct {
    const camera_model_t model;          // Enum, das das jeweilige Kameramodell angibt (z. B. CAMERA_OV2640).
    const char *name;                    // Zeichenkette mit der Bezeichnung des Sensors (z. B. "OV2640").
    const camera_sccb_addr_t sccb_addr;  // I2C/SCCB-Kommunikationsadresse des Sensors ((Serial Camera Control Bus).
    const camera_pid_t pid;              // Der Wert des Produkt-ID-Registers wird direkt aus der Hardware ausgelesen.       
    const framesize_t max_size;          // Maximale Bildgröße/Auflösung, die von der Hardware unterstützt wird.
    const bool support_jpeg;             // Boolescher Schalter, der angibt, ob der Sensor JPEG nativ ausgeben kann.
} camera_sensor_info_t;

camera_model_t, camera_sccb_addr_t, camera_pid_t und framesize_t sind Enumerationswerte für die entsprechen Parameter des Kameramodells.

struct sensor_id_t

typedef struct {
    uint8_t MIDH; // Hersteller-ID High Byte
    uint8_t MIDL; // Hersteller-ID Low Byte
    uint16_t PID; // Produkt-ID
    uint8_t VER;  // Versionsnummer
} sensor_id_t;

Der Datentyp sensor_id_t dient zur eindeutigen Identifikation des angeschlossenen Kameramodells.

struct camera_status_t

typedef struct {
    framesize_t framesize;    // Bildauflösung (z.B. FRAMESIZE_VGA, FRAMESIZE_UXGA)
    bool scale;               // Downsampling aktiv
    bool binning;             // Pixel-Binning-Status. Kombiniert benachbarte Pixel für höhere Lichtempfindlichkeit bei geringerer Auflösung.
    uint8_t quality;          // JPEG-Qualität: 10 (hoch) bis 63 (niedrig)
    int8_t brightness;        // Helligkeit: -2 bis 2
    int8_t contrast;          // Kontrast: -2 bis 2
    int8_t saturation;        // Sättigung: -2 bis 2
    int8_t sharpness;         // Schärfe: -2 bis 2
    uint8_t denoise;          // Rauschunterdrückung aktiv (1) oder inaktiv (0)
    uint8_t special_effect;   // Digitale Effekte (0: Normal, 1: Negativ, 2: S/W, etc.)
    uint8_t wb_mode;          // Weißabgleich-Modus (0: Auto, 1: Sonnig, 2: Bewölkt...)
    uint8_t awb;              // Auto-Weißabgleich (1 = Ein, 0 = Aus)
    uint8_t awb_gain;         // Verstärkung für Auto-Weißabgleich (1 = Ein)
    uint8_t aec;              // Automatische Belichtungsregelung (1 = Ein)
    uint8_t aec2;             // Erweiterte automatische Belichtung (1 = Ein)
    int8_t ae_level;          // Belichtungsstufe: -2 bis 2
    uint16_t aec_value;       // Manueller Belichtungswert
    uint8_t agc;              // Automatische Verstärkungsregelung / Gain (1 = Ein)
    uint8_t agc_gain;         // Manueller Verstärkungswert
    uint8_t gainceiling;      // Maximale Verstärkungsgrenze (0 bis 6)
    uint8_t bpc;              // Pixel-Korrektur defekter Pixel (1 = Ein)
    uint8_t wpc;              // Weißpunkt-Korrektur (1 = Ein)
    uint8_t raw_gma;          // Gamma-Korrektur (1 = Ein)
    uint8_t lenc;             // Objektiv-Korrektur / Vignettierung (1 = Ein)
    uint8_t hflip;            // Bild horizontal spiegeln (1 = Ein)
    uint8_t vflip;            // Bild vertikal spiegeln (1 = Ein)
    uint8_t dcw;              // Downsize-Kompensation (1 = Ein)
    uint8_t colorbar;         // Test-Farbbalken anzeigen (1 = Ein)
} camera_status_t;

Der Datentyp camera_status_t liefert den aktuellen Zustand und die Konfigurationseinstellungen des Kamerasensors. Die Struktur spiegelt die Live-Einstellungen der Kamera während des Betriebs wider.

Verwendung

Die Struktur struct _sensor (im Code meist via typedef als sensor_t angesprochen) ist die zentrale Steuerungseinheit für den Kamerasensor (z. B. OV2640 oder OV5640) in der Espressif ESP32-Camera-Bibliothek.

Sie fungiert als Abstraktionsschicht (HAL) und enthält primär Funktionspointer, mit denen Bildparameter, Auflösungen und Hardware-Register direkt während des Betriebs verändert werden können. Ein Zeiger auf diese Struktur wird im Code üblicherweise über sensor_t *s = esp_camera_sensor_get(); geholt.

Die wichtigsten Funktionen und Funktionspointer der struct _sensor lassen sich in logische Kategorien unterteilen:

1. Basiskonfiguration und Sensor-Initialisierung

Diese Funktionen steuern den Zustand des Kamerasensors selbst:

2. Bildkorrektur und Belichtung (AEC / AGC / AWB)

Diese Steuerelemente regeln, wie der Kamerasensor auf Lichtverhältnisse reagiert:

3. Bildanpassung und Effekte

Hiermit lässt sich das visuelle Erscheinungsbild des Bildes direkt auf Hardware-Ebene manipulieren:

4. Bildausrichtung (Geometrie)

Sehr nützlich, wenn die Kamera im Gehäuse auf dem Kopf oder spiegelverkehrt verbaut ist:

5. Register-Direktzugriff (Low-Level)

Sollten vordefinierte Funktionen nicht ausreichen, bietet die Struktur direkten Zugriff auf die Hardware-Register des Sensors über den SCCB-Bus (I2C):

Bibliothek UrsESP32Camera

Die Espressif-Bibliotheken sind im alten C-Stil ohne Objektorientierung geschrieben. Objektorientierte Programmierung mit strenger Typisierung bietet eine besonders robuste Basis für Softwareprojekte. Zu den wichtigsten Vorteilen gehören höhere Codequalität, frühe Fehlererkennung und bessere Wartbarkeit. Die Bibliothek UrsESP32Camera kapselt die Funktionalitäten in einer Reihe von Klassen.

Datentypen

Enumerationen

Zur Gewährleistung der Typsicherheit sind die möglichen Eigenschaftswerte als Enum-Klasse (enum class) hinterlegt:

Datentypen

Basis-Klasse EspCamera

Die abstrakte Basis-Klasse EspCamera kapselt die Methoden der IDF-Funktionen aus der Kamera-Bibliothek (esp_camera.h). Von dieser Klasse werden Klassen für die speziellen Module abgeleitet, die insbesondere Funktion für die Initialisierung bereit stellen:

EspCamera

Die meisten Methoden der Klasse sind typsichere Wrapper um die entsprechenden IDF-Methoden. Hier wird auf den Bibliotheks-Code verwiesen.

Kamera-Initialisierung

Die abgeleitete Klasse muss die Methode makeRawConfig zur Verfügung stellen. Hier werden die Pin-Informationen in das von der Basis-Klasse bereitgestellte Feld config vom Typ camera_config_t geschrieben. Für die AI-Thinker-Cam mit einer OV2640 gilt folgende Pin-Belegung und weitere Standardeinstellungen:

void Ai_ThinkerOV2640::makeRawConfig() {
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27
#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22

//   camera_config_t config;
   config.pin_d0 = Y2_GPIO_NUM;
   config.pin_d1 = Y3_GPIO_NUM;
   config.pin_d2 = Y4_GPIO_NUM;
   config.pin_d3 = Y5_GPIO_NUM;
   config.pin_d4 = Y6_GPIO_NUM;
   config.pin_d5 = Y7_GPIO_NUM;
   config.pin_d6 = Y8_GPIO_NUM;
   config.pin_d7 = Y9_GPIO_NUM;
   config.pin_xclk = XCLK_GPIO_NUM;
   config.pin_pclk = PCLK_GPIO_NUM;
   config.pin_vsync = VSYNC_GPIO_NUM;
   config.pin_href = HREF_GPIO_NUM;
   config.pin_sccb_sda = SIOD_GPIO_NUM;
   config.pin_sccb_scl = SIOC_GPIO_NUM;
   config.pin_pwdn = PWDN_GPIO_NUM;
   config.pin_reset = RESET_GPIO_NUM;
   config.xclk_freq_hz = 20000000;
   config.pixel_format = PIXFORMAT_JPEG;
   config.grab_mode = CAMERA_GRAB_LATEST;
}

In der Methode init ergänzt die Basis-Klasse EspCamera die übergebenen Daten abhängig davon, ob ein PSRAM vorhanden ist (4 MB bei der AI-Thinker):

esp_err_t EspCamera::init() {
   makeRawConfig();

   config.ledc_channel = defaultLedcChannel;
   config.ledc_timer = defaultLedcTimer;

   if (psramFound()) {
      config.frame_size = FRAMESIZE_UXGA;
      config.jpeg_quality = 10;
      config.fb_count = 2;
      config.fb_location = CAMERA_FB_IN_PSRAM;
   }
   else {
      config.frame_size = FRAMESIZE_SVGA;
      config.jpeg_quality = 12;
      config.fb_count = 1;
      config.fb_location = CAMERA_FB_IN_DRAM;
   }

   esp_err_t err = esp_camera_init(&config);
   if (err == ESP_OK) {
      initDone = true;
      sensor = esp_camera_sensor_get();
      info = esp_camera_sensor_get_info(&sensor->id);
   }
   return err;
}

Flash-LED

Das AI-Thinker-Cam-Modul besitzt eine Flash-LED zur Ausleuchtung. Die Daten hierzu werden ebenfalls von der konkreten Klasse bereitgestellt. Im Konstruktor werden LED-Timer und LED-Channel zur Erzeugung eines PWM-Signals festgelegt. Mir ist nicht bekannt, in wie weit diese Informationen ausgewertet werden. Standardmäßig werden LEDC_TIMER_0 und LEDC_CHANNEL_0 verwendet.

Die Bibliothek stellt Funktionen zur Ansteuerung der LED bereit:

Funktion Wirkung Anmerkung
bool hasFlashLed() Liefert true, wenn das Kamera-Modul eine Flash-LED besitzt. Die AI-Thinker besitzt eine Flash-LED.
void setFlashLedValue(uint8_t value) Schaltet die Helligkeit der Flash-LED [0..255].  Bei 0 wird der Pin wieder frei gegeben (PIN-Mode = INPUT). Bei der AI-Thinker wird der Pin wird zur Ansteuerung der SD-Karte benutzt (Signal SD_DATA1).
uint8_t getFlashLedPin() Liefert den Pin der Flash-LED (oder -1, wenn keine Flash-LED vorhanden ist). Bei der AI-Thinker ist die Flash-LED an GPIO4 angeschlossen.

Foto abrufen

Der Abruf eines Fotos dient die Funktion getFrameBuffer. Sie liefert einen Zeiger auf eine Struktur vom Typ camera_fb_t

typedef struct {
    uint8_t * buf;              /* Pointer to the pixel data */
    size_t len;                 /* Length of the buffer in bytes */
    size_t width;               /* Width of the buffer in pixels */
    size_t height;              /* Height of the buffer in pixels */
    pixformat_t format;         /* Format of the pixel data */
    struct timeval timestamp;   /* Timestamp since boot of the first DMA buffer of the frame */
} camera_fb_t;

Wenn das Foto verarbeit wurde muss der Framebuffer zur weiteren Verwendung durch das Kamera-Modul wieder freigegenen werden (void returnFrameBuffer(camera_fb_t* fb)):

void getPicture(uint8_t flashInzensity) {
   camera_fb_t* fb = NULL;
   if (flashInzensity && camera.hasFlashLed()) {
      camera.setFlashLedValue(flashInzensity); // Flash an
      delay(150); // kurze Verzögerung, um die Kamera aufzuhellen
   }
   fb = camera.getFrameBuffer();
   // -------------------------------------------------------
   // Hier das Foro verarbeiten
   //--------------------------------------------------------
   camera.returnFrameBuffer(fb);
   if (flashMode && camera.hasFlashLed()) {
      camera.setFlashLedValue(0); // Flash aus
   }
}

 

Testprogramm

Das in der Bibliothek enthaltene Testprogramm listet die Kameraeinstellung auf und blinkt mit der Flash-LED:

// Diese Datei ist wegen der Umlaute UTF-8 codiert

#include "AppVersion.h"
#include "Ai_ThinkerOV2640.h"

EspCamera* camera;

const char* onoff(OptionOnOff o) {
   return o == OptionOnOff::on ? "on" : "off";
}

const char* level(int l) {
   switch (l) {
   case -2: return "lowest";
   case -1: return "lower";
   case 1:  return "higher";
   case 2:  return "highest";
   default:
      return "normal";
   }
}

void setup() {
   camera = new Ai_ThinkerOV2640(); // Instanz der Kamera-Klasse erstellen

   Serial.begin(115200);
   delay(500); // Warte kurz, damit die serielle Verbindung stabil ist
   Serial.println();
   Serial.printf("Start %s Version %s\n", APP_NAME, APP_VERSION);
   Serial.printf("Documentation: %s\n", APP_WEBSITE);
   Serial.printf("Author: %s\n", APP_AUTHOR);
   Serial.println();

   delay(500); // Warten, damit die Kamera hochgefahren ist.

   esp_err_t err = camera->init();  // Kamera initialisieren
   if (err != ESP_OK) {
      Serial.printf("Camera init failed with error 0x%x", err);
      return;
   }

   Serial.printf("Modellname: %s\n", camera->getCameraModelName().c_str());
   Serial.printf("Maximale Framegröße der Kamera: %s\n", EspCamera::getFrameSizeString(camera->getMaxFrameSize()).c_str());
   Serial.printf("Die Kamera unterstützt JPEG: %s\n", camera->supportsJpeg() ? "Ja" : "Nein");
   Serial.printf("PID: %i\n", (int)camera->getCameraPID());
 
  ...

   Serial.printf("DCW:            %s\n", onoff(camera->getDcw()));
   Serial.printf("Farbbalken:     %s\n", onoff(camera->getColorBar()));

   pinMode(camera->getFlashLedPin(), OUTPUT);
}

void loop() {
   analogWrite(camera->getFlashLedPin(), 10); // Flash-LED einschalten. Die Flash-LED ist sehr hell!
   delay(1000); // 1 Sekunde warten
   analogWrite(camera->getFlashLedPin(), 0); // Flash-LED ausschalten
   delay(1000); // 1 Sekunde warten
}

Die Ausgabe:

Start UrsESP32Camera-Test Version 1.0.0
Documentation: http://ullisroboterseite.de/esp32-UrsCamera.html
Author: Ulli

Modellname: OV2640
Maximale Framegröße der Kamera: UXGA (1600x1200)
Die Kamera unterstützt JPEG: Ja
PID: 38
SCCB/I2C Adresse: 48
XCLK Frequenz: 20000000 Hz
Flash-LED Pin: 4
PSRAM verfügbar

=== Einstellbare Eigenschaften ===
=== Bildgröße und Qualität ===
Pixel Format:   JPEG
Bildgröße:      UXGA (1600x1200)
Downsizing:     off
Pixel-Binning:  off
Qualität:       10
Rauschunterdr.: off
Autofokus:      Nein

=== Farb- und Belichtungswerte ===
Helligkeit:     normal
Konstrast:      normal
Sättigung:      normal
Schärfe:        normal
Spezialeffekt:  None

=== Automatische Regelungen ===
AGC:            on
AGC-Gain:       0
Gain-Ceiling:   2x
AEC:            on
Man. Bel.Zeit:  168
AECDSP:         off
AEC Level:      normal
A.Weißabgleich: on
W.Abgl. Profil: auto
ABW-Gain:       on

=== Bildkorrekturen und Filter ===
WPC:            on
BPC:            off
Raw Gamma:      on
Linsenkorrekt.: on

=== Orientierung und Testmuster ===
H. Spiegelung:  off
V. Spiegelung:  off
DCW:            on
Farbbalken:     off

 

Links

Random Nerd Tutorials: ESP32-CAM Projects, Tutorials and Guides with Arduino IDE

Random Nerd Tutorials: Change ESP32-CAM Camera Settings: Brightness, Resolution, Quality, Contrast, and More

GitHub Espressif Systems: https://github.com/espressif/esp32-camera

ESPRESSIF ESP-FAQ application solution: Camera Application

ESPRESSIF Espressif Camera Sensors Component

Edi's Techlab: ESP32-CAM Pinout und die Hardware detailliert beschrieben

AI-Thinker ESP32 Schaltplan

Makerguides: ESP32-CAM Blitz-LED steuern

OV2640 Datasheet

Arducam Blog: OV2640 – Specs, Datasheets, Cameras, Features, Alternatives

Source-Code github: espressif/esp32-camera

Video IR-Filter entfernen