ESP32-CAM-Video-Streaming-Server zum Verbinden von I2C- und SPI-Displays

ESP-32 CAM-Modul mit Kamera von Diymore

ESP32-CAM Video Streaming Server


Ein Anwendungsbeispiel finden Sie hier .

Sie müssen zuerst die Bibliotheken installieren: Esp32-Karte in Arduino Ide Windows / Esp32-Karte in Arduino Ide Linux und Mac

Detaillierte Einstellungen finden Sie im Artikel.

In meinem Fall habe ich das AI-THINKER-Modul so unkommentiert verwendet
#define CAMERA_MODEL_AI_THINKER

Die Funktionalität der Gesichtserkennung hat bei mir nicht funktioniert. Der Kommentar im Artikel war hilfreich.

Es scheint, dass die Gesichtserkennung (zumindest mit dem Beispielprogramm) bei Verwendung des 1.02 ESP-Kerns nicht mehr funktioniert. Wenn Sie auf den 1.01-Kern zurücksetzen und das zu diesem Kern gehörende Beispielprogramm verwenden, wird dies behoben

Nach dem Zurücksetzen auf die vorherige Version von Bibliothek 1.01 hat alles funktioniert.


Ich habe ein Paar I2C 128x64- und TFT SPI 128x128-Displays

Artikel OV7670 mit FIFO zum Anschließen der Kamera an das Display, wenn Sie kein CAM-Modul haben. Unterstützt OV2640- und OV7670-Kameras

Zum Zeitpunkt des Schreibens hat Folgendes für mich funktioniert

ESP32-Kamera + WLAN-Server + I2C-Display (AdaFruit)
ESP32-Kamera + SPI-Display 1,44 "TFT 128x128 v1.1 (AdaFruit)
ESP32-Kamera + SPI-Display 1,8 "TFT 128 * 160 (Espressif-Bibliothek)

Der WiFi-Treiber steht in Konflikt mit dem SPI-Bus. Mögliche Lösung zur Verwendung einer anderen Bibliothek. Das Problem trat zum Zeitpunkt der Initialisierung des WiFi-Moduls auf.

Das Hauptproblem besteht darin, dass das ESP32-CAM-Modul eine begrenzte Anzahl freier Beine hat. Ein Teil der Anschlüsse wird für die Kamera verwendet, ein Teil parallel zur SD-Karte. Der SD-Kartenanschluss ist auf der Platine installiert. Eine weitere Schlussfolgerung (IO4) ist die LED-Taschenlampe.

Das I2C-Display in Schwarzweiß ist für den tatsächlichen Gebrauch mit dem von der Kamera empfangenen Bild nicht von besonderem Interesse. TFT-Farbe und hohe Auflösung. Darauf sieht man schon das Gesicht. Auf einem solchen Display oder einer etwas höheren Auflösung können Sie das Türauge machen

Ich werde gleich sagen, dass die AdaFruit-Bibliothek nicht die schnellste ist. Ich habe es geschafft, ein paar Bilder pro Sekunde anzuzeigen. Es ist vielversprechender, Bibliotheken zu verwenden, die auf niedrigem Niveau arbeiten. Aber ich konnte keine ESP32_TFT_Bibliothek mit meinem Display 1.44 "128x128 SPI V1.1 erhalten. Vielleicht wird ILI9163 nicht unterstützt. Ich habe 1.8" 128 * 160 SPI TFT genommen und es geschafft, ungefähr 12 FPS zu quetschen! Link

Es gibt einige Bibliotheken, die schneller arbeiten. Einige sind jedoch nicht für esp-32 ( Link ) portiert:

4,98 Sek. Adafruit_ST7735
1,71 Sek. ST7735X_kbv
1,30 Sek. PDQ_ST7735

Das Video sieht beeindruckend aus:



Bei Verwendung von zwei Ports kann einer der HSPI- oder VSPI-Hardware-Ports des Mikrocontrollers und der Anzeige mit dem ILI9341-Treiber 30 Bilder pro Sekunde empfangen ( Link ).



