在使用ESP32-CAM發布了一些項目後,一些讀者在嚐試使用 ESP32-CAM 時報告了問題。本指南彙總了使用 ESP32-CAM 時最常見的錯誤以及如何修複它們。
我們使用ESP32-CAM發布了以下項目:
注意:我們的一些讀者在嚐試使用 Home Assistant關注ESP32-CAM 項目時報告了錯誤。我們修改了代碼中的一些行,因此與該項目相關的大部分問題都應該得到修複。
請注意,我們最終無法重現某些錯誤。但是,我們已經收集了讀者提供的所有信息,以獲得最常見問題的答案。
如果您對這些問題有不同的問題或不同的解決方案,可以通過在下麵發表評論來分享您的提示。
最常見的錯誤:
連接 ESP32 失敗:等待數據包頭超時
相機初始化失敗,錯誤 0x20001 或類似錯誤
掉電檢測器或 Guru 冥想錯誤
Sketch too big error – 選擇了錯誤的分區方案
COMX 上的板不可用 - 未選擇 COM 端口
Psram 錯誤:未安裝 GPIO isr 服務
Wi-Fi 信號弱
Arduino IDE 串行監視器中沒有 IP 地址
無法打開網絡服務器
圖像滯後/顯示大量延遲
esp_camera_fb_get(): 無法按時取幀!
1. 連接ESP32失敗:等待包頭超時
此錯誤表示 ESP32-CAM 未處於閃爍模式或未正確連接到 FTDI 編程器。
仔細檢查上傳代碼的步驟
仔細檢查您是否已按照將 ESP32-CAM 置於閃爍模式的確切步驟進行操作。未能完成其中一個步驟可能會導致該錯誤。以下是您需要遵循的步驟:
使用 FTDI 編程器將 ESP32-CAM 板連接到您的計算機。按照下一個示意圖:
重要提示: GPIO 0需要連接到GND,以便您能夠上傳代碼。
許多 FTDI 編程器都有一個跳線,可以讓您選擇 3.3V 或 5V。確保跳線在正確的位置以選擇 5V。
重要提示: GPIO 0 需要連接到 GND,以便您能夠上傳代碼。
ESP32-CAM | FTDI 程序員 |
地線 | 地線 |
5V | VCC (5V) |
U0R | TX |
U0T | 接收 |
通用輸入輸出口 0 | 地線 |
要上傳代碼,請按照以下步驟操作:
1) 前往 工具 > 開發 板 並選擇 AI-Thinker ESP32-CAM。
2) 進入 工具 > 端口 ,選擇 ESP32 連接的 COM 端口。
3) 然後,點擊上傳按鈕上傳代碼。
4) 當您開始在調試窗口看到這些點時,如下圖所示,按下 ESP32-CAM 板載 RST 按鈕。
幾秒鍾後,代碼應該會成功上傳到您的開發板。
GPIO 0 必須連接到 GND
重要提示:如果您無法上傳代碼,請仔細檢查GPIO 0是否已連接到GND,並且您在“工具”菜單中選擇了正確的設置。您還應該按下板載重置按鈕以在閃爍模式下重新啟動 ESP32。另外,檢查您是否將 FTDI 編程器跳線帽設置為 5V。
檢查您正在使用的 FTDI 編程器
我們的一位讀者報告了以下內容:“發現您可以使用 USB-to-TTL 模塊模型 CP2102 對電路板進行編程,而 CH340 模型不起作用”。這是我們正在使用的 FTDI 程序員。
用 5V 為 ESP32-CAM 供電
我們的一些讀者報告說,他們隻能在 ESP32 由 5V 供電時上傳代碼。因此,用 5V 為 ESP32-CAM 供電。
FTDI 編程器 5V
使用萬用表測量FTDI 編程器(VCC 和 GND)的輸出電壓,以確保它為 ESP32-CAM 提供 5V 電壓。
2. 相機初始化失敗,錯誤 0x20001 或類似錯誤
如果您收到此確切錯誤,則意味著您的相機 OVX 未正確連接到您的 ESP32 開發板,或者您在代碼中的引腳分配錯誤。
有時,多次拔插 FTDI 編程器或多次重新啟動板,可能會解決問題。
相機未正確連接
相機有一個很小的連接器,您必須確保它立即連接並牢固安裝,否則將無法建立連接。
代碼中的引腳分配錯誤
當您收到此錯誤時,也可能意味著您沒有在定義部分選擇正確的電路板,或者您的電路板的引腳定義錯誤。
確保在項目中選擇正確的相機模塊。您隻需要取消注釋正確的相機模塊並注釋所有其他模塊:
//#define CAMERA_MODEL_WROVER_KIT//#define CAMERA_MODEL_M5STACK_PSRAM#define CAMERA_MODEL_AI_THINKER
在這個例子中,我們使用了 CAMERA_MODEL_AI_THINKER,所以它是啟用的。否則,引腳分配將失敗,相機將無法初始化。
有很多 esp32-cam 板(“假板”)被發布,ESP32 和 OV 相機之間的接線可能不同,因此選擇相機模塊可能還不夠。您可能需要使用您的電路板引腳排列檢查每個 gpio 聲明。
例如,不帶PSRAM 的M5Stack 板與帶PSRAM的 M5STACK (默認在代碼中定義)具有不同的引腳分配。因此,您需要根據電路板引腳排列更改代碼中的引腳定義。
通過 USB 電源供電不足
如果您通過計算機上的 USB 端口為 ESP32 供電,則它可能無法提供足夠的電力。
錯誤的 FTDI 程序員
一些讀者還報告了這個問題被更換自己的實際FTDI程序員解決了這一個。
相機/連接器壞了
如果出現此錯誤,也可能意味著您的相機或相機色帶已損壞。如果是這種情況,您可能會得到一個新的 OV2640 攝像頭探頭。
3. 掉電檢測器或 Guru 冥想錯誤
當您打開 Arduino IDE 串行監視器並且不斷地一遍又一遍地打印錯誤消息“已觸發斷電檢測器”時。這意味著存在某種硬件問題。
它通常與以下問題之一有關:
劣質 USB 數據線;
USB 線太長;
板子有缺陷(焊點不好);
電腦USB口壞;
或者電腦USB口供電不足。
解決方案:
嚐試不同的較短的 USB 電纜(帶數據線)
使用不同的計算機 USB 端口或使用帶有外部電源的 USB 集線器
一些讀者報告說,當用 5V 為 ESP32-CAM 供電時,問題得到了解決。
此外,請遵循問題 2 中描述的建議。
4. Sketch too big error – 選擇了錯誤的分區方案
當您收到以下錯誤時:
Sketch too big; see http://www.arduino.cc/en/Guide/Troubleshooting#size for tips on reducing it.Error compiling for board ESP32 Dev Module.
這意味著您沒有選擇正確的分區方案。確保選擇正確的分區方案。在您的 Arduino IDE 中,轉到Tools > Partition Scheme,選擇“ Huge APP (3MB No OTA) ”。
5. 板在 COMX 不可用 – 未選擇 COM 端口
如果您收到以下錯誤或類似錯誤:
serial.serialutil.SerialException: could not open port 'COM8': WindowsError(2, 'The system cannot find the file specified.')Failed to execute script esptoolthe selected serial port Failed to execute script esptool does not exist or your board is not connectedBoard at COM8 is not available
這意味著您沒有在工具菜單中選擇 COM 端口。在您的 Arduino IDE 中,轉到“工具” >“端口”並選擇 ESP32 連接到的 COM 端口。
這也可能意味著 ESP32-CAM 未與您的計算機建立串行連接或未正確連接到 USB 連接器。
6.Psram錯誤:GPIO isr服務沒有安裝
您使用的是沒有 PSRAM 的電路板,並且出現以下錯誤或類似錯誤:
E (161) gpio: gpio_isr_handler_remove(380): GPIO isr service is not installed, call gpio_install_isr_service() firstCamera init failed with error 0x101
當使用以下設置初始化電路板時:
config.frame_size = FRAMESIZE_UXGA;config.jpeg_quality = 10;config.fb_count = 2;
添加以下內容修複了問題(它降低了圖像分辨率,因此不需要太多空間來存儲圖像。但是,由於內存有限,您無法獲得某些高分辨率格式):
if(psramFound()){ config.frame_size = FRAMESIZE_UXGA; config.jpeg_quality = 10; config.fb_count = 2;} else { config.frame_size = FRAMESIZE_SVGA; config.jpeg_quality = 12; config.fb_count = 1;}
注意:人臉識別和檢測不適用於沒有 PSRAM 的電路板。但是,您仍然可以使用該板的所有其他功能。例如,雖然你不能使用這個項目的人臉識別和檢測功能(ESP32-CAM Video Streaming and Face Recognition with Arduino IDE),但你仍然可以玩這個例子並探索板的功能,隻要你有代碼中的正確引腳分配。
7. Wi-Fi 信號弱
一些讀者報告說,在用 5V 為 ESP32-CAM 供電後,他們獲得了更穩定的 Wi-Fi 信號。您可以閱讀此專用指南,了解如何將外部天線連接到 ESP32-CAM 並擴展 Wi-Fi 覆蓋範圍。
ESP32-CAM 可以選擇使用內置天線或外置天線。如果您的 ESP32-CAM AI-Thinker 沒有 Wi-Fi 連接或連接不良,則可能啟用了外部天線。 如果將外部天線連接到連接器,它應該可以正常工作。
檢查天線連接器旁的跳線 0K 電阻是否處於所需天線的正確位置。有3個白色的小方塊,像“<”一樣排列,中間位置很常見。
照片由 Helmut Schoenborn 提供
下圖顯示了對該區域的仔細觀察。您可以清楚地看到連接到內置天線的 0K 小電阻。
照片由 Helmut Schoenborn 提供
隨著電路板轉動,PCB天線向上:
要使用PCB天線,電阻必須在頂部位置,如下所示:/
對於天線連接器,電阻必須在底部位置,如下所示:\
因此,要啟用板載天線:
拆掉連接天線的電阻,就在這個位置\
並將兩個連接焊接在一起以啟用板載天線。
8. Arduino IDE 串行監視器中沒有 IP 地址
如果您隻看到串行監視器上打印的點 (……),則表示您的 ESP32-CAM 未與您的路由器建立 Wi-Fi 連接。
仔細檢查您的網絡憑據
您需要確保在以下變量中輸入了準確的網絡憑據(SSID 和密碼):
const char* ssid = "REPLACE_WITH_YOUR_SSID";const char* password = "REPLACE_WITH_YOUR_PASSWORD";
在 Arduino IDE 串行監視器中選擇正確的波特率
如果您沒有在 Arduino IDE 串行監視器中選擇正確的波特率,您將無法獲得您的開發板 IP 地址,或者您隻會在屏幕上看到垃圾。
確保選擇正確的波特率。在我們使用 ESP32-CAM 的示例中,我們使用 115200 波特率。
多次重置電路板
您可能還需要多次按下 ESP32-CAM 板載 RESET 按鈕以重新啟動 ESP 並在啟動期間打印 IP 地址。
RX 和 TX 交換
仔細檢查 ESP32 板和 FTDI 編程器之間的連接。RX 去 TX,TX 去 RX。如果這些連接被交換,ESP32-CAM 將無法與您的計算機建立串行通信。
無線範圍
如果路由器離您的 ESP32 板很遠,它可能無法捕捉到 Wi-Fi 信號。確保您的 ESP32-CAM 離路由器相當近。
9. 打不開網頁服務器
如果 ESP32-CAM 正在 Arduino IDE 串行監視器中打印 IP 地址,但是當您嚐試在 Web 瀏覽器中打開 Web 服務器時,您會看到一個空白屏幕,這通常意味著您正在嚐試訪問 ESP32-CAM Web具有多個 Web 瀏覽器選項卡的服務器。
目前,這些 ESP32-CAM 草圖一次隻能與一個客戶端連接。
10. 圖像滯後/顯示大量延遲
對於這麼小又便宜的相機,有一些延遲是正常的。一些讀者提出了以下建議以減少延遲:
使用獨立的 5V 電源為 ESP32-CAM 供電
在代碼中使用以下內容減小幀大小:
config.frame_size = FRAMESIZE_SVGA或config.frame_size = FRAMESIZE_VGA使用外部天線。
11. esp_camera_fb_get():無法按時取幀!
我們個人從未遇到過這個問題。然而,許多讀者在他們的 ESP32-CAM 板卡上遇到了這個錯誤。
我們的一位讀者 (Fibula) 提出以下建議來解決此問題:
“我使用 Aliexpress 的 ESP32-CAM 模塊 2MP OV2640 攝像頭傳感器模塊 Type-C USB 模塊。雖然沒有提到,但它沒有其他 M5 型號的額外 PSRAM,並且相機有一個改變的 IO 引腳。
請參閱此處:https : //github.com/m5stack/m5stack-cam-psram/blob/master/README.md 並向下滾動到界麵比較。
我們可能都在使用的 CameraWebServer Arduino 示例沒有定義這個 ESP32-CAM 模型。
您需要在主選項卡中自行添加添加:
#define CAMERA_MODEL_M5STACK_NO_PSRAM
在camera_pins.h選項卡中添加以下內容:
#elif defined(CAMERA_MODEL_M5STACK_NO_PSRAM)#define PWDN_GPIO_NUM -1#define RESET_GPIO_NUM 15#define XCLK_GPIO_NUM 27#define SIOD_GPIO_NUM 25#define SIOC_GPIO_NUM 23#define Y9_GPIO_NUM 19#define Y8_GPIO_NUM 36#define Y7_GPIO_NUM 18#define Y6_GPIO_NUM 39#define Y5_GPIO_NUM 5#define Y4_GPIO_NUM 34#define Y3_GPIO_NUM 35#define Y2_GPIO_NUM 17#define VSYNC_GPIO_NUM 22#define HREF_GPIO_NUM 26#define PCLK_GPIO_NUM 21
你很高興去。
另請注意,裸 ESP32-CAM 模塊的最大分辨率為 XGA 1024×768,我假設也是因為缺少 PSRAM。“
我們希望這個建議可以解決您的問題。請在評價部分留下您的意見。
使用更大的 microSD 卡
根據數據表,ESP32-CAM 應該隻支持 4GB microSD 卡。
但是,我們已經使用16GB microSD 卡進行了測試,效果很好。
即使您有 16GB,您也可能無法存儲超過 4GB 的空間。我們尚未測試存儲超過 4GB 的空間,因此我們不確定這一點。
這些項目是否與 M5Stack 板兼容?
是的,M5Stack ESP32 開發板與外部項目兼容。但是,您必須檢查您的相機引腳以確保您在代碼中分配了正確的代碼。
如何設置固定IP地址
要設置靜態/固定 IP 地址,您可以按照下一個教程進行操作:
將 ESP32-CAM 設置為接入點 (AP)
您可以將 ESP32-CAM 設置為接入點 (AP)。這意味著您可以直接連接到 ESP32-CAM,而無需連接到路由器。您可以使用以下代碼將您的視頻流網絡服務器設置為接入點:
/********* Rui Santos Complete project details at https://RandomNerdTutorials.com/esp32-cam-video-streaming-web-server-camera-home-assistant/ IMPORTANT!!! - Select Board "AI Thinker ESP32-CAM" - GPIO 0 must be connected to GND to upload a sketch - After connecting GPIO 0 to GND, press the ESP32-CAM on-board RESET button to put your board in flashing mode Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. *********/#include "esp_camera.h"#include <WiFi.h>#include "esp_timer.h"#include "img_converters.h"#include "Arduino.h"#include "fb_gfx.h"#include "soc/soc.h" //disable brownout problems#include "soc/rtc_cntl_reg.h" //disable brownout problems#include "esp_http_server.h"// Replace with your network credentialsconst char* ssid = "ESP32-Access-Point";const char* password = "123456789";#define PART_BOUNDARY "123456789000000000000987654321"// This project was tested with the AI Thinker Model, M5STACK PSRAM Model and M5STACK WITHOUT PSRAM#define CAMERA_MODEL_AI_THINKER//#define CAMERA_MODEL_M5STACK_PSRAM//#define CAMERA_MODEL_M5STACK_WITHOUT_PSRAM// Not tested with this model//#define CAMERA_MODEL_WROVER_KIT#if defined(CAMERA_MODEL_WROVER_KIT) #define PWDN_GPIO_NUM -1 #define RESET_GPIO_NUM -1 #define XCLK_GPIO_NUM 21 #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 19 #define Y4_GPIO_NUM 18 #define Y3_GPIO_NUM 5 #define Y2_GPIO_NUM 4 #define VSYNC_GPIO_NUM 25 #define HREF_GPIO_NUM 23 #define PCLK_GPIO_NUM 22#elif defined(CAMERA_MODEL_M5STACK_PSRAM) #define PWDN_GPIO_NUM -1 #define RESET_GPIO_NUM 15 #define XCLK_GPIO_NUM 27 #define SIOD_GPIO_NUM 25 #define SIOC_GPIO_NUM 23 #define Y9_GPIO_NUM 19 #define Y8_GPIO_NUM 36 #define Y7_GPIO_NUM 18 #define Y6_GPIO_NUM 39 #define Y5_GPIO_NUM 5 #define Y4_GPIO_NUM 34 #define Y3_GPIO_NUM 35 #define Y2_GPIO_NUM 32 #define VSYNC_GPIO_NUM 22 #define HREF_GPIO_NUM 26 #define PCLK_GPIO_NUM 21#elif defined(CAMERA_MODEL_M5STACK_WITHOUT_PSRAM) #define PWDN_GPIO_NUM -1 #define RESET_GPIO_NUM 15 #define XCLK_GPIO_NUM 27 #define SIOD_GPIO_NUM 25 #define SIOC_GPIO_NUM 23 #define Y9_GPIO_NUM 19 #define Y8_GPIO_NUM 36 #define Y7_GPIO_NUM 18 #define Y6_GPIO_NUM 39 #define Y5_GPIO_NUM 5 #define Y4_GPIO_NUM 34 #define Y3_GPIO_NUM 35 #define Y2_GPIO_NUM 17 #define VSYNC_GPIO_NUM 22 #define HREF_GPIO_NUM 26 #define PCLK_GPIO_NUM 21#elif 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#else #error "Camera model not selected"#endifstatic const char* _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY;static const char* _STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n";static const char* _STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n";httpd_handle_t stream_httpd = NULL;static esp_err_t stream_handler(httpd_req_t *req){ camera_fb_t * fb = NULL; esp_err_t res = ESP_OK; size_t _jpg_buf_len = 0; uint8_t * _jpg_buf = NULL; char * part_buf[64]; res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE); if(res != ESP_OK){ return res; } while(true){ fb = esp_camera_fb_get(); if (!fb) { Serial.println("Camera capture failed"); res = ESP_FAIL; } else { if(fb->width > 400){ if(fb->format != PIXFORMAT_JPEG){ bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len); esp_camera_fb_return(fb); fb = NULL; if(!jpeg_converted){ Serial.println("JPEG compression failed"); res = ESP_FAIL; } } else { _jpg_buf_len = fb->len; _jpg_buf = fb->buf; } } } if(res == ESP_OK){ size_t hlen = snprintf((char *)part_buf, 64, _STREAM_PART, _jpg_buf_len); res = httpd_resp_send_chunk(req, (const char *)part_buf, hlen); } if(res == ESP_OK){ res = httpd_resp_send_chunk(req, (const char *)_jpg_buf, _jpg_buf_len); } if(res == ESP_OK){ res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY)); } if(fb){ esp_camera_fb_return(fb); fb = NULL; _jpg_buf = NULL; } else if(_jpg_buf){ free(_jpg_buf); _jpg_buf = NULL; } if(res != ESP_OK){ break; } //Serial.printf("MJPG: %uB\n",(uint32_t)(_jpg_buf_len)); } return res;}void startCameraServer(){ httpd_config_t config = HTTPD_DEFAULT_CONFIG(); config.server_port = 80; httpd_uri_t index_uri = { .uri = "/", .method = HTTP_GET, .handler = stream_handler, .user_ctx = NULL }; //Serial.printf("Starting web server on port: '%d'\n", config.server_port); if (httpd_start(&stream_httpd, &config) == ESP_OK) { httpd_register_uri_handler(stream_httpd, &index_uri); }}void setup() { WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector Serial.begin(115200); Serial.setDebugOutput(false); 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.pixel_format = PIXFORMAT_JPEG; if(psramFound()){ config.frame_size = FRAMESIZE_UXGA; config.jpeg_quality = 10; config.fb_count = 2; } else { config.frame_size = FRAMESIZE_SVGA; config.jpeg_quality = 12; config.fb_count = 1; } // Camera init esp_err_t err = esp_camera_init(&config); if (err != ESP_OK) { Serial.printf("Camera init failed with error 0x%x", err); return; } // Connect to Wi-Fi network with SSID and password Serial.print("Setting AP (Access Point)…"); // Remove the password parameter, if you want the AP (Access Point) to be open WiFi.softAP(ssid, password); IPAddress IP = WiFi.softAPIP(); Serial.print("Camera Stream Ready! Connect to the ESP32 AP and go to: http://"); Serial.println(IP); // Start streaming web server startCameraServer();}void loop() { delay(1);}