網上找了一個拍照片之后用UDP傳輸的程序改的,有些頭文件應該沒用
做這個的原因是需要一個有無線功能的攝像頭用於校准機械臂抓取,淘寶上搜到了ESP32-CAM,但這個東西工作起來發熱嚴重,於是寫了深度睡眠和外部喚醒的功能
ESP32-CAM的供電和外部觸發都用的機械臂上的復用端口,程序調好之后連三根線就能工作,就是拍出來的圖片不太清晰,不知道能不能支持后續的校准
記錄一下調試過程
TCP服務端接收的數據轉jpg會報“字符串末尾有無法識別字符”的錯,百度了一下以為是沾包,於是就加了delay(100),現在想想可能是HEX字符串處理出了問題
板子一直無法訪問到TCP服務端,加了5000的延時就好了
上傳程序的時候報找不到板子的錯,原因是串口助手或者串口監視器開着,關掉就好了
里面的Wifi信息和TCP服務端信息要根據實際情況修改
順便記錄一下調試一個用ESP8266無線通訊的AGV的過程
代碼應該不會貼了,控制板用的STM32,我也不太會,剛做嵌入式沒幾天,一直沒空研究這個東西
調試過程中發現TCP怎么都連不上,以為是硬件的問題,從頭到尾換了一遍,最后用串口助手調試發現要連接TCP服務端地址跟我設置的不一樣,后來發現Keil下程序之前需要編譯一下,很低級的錯誤,只是我好久沒做C的東西了,全忘了
調試過程中發現一個問題
TCP服務端發送第一次take后,返回的圖片很暗很模糊,發送多次take並接收HEX數據后,圖片才變正常
而且,除第一次發送take外,之后發送take會重復發送之前的圖片數據,就是說比如我第五次發送take,它返回的是第二次或者第三次拍攝的照片,不過項目里只需要拍攝靜態物體,不影響用
#include "esp_camera.h" #include <WiFi.h> #include "esp_timer.h" #include "img_converters.h" #include "Arduino.h" #include "fb_gfx.h" #include "driver/rtc_io.h" #include "soc/soc.h" //disable brownout problems #include "soc/rtc_cntl_reg.h" //disable brownout problems const char *ssid = "*****"; const char *password = "*****"; const IPAddress serverIP(192,168,3,252); //欲訪問的地址 uint16_t serverPort = 8888; //服務器端口號 WiFiClient client; //聲明一個客戶端對象,用於與服務器進行連接 //定義單個數據包最大數據量 #define maxcache 1024 //定義相機類型 #define CAMERA_MODEL_AI_THINKER #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 #else #error "Camera model not selected" #endif void wifi_init(void) { WiFi.mode(WIFI_STA); WiFi.setSleep(false); //關閉STA模式下wifi休眠,提高響應速度 WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); //Serial.print("."); } //Serial.println("Connected"); //Serial.print("IP Address:"); //Serial.println(WiFi.localIP()); } void tcpclient_init(void) { //Serial.println("嘗試訪問服務器"); int i = 0; while(i<5) { if (client.connect(serverIP, serverPort,5000)) //嘗試訪問目標地址 { //Serial.println("訪問成功"); client.print("Hello world!"); //向服務器發送數據 return; } else { //Serial.println("訪問失敗"); client.stop(); //關閉客戶端 delay(5000); i++; } } } void setup() { WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector //Serial.setDebugOutput(true); Serial.begin(115200); Serial.println(); wifi_init(); tcpclient_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.pixel_format = PIXFORMAT_JPEG; config.frame_size = FRAMESIZE_XGA; config.jpeg_quality = 12; config.fb_count = 1; if(psramFound()) { config.frame_size = FRAMESIZE_UXGA; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA config.jpeg_quality = 10; config.fb_count = 2; } else { config.frame_size = FRAMESIZE_SVGA; config.jpeg_quality = 12; config.fb_count = 1; } esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, 1);//設置IO13端口高電平為睡眠喚醒 // Init Camera esp_err_t err = esp_camera_init(&config); if (err != ESP_OK) { //Serial.printf("Camera init failed with error 0x%x", err); return; } sensor_t * s = esp_camera_sensor_get(); s->set_brightness(s, 2); // up the brightness just a bit s->set_quality(s, 12); s->set_contrast(s, 2); s->set_saturation(s, 2); //Serial.printf("init success"); } void loop() { if(client.connected() || client.available())//如果已連接或有收到的未讀取的數據 { if(client.available()) //如果有數據可讀取 { String line = client.readStringUntil('\n'); //讀取數據到換行符 //Serial.print("讀取到數據:"); //Serial.println(line); client.write(line.c_str()); //將收到的數據回發 //收到take,拍一張照片並傳送給TCP服務端 if(line == "take") { rtc_gpio_hold_en(GPIO_NUM_4); camera_fb_t * fb = NULL; fb = esp_camera_fb_get(); uint8_t * temp = fb->buf; if(!fb) { //Serial.println("Camera capture failed"); } else { // 將圖片數據分段發送 int leng = fb->len; int timess = leng/maxcache; int extra = leng%maxcache; for(int j = 0;j< timess;j++) { client.write(fb->buf, maxcache); for(int i =0;i< maxcache;i++) { fb->buf++; } //Serial.println("succes to send image for tcp"); } client.write(fb->buf, extra); for(int j = 0;j< timess;j++) { for(int i =0;i< maxcache;i++) { fb->buf++; } //Serial.println("succes to send image for tcp"); } fb->buf = temp; //將當時保存的指針重新返還 esp_camera_fb_return(fb); //這一步在發送完畢后要執行,具體作用還未可知。 } } //收到stop,進入深度睡眠 if(line == "stop") { //Serial.println("關閉當前連接"); client.stop(); //關閉客戶端 esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, 1); int i = 0; while(i<10) { //Serial.println("Going to sleep now"+i); delay(100); i++; } esp_deep_sleep_start(); } } } else { //Serial.println("訪問失敗"); client.stop(); //關閉客戶端 } delay(5000); }