Wie ich bereits im ESP32-CAM-Modul erwähnt habe, ist nur ein SPI kostenlos. Es wird auf den folgenden PINS angezeigt:

IO2 - DC (A0)
IO14 - CLK
IO15 - CS
IO13 - MOSI (SDA)
IO12 - MISO (Eingabe. Nicht verwendet)

IO0 - BCKL (Hintergrundbeleuchtung. Nicht verwendet)
IO16 - RST





Die erste Bibliothek, die ich ausprobiert habe, war AdaFruit SSD1306

I2C 128x64 Blaues OLED-Display



#include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 64 // OLED display height, in pixels // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) Adafruit_SSD1306 display; void init_display(){ pinMode(14,INPUT_PULLUP); pinMode(15,INPUT_PULLUP); Wire.begin(14,15); display = Adafruit_SSD1306(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64 Serial.println(F("SSD1306 allocation failed")); for(;;); // Don't proceed, loop forever } .... 

camera_capture ()
 #define BACKCOLOR 0x0000 // Black #define PIXELCOLOR 0xFFFF // White #define FRAME_WIDTH 320 #define FRAME_HEIGHT 240 uint16_t pixel_color = 0; esp_err_t camera_capture(){ //acquire a frame camera_fb_t * fb = esp_camera_fb_get(); if (!fb) { ESP_LOGE(TAG, "Camera Capture Failed"); return ESP_FAIL; } int i = 0; for(int y = 0; y < SCREEN_HEIGHT; y++){ for(int x = 0; x < SCREEN_WIDTH; x++){ i = y * FRAME_WIDTH + x; // FRAMESIZE_QVGA // 320x240 char ch = (char)fb->buf[i]; if (ch > 128) pixel_color = WHITE; else pixel_color = BLACK; // Draw a single pixel in white display.drawPixel(x, y, pixel_color); } } display.display(); //return the frame buffer back to the driver for reuse esp_camera_fb_return(fb); Serial.println("Capture frame ok."); return ESP_OK; } 


Bei der Arbeit in esp32 wird die Software I2C-Emulation verwendet. Beteiligte IO14 und IO15. Es können fast alle freien Ports verwendet werden, nicht der H / W-Bus.

So schließen Sie ein monochromes 0,96 "i2c-OLED-Display an . Sie müssen auf die Anzeigeadresse am I2C-Bus achten. In diesem Fall 0x3C

SPI-Anzeige 1,8 "TFT 128 * 160 Espressif Library




Schaltplan:

IO2 - A0
IO14 - SCK
IO15 - CS
IO13 - SDA
IO16 - RESET


Auf der Platine befindet sich auch ein SD-Kartenleser

E / A-Konfiguration:

 // Configuration for other boards, set the correct values for the display used //---------------------------------------------------------------------------- #define DISP_COLOR_BITS_24 0x66 //#define DISP_COLOR_BITS_16 0x55 // Do not use! // ############################################# // ### Set to 1 for some displays, ### // for example the one on ESP-WROWER-KIT ### // ############################################# #define TFT_INVERT_ROTATION 0 #define TFT_INVERT_ROTATION1 0 // ################################################ // ### SET TO 0X00 FOR DISPLAYS WITH RGB MATRIX ### // ### SET TO 0X08 FOR DISPLAYS WITH BGR MATRIX ### // ### For ESP-WROWER-KIT set to 0x00 ### // ################################################ #define TFT_RGB_BGR 0x08 // ############################################################## // ### Define ESP32 SPI pins to which the display is attached ### // ############################################################## // The pins configured here are the native spi pins for HSPI interface // Any other valid pin combination can be used #define PIN_NUM_MISO 12 // SPI MISO #define PIN_NUM_MOSI 13 // SPI MOSI #define PIN_NUM_CLK 14 // SPI CLOCK pin #define PIN_NUM_CS 15 // Display CS pin #define PIN_NUM_DC 2 // Display command/data pin #define PIN_NUM_TCS 0 // Touch screen CS pin (NOT used if USE_TOUCH=0) // -------------------------------------------------------------- // ** Set Reset and Backlight pins to 0 if not used ! // ** If you want to use them, set them to some valid GPIO number #define PIN_NUM_RST 0 // GPIO used for RESET control #define PIN_NUM_BCKL 0 // GPIO used for backlight control #define PIN_BCKL_ON 0 // GPIO value for backlight ON #define PIN_BCKL_OFF 1 // GPIO value for backlight OFF // -------------------------------------------------------------- // ####################################################### // Set this to 1 if you want to use touch screen functions // ####################################################### #define USE_TOUCH TOUCH_TYPE_NONE // ####################################################### // ####################################################################### // Default display width (smaller dimension) and height (larger dimension) // ####################################################################### #define DEFAULT_TFT_DISPLAY_WIDTH 128 #define DEFAULT_TFT_DISPLAY_HEIGHT 160 // ####################################################################### #define DEFAULT_GAMMA_CURVE 0 #define DEFAULT_SPI_CLOCK 32000000 #define DEFAULT_DISP_TYPE DISP_TYPE_ST7735B //---------------------------------------------------------------------------- #define TFT_INVERT_ROTATION 0 #define TFT_INVERT_ROTATION1 1 #define TFT_INVERT_ROTATION2 0 

Installieren Sie die Umgebung und die Entwicklungsumgebung von Espressif . Detaillierte Anweisungen dazu .

Installieren Sie die Bibliothek . Zum Zusammenstellen der Bibliothek müssen zwei Korrekturen vorgenommen werden.

Makefile:

 + CFLAGS += -Wno-error=tautological-compare \ + -Wno-implicit-fallthrough \ + -Wno-implicit-function-declaration 

Komponenten / tft / tftspi.c:

 + #include "driver/gpio.h 

Patch

Installieren Sie dann den ESP32-Kameratreiber .

Konfigurieren:

#. $ HOME / esp / esp-idf / export.sh
# idf.py menuconfig




Ermöglichen Sie den Zugriff auf den USB-Anschluss für Firmware und Überwachung:

#sudo chmod 777 / dev / ttyUSB0

Wir sammeln und füllen:

#make -j4 && Flash machen

12FPS wird durch Paketschreiben mit der Methode send_data erreicht. Die Aufnahme erfolgt nicht Pixel für Pixel, sondern als ganze Zeile, die der Breite des Bildschirms entspricht:

 esp_err_t camera_capture(){ uint32_t tstart, t1, t2; tstart = clock(); //acquire a frame camera_fb_t * fb = esp_camera_fb_get(); if (!fb) { printf("Camera Capture Failed\n"); return ESP_FAIL; } t1 = clock() - tstart; printf("Capture camera time: %u ms\r\n", t1); int i = 0, bufPos = 0; uint8_t hb, lb; color_t color; color_t *color_line = heap_caps_malloc(_width*3, MALLOC_CAP_DMA); tstart = clock(); for(int y = 0; y < _height; y++) { bufPos = 0; for(int x = 0; x < _width; x++) { i = (y * FRAME_WIDTH + x) << 1; hb = fb->buf[i] ; lb = fb->buf[i + 1]; color.r = (lb & 0x1F) << 3; color.g = (hb & 0x07) << 5 | (lb & 0xE0) >> 3; color.b = hb & 0xF8; color_line[bufPos] = color; bufPos++; // TFT_drawPixel(0, 0, color, 1); } disp_select(); send_data(0, y, _width-1, y, _width, color_line); wait_trans_finish(1); disp_deselect(); } free(color_line); t1 = clock() - tstart; printf("Send buffer time: %u ms\r\n", t1); esp_camera_fb_return(fb); printf("Capture frame ok.\n"); return ESP_OK; } 

Kamerakonfiguration
 // #if defined(CAMERA_MODEL_AI_THINKER) #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 void camera_init_(){ camera_config_t config; config.ledc_channel = LEDC_CHANNEL_0; config.ledc_timer = LEDC_TIMER_0; 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_sscb_sda = SIOD_GPIO_NUM; config.pin_sscb_scl = SIOC_GPIO_NUM; config.pin_pwdn = PWDN_GPIO_NUM; config.pin_reset = RESET_GPIO_NUM; config.xclk_freq_hz = 20000000; config.fb_count = 2; // for display config.frame_size = FRAMESIZE_QVGA; config.pixel_format = PIXFORMAT_RGB565; // camera init esp_err_t err = esp_camera_init(&config); if (err != ESP_OK) { printf("Camera init failed with error 0x%x", err); return; } printf("Camera init OK\n"); } 


Kern

FRAME_WIDTH ist die Bildbreite von 320 Pixel für QVGA

 config.frame_size = FRAMESIZE_QVGA; // 320x240 

Tatsächlich sehen wir im Anzeigefenster 128 * 160 das Vollbild

Protokollieren Sie die Konfiguration mit einem Videokamerapuffer (config.fb_count = 1).
Kamerazeit erfassen: 32 ms
Sendepufferzeit: 47 ms
Frame erfassen ok.

Ergebnis
1000 / (32 + 47) = 12,65 FPS

Protokollieren Sie die Konfiguration mit zwei Camcorder-Puffern (config.fb_count = 2).
Kamerazeit erfassen: 39 ms

Sendepufferzeit: 63 ms

Frame erfassen ok.
Kamerazeit erfassen: 0 ms

Sendepufferzeit: 59 ms

Frame erfassen ok.
Kamerazeit erfassen: 0 ms

Sendepufferzeit: 34 ms

Frame erfassen ok.
Kamerazeit erfassen: 40 ms

Sendepufferzeit: 64 ms

Frame erfassen ok.
Kamerazeit erfassen: 0 ms

Sendepufferzeit: 59 ms

Frame erfassen ok.
Kamerazeit erfassen: 0 ms

Sendepufferzeit: 34 ms

Frame erfassen ok.
Kamerazeit erfassen: 40 ms

Sendepufferzeit: 63 ms

Frame erfassen ok.
Kamerazeit erfassen: 0 ms

Sendepufferzeit: 60 ms

Frame erfassen ok.
Kamerazeit erfassen: 0 ms

Sendepufferzeit: 34 ms

Frame erfassen ok.
Kamerazeit erfassen: 39 ms

Sendepufferzeit: 63 ms

Frame erfassen ok.
Kamerazeit erfassen: 0 ms

Sendepufferzeit: 60 ms

Frame erfassen ok.
Kamerazeit erfassen: 1 ms

Sendepufferzeit: 34 ms

Frame erfassen ok.
Kamerazeit erfassen: 40 ms

Sendepufferzeit: 63 ms

Frame erfassen ok.
Kamerazeit erfassen: 0 ms

Sendepufferzeit: 60 ms

Frame erfassen ok.
Kamerazeit erfassen: 0 ms

Sendepufferzeit: 34 ms

Frame erfassen ok.
Kamerazeit erfassen: 40 ms

Sendepufferzeit: 63 ms

Frame erfassen ok.
Kamerazeit erfassen: 0 ms

Sendepufferzeit: 59 ms

Frame erfassen ok.
Kamerazeit erfassen: 0 ms

Sendepufferzeit: 35 ms

Frame erfassen ok.

Durch Verwendung des zweiten Puffers des Camcorders wird der Puffer in einigen Zyklen sofort erhalten. Zuerst wird der vollständige Zyklus in weniger als der Verwendung eines Puffers erhalten, aber dieses Mal läuft es weiter. Das Intervall zwischen den Zyklen ist schwebend.

Mehrmals habe ich in den Protokollen "Brownout-Detektor wurde ausgelöst" abgefangen, also habe ich den Detektor ausgeschaltet. Denn zuerst habe ich die Hintergrundbeleuchtung über den 3,3-V-ESP32-CAM-Pin gespeist

 #include "soc/rtc_cntl_reg.h" ... WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector 

Fazit


Kostengünstiges ESP32-Funktionsmodul. Es gibt einen katastrophalen Mangel an Schlussfolgerungen für die implementierten Ports in der CAM-Version der Karte. Wählen Sie daher die CAM-Version, wenn Sie wirklich eine Kamera benötigen.

Source: https://habr.com/ru/post/de463157/


All Articles