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