Arduino——ESP32-CAM深度睡眠+外部喚醒+拍攝照片+TCP通訊


 

網上找了一個拍照片之后用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);
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM