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.
Inhaltsverzeichnis
| Version | Anpassungen |
|---|---|
| 1.0 (2026-11-10) | Basis-Version |
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).
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.
Das ESP32-CAM verfügt über insgesamt 16 Pins. Der Übersichtlichkeit halber sind Pins mit ähnlicher Funktion zusammengefasst. Die Pinbelegung sieht wie folgt aus:

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.
Bildquelle: https://github.com/SeeedDocument/forum_doc/blob/master/reg/ESP32_CAM_V1.6.pdf
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).
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). |
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;
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.
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.
Bei vorhandenem PSRAM: Immer fb_location = CAMERA_FB_IN_PSRAM verwenden, um den internen SRAM des ESP32 zu schonen.
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.
fb_count
= 1) verwendet wird.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.
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;
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.
| 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ß. |
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;
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.
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.
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.
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):
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.
Zur Gewährleistung der Typsicherheit sind die möglichen Eigenschaftswerte als Enum-Klasse (enum class) hinterlegt:
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:
Die meisten Methoden der Klasse sind typsichere Wrapper um die entsprechenden IDF-Methoden. Hier wird auf den Bibliotheks-Code verwiesen.
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;
}
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. |
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
}
}
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
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
Makerguides: ESP32-CAM Blitz-LED steuern
Arducam Blog: OV2640 – Specs, Datasheets, Cameras, Features, Alternatives
Source-Code github: espressif/esp32-camera
Video IR-Filter entfernen