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