خادم دفق الفيديو ESP32-CAM الذي يعرض I2C و SPI

وحدة CAM ESP-32 مع كاميرا من Diymore

خادم بث الفيديو ESP32-CAM


مثال للاستخدام هنا .

يجب عليك أولاً تثبيت المكتبات: Esp32 board في Arduino Ide Windows / Esp32 board في Arduino Ide Linux و Mac

الإعدادات التفصيلية في المقالة.

في حالتي ، استخدمت وحدة AI-THINKER غير المنضبطة
#define CAMERA_MODEL_AI_THINKER

وظيفة التعرف على الوجه لا تعمل بالنسبة لي. كان التعليق في المقال مفيدًا.

يبدو أن التعرف على الوجوه لم يعد يعمل (على الأقل مع البرنامج المثال) عند استخدام الأساسية 1.02 ESP. التراجع إلى 1.01 الأساسية واستخدام البرنامج المثال ينتمي إلى هذا الأساسية ، "إصلاح"

بعد التراجع إلى الإصدار السابق من المكتبة 1.01 كل شيء يعمل.


لدي زوج من شاشات I2C 128x64 و TFT SPI 128x128

المادة OV7670 مع FIFO كيفية توصيل الكاميرا إلى الشاشة إذا لم يكن لديك وحدة CAM. دعم كاميرات OV2640 و OV7670

في وقت كتابة هذا التقرير ، عملت ما يلي بالنسبة لي

كاميرا ESP32 + خادم Wifi + شاشة I2C (AdaFruit)
كاميرا ESP32 + شاشة SPI 1.44 بوصة TFT 128 × 128 v1.1 (AdaFruit)
كاميرا ESP32 + شاشة SPI 1.8 بوصة TFT 128 * 160 (مكتبة Espressif)

يتعارض برنامج WiFi مع ناقل SPI. الحل الممكن لاستخدام مكتبة مختلفة. نشأت المشكلة في وقت تهيئة وحدة WiFi.

المشكلة الرئيسية هي أن وحدة ESP32-CAM لديها عدد محدود من الأرجل الحرة. يتم استخدام جزء من المنافذ للكاميرا ، جزء بالتوازي مع بطاقة الذاكرة الرقمية المؤمنة. موصل بطاقة sd مثبت على اللوحة. استنتاج آخر (IO4) هو مصباح يدوي LED.

شاشة I2C B / W ليست ذات أهمية خاصة للاستخدام الحقيقي مع الصورة الواردة من الكاميرا. لون TFT وعالية الدقة. على ذلك يمكنك أن ترى بالفعل الوجه. على مثل هذا العرض أو دقة أعلى بقليل ، يمكنك عمل Door Door

سأقول على الفور أن مكتبة AdaFruit ليست الأسرع. تمكنت من عرض بضع إطارات في الثانية. من الأفضل استخدام المكتبات التي تعمل بمستوى منخفض. لكنني لم أتمكن من الحصول على ESP32_TFT_library مع شاشتي 1.44 "128 × 128 SPI V1.1. ربما ILI9163 غير مدعوم. أخذت 1.8" 128 * 160 SPI TFT وتمكنت من الضغط على حوالي 12 FPS! الارتباط .

هناك عدة مكتبات تعمل بشكل أسرع. لكن البعض لا يتم نقله إلى esp-32 ( link ):

4.98 ثانية Adafruit_ST7735
1.71 ثانية ST7735X_kbv
1.30 ثانية PDQ_ST7735

الفيديو يبدو رائعا:



عند استخدام منفذين ، يمكن أن يتلقى أحد منافذ أجهزة HSPI أو VSPI على متحكم الشاشة وعرضه مع برنامج التشغيل ILI9341 30 إطارًا في الثانية ( ارتباط ).



ولكن كما قلت سابقًا في وحدة ESP32-CAM ، فإن SPI واحد فقط مجاني. يتم عرضه على أرقام PIN التالية:

IO2 - DC (A0)
IO14 - CLK
IO15 - CS
IO13 - MOSI (SDA)
IO12 - MISO (الإدخال. غير مستخدم)

IO0 - BCKL (الخلفية. غير مستخدم)
IO16 - RST





كانت المكتبة الأولى التي جربتها هي AdaFruit SSD1306

I2C 128x64 الأزرق شاشة OLED



#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; } 


عند العمل في esp32 ، يتم استخدام مضاهاة البرامج I2C. تشارك IO14 و IO15. يمكن استخدام أي منافذ مجانية تقريبًا ، ولا يتم استخدام ناقل H / W.

كيفية توصيل شاشة أحادية اللون مقاس 0.96 "i2c OLED . يلزمك الانتباه إلى عنوان العرض الموجود على ناقل I2C. في هذه الحالة ، 0x3C

عرض SPI 1.8 "TFT 128 * 160 مكتبة Espressif




مخطط الأسلاك:

IO2 - A0
IO14 - SCK
IO15 - CS
IO13 - SDA
IO16 - إعادة تعيين


يوجد أيضًا قارئ بطاقة SD على السبورة

التكوين IO:

 // 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 

قم بتثبيت البيئة وبيئة التطوير من Espressif . تعليمات مفصلة حول كيفية القيام بذلك .

تثبيت المكتبة . يلزم إجراء تصويبين لتجميع المكتبة.

ماكيفيلي:

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

مكونات / tft / tftspi.c:

 + #include "driver/gpio.h 

التصحيح

ثم تثبيت برنامج تشغيل الكاميرا ESP32 .

تكوين:

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




السماح بالوصول إلى منفذ USB للبرامج الثابتة والمراقبة:

#sudo chmod 777 / dev / ttyUSB0

نحن نجمع ونملأ:

#make -j4 && جعل فلاش

يتم تحقيق 12FPS من خلال كتابة الحزمة باستخدام أسلوب send_data. التسجيل ليس بكسل بالبكسل ، ولكن سطر كامل يساوي عرض الشاشة:

 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; } 

تكوين الكاميرا
 // #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"); } 


جيست

FRAME_WIDTH هو عرض الإطار البالغ 320 بكسل لـ QVGA

 config.frame_size = FRAMESIZE_QVGA; // 320x240 

في الواقع ، نرى على نافذة العرض 128 * 160 من الإطار الكامل

قم بتسجيل التكوين باستخدام مخزن مؤقت لكاميرا فيديو واحدة (config.fb_count = 1)
التقط وقت الكاميرا: 32 مللي ثانية
إرسال وقت العازلة: 47 مللي ثانية
القبض على الإطار موافق.

يؤدي
1000 / (32 + 47) = 12.65 إطارًا في الثانية

سجل للتكوين مع اثنين من المخازن المؤقتة كاميرا الفيديو (config.fb_count = 2)
التقط وقت الكاميرا: 39 مللي ثانية

إرسال وقت العازلة: 63 مللي ثانية

القبض على الإطار موافق.
التقط وقت الكاميرا: 0 مللي ثانية

إرسال وقت العازلة: 59 مللي ثانية

القبض على الإطار موافق.
التقط وقت الكاميرا: 0 مللي ثانية

إرسال وقت العازلة: 34 مللي ثانية

القبض على الإطار موافق.
التقط وقت الكاميرا: 40 مللي ثانية

إرسال وقت العازلة: 64 مللي ثانية

القبض على الإطار موافق.
التقط وقت الكاميرا: 0 مللي ثانية

إرسال وقت العازلة: 59 مللي ثانية

القبض على الإطار موافق.
التقط وقت الكاميرا: 0 مللي ثانية

إرسال وقت العازلة: 34 مللي ثانية

القبض على الإطار موافق.
التقط وقت الكاميرا: 40 مللي ثانية

إرسال وقت العازلة: 63 مللي ثانية

القبض على الإطار موافق.
التقط وقت الكاميرا: 0 مللي ثانية

إرسال وقت العازلة: 60 مللي ثانية

القبض على الإطار موافق.
التقط وقت الكاميرا: 0 مللي ثانية

إرسال وقت العازلة: 34 مللي ثانية

القبض على الإطار موافق.
التقط وقت الكاميرا: 39 مللي ثانية

إرسال وقت العازلة: 63 مللي ثانية

القبض على الإطار موافق.
التقط وقت الكاميرا: 0 مللي ثانية

إرسال وقت العازلة: 60 مللي ثانية

القبض على الإطار موافق.
التقط وقت الكاميرا: 1 مللي ثانية

إرسال وقت العازلة: 34 مللي ثانية

القبض على الإطار موافق.
التقط وقت الكاميرا: 40 مللي ثانية

إرسال وقت العازلة: 63 مللي ثانية

القبض على الإطار موافق.
التقط وقت الكاميرا: 0 مللي ثانية

إرسال وقت العازلة: 60 مللي ثانية

القبض على الإطار موافق.
التقط وقت الكاميرا: 0 مللي ثانية

إرسال وقت العازلة: 34 مللي ثانية

القبض على الإطار موافق.
التقط وقت الكاميرا: 40 مللي ثانية

إرسال وقت العازلة: 63 مللي ثانية

القبض على الإطار موافق.
التقط وقت الكاميرا: 0 مللي ثانية

إرسال وقت العازلة: 59 مللي ثانية

القبض على الإطار موافق.
التقط وقت الكاميرا: 0 مللي ثانية

إرسال وقت العازلة: 35 مللي ثانية

القبض على الإطار موافق.

نظرًا لاستخدام المخزن المؤقت الثاني لكاميرا الفيديو ، يتم الحصول على المخزن المؤقت في بعض الدورات على الفور. في البداية ، يتم الحصول على الدورة الكاملة بأقل من استخدام مخزن مؤقت واحد ، ولكن هذه المرة "تعمل". الفاصل الزمني بين الدورات العائمة.

عدة مرات مسكت في سجلات "تم تشغيل كاشف Brownout" لذا أغلقت جهاز الكشف. لأنه في البداية أطعمت شاشة الإضاءة الخلفية من دبوس 3.3V ESP32-CAM

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

استنتاج


ESP32 وحدة وظيفية منخفضة التكلفة. هناك نقص كارثي في ​​الاستنتاجات للمنافذ المنفذة في إصدار CAM من اللوحة ، لذا اختر إصدار CAM إذا كنت بحاجة إلى كاميرا بالفعل.

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


All Articles