安信可 ESP32-S3 模组上驱动摄像头 OV2640,实现远程拍照并 HTTP 传输到阿里云对象存储OSS,并显示在微信小程序上。(深度好文,全部开源)


  • 本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途。如有不对之处,请留言,本人及时更改。

系列一:ESP32系列模组基础学习系列笔记

1、 爬坑学习新旅程,虚拟机搭建esp32开发环境,打印 “Hellow World”。
2、 巧用eclipes编辑器,官方教程在在Windows下搭建esp32开发环境,打印 “Hellow World”。
3、 认识基本esp32的GPIO接口,开始点亮您的第一盏 LED和中断回调实现按键功能 。
4、体会esp32的强大的定时器功能, 实现定时2s闪烁一盏LED灯。
5、接触实践esp32的pwm宽度脉冲功能, 实现呼吸效果闪烁一盏LED灯。
6、smartConfig和微信airKiss在esp32的实现,一键配网轻松快捷连接路由器。
7、利用GPIO中断做一个按键的短按和长按的回调事件,再也无须担心触发源。
8、esp32上实现本地 UDP 客户端和服务端角色,在局域网内实现通讯。
9、esp32上实现本地 TCP 客户端和服务端角色,可断线重连原路返回数据。
10、乐鑫esp32 SDK编程利用rmt驱动ws2812七彩灯,实现彩虹渐变效果。
11、入门 乐鑫esp-adf 音频框架开发,esp32造一个蓝牙耳机,实现切换歌曲,获取歌曲信息等功能。
12、开源一个微信公众号airkiss配网esp32以及局域网发现功能的工程,分享一个airkiss配网小工具。
13、esp32 内置 dns 服务器,无需外网访问域名返回指定网页。
14、esp32 sdk编程实现门户强制认证,连接esp32热点之后,自动强制弹出指定的登录界面。
15、认识本地离线语音唤醒识别框架 esp-skainet ,实现较低成本的硬件语音本地识别控制。
16、学习本地语音唤醒离线识别框架 esp-skainet ,如何修改唤醒词? 如何自定义命令词?如何做意图动作?
17、全网首发,乐鑫esp32 sdk直连京东微联·小京鱼 · IoT开放平台,实现叮咚音响语音智能控制。
18、入门京东微联·小京鱼的控制面板H5开发,读懂vue语法,做自己的控制页面。
19、重磅开源,如何在微信小程序上ble蓝牙配网esp32,blufi的那些事!
20、一篇好文,开发过程中编译esp32固件太大,无法正常启动?教你如何自定义分区表partitions.csv。
21、 esp32蓝牙配网blufi的高度封装,集成简单、使用简单、容易上手,提高开发效率!
22、讨论下程序员 “青春饭” 那些事,分享在esp32实现多种加密算法md5 |AES CBC-ECB| Sha1 | Sha256 等!
23、安信可 esp32-a1s 音频开发板移植最新 esp-adf 音频框架,小试牛刀如何实现在线文字转语音播放。
25、分享在 esp32 SDK实现冷暖光色温平滑调节的封装,轻松集成到您的项目去。
26、分享下如何在window下使用CMake编译,编译速度提高传统 make 编译一个档次,支持 ESP32 和 ESP32-C3。
27、windows10平台下自带的Linux安装 ESP8266/ESP32 环境,再无需额外安装虚拟机了。

系列二:ESP32-Camera 摄像头开发板系列笔记

1、安信可 ESP32-Cam 摄像头开发板二次开发 C SDK编程,实现MQTT远程拍照传输到私有服务器。
2、安信可 ESP32-Cam 摄像头开发板二次开发 C SDK编程,实现本地视频流监控。
3、安信可 ESP32-Cam 摄像头开发板二次开发 C SDK编程,拍照图片通过有线串口传到上位机PC端。

系列三:ESP32-C3 模组系列笔记

1、【蓝牙Mesh笔记 ①】ESP32-C3 模组上实现天猫精灵蓝牙 BLE Mesh AliGenie 接入,无需WiFi 连接也可以实现天猫精灵语音控制。

系列四:ESP32-S3 模组系列笔记

1、安信可 ESP32-S3 模组上驱动摄像头 OV2640,实现远程拍照并 HTTP 传输到阿里云对象存储OSS,并显示在微信小程序上。。



在这里插入图片描述

前言

     第一批拿到了安信可 ESP32-S3模组的样品,今天给大家分享下这个模组的规格,此模组精准聚焦 AIoT 市场,响应市场对 AI 算法的技术需求,那么此文章介绍的是ESP32-S3模组上驱动摄像头 OV2640,后续将继续更新此系列博文。


在这里插入图片描述

一、 ESP32-S3 产品特性

   拿到了安信可的ESP32-S3样品,当然得查看其规格啦。

CPU 和存储

Xtensa® 32 位 LX7 双核处理器,主频高达 240 MHz
• 128 位数据总线位宽,支持 SIMD 指令
• 384 KB ROM
• 512 KB SRAM
• 16 KB RTC SRAM
• SPI、Dual SPI、Quad SPI、Octal SPI、QPI、OPI 接口外接多个 flash 和片外 RAM

外设接口和传感器

• 45 × GPIO 口 • 数字接口:
• 4 × SPI
• 1 × LCD 接口(8 位 ~16 位并行 RGB, I8080, MOTO6800), 支持 RGB565, YUV422, YUV420, YUV411 之间互相转换
• 1 × DVP 8 位 ~16 位摄像头接口
• 3 × UART
• 2 × I2C
• 2 × I2S
• 1 × RMT (TX/RX)
• 1 × 脉冲计数器
• LED PWM 控制器,多达 8 个通道
• 1 × 全速 USB OTG
• 1 × USB Serial/JTAG 控制器
• 2 × MCPWM
• 1 × SDIO 主机接口,具有 2 个卡槽
• DMA 控制器,5 个接收通道和 5 个发送通道
• 1 × TWAI® 控制器(兼容 ISO11898-1)
• 2 × 12 位 SAR ADC,多达 20 个通道
• 1 × 温度传感器 – 14 × 电容式传感 GPIO • 定时器:
• 4 × 54 位通用定时器
• 1 × 52 位系统定时器
• 3 × 看门狗定时器

功耗特性

   ESP32-S3 采用了先进的电源管理技术,可以在不同的功耗模式之间切换。ESP32-S3 支持的功耗模式有:

Active 模式:CPU 和芯片射频处于工作状态。芯片可以接收、发射和侦听信号。
Modem-sleep 模式:CPU 可运行,时钟频率可配置。Wi-Fi 基带和射频关闭,但 Wi-Fi 可保持连接。
Light-sleep 模式:CPU 暂停运行。RTC 外设以及 ULP 协处理器可被定时器周期性唤醒运行。任何唤醒事 件(MAC、主机、RTC 定时器或外部中断)都会唤醒芯片。Wi-Fi 可保持连接。
Deep-sleep 模式:CPU 和大部分外设都会掉电,只有 RTC 存储器和 RTC 外设处于工作状态。Wi-Fi 连接 数据存储在 RTC 中。ULP 协处理器可以工作。
Hibernation 模式:内置快速 RC 振荡器时钟和 ULP 协处理器均被禁用。只有 1 个位于低速时钟上的 RTC 时钟定时器和某些 RTC GPIO 在工作。RTC 时钟定时器或 RTC GPIO 可以将芯片从 Hibernation 模式中唤 醒。 设备在

不同的功耗模式下有不同的电流消耗,详情请见下面:

功耗模式 描述 典型值 单位
Light-sleep CPU 暂停运行。 240 µA
Deep-sleep RTC 存储器和 RTC 外设处于工作状态 8 µA
Hibernation RTC 存储器处于工作状态,RTC 外设处于关闭状态 7 µA
Power off CHIP_PU 管脚拉低,芯片处于关闭状态 1 µA

二、 准备工作

硬件

  • 安信可 ESP32-S3 模组。

  • TTL-USB 调试工具(推荐使用 CP2102串口芯片的 ,保证足够的电压电流)。

软件

  • 环境搭建: Linux环境搭建 master 分支
  • 工具链设置:下载 toolchain,博主使用的版本是:gcc version 5.2.0 (crosstool-NG crosstool-ng-1.22.0-97-gc752ad5)
  • Python版本:Python 3.8

接线

摄像头引脚 模组引脚
pin_pwdn GPIO_NUM_35
pin_reset GPIO_NUM_36
pin_xclk GPIO_NUM_15
pin_sscb_sda GPIO_NUM_4
pin_sscb_scl GPIO_NUM_5
pin_d7 GPIO_NUM_16
pin_d6 GPIO_NUM_17
pin_d5 GPIO_NUM_18
pin_d4 GPIO_NUM_12
pin_d3 GPIO_NUM_11
pin_d2 GPIO_NUM_10
pin_d1 GPIO_NUM_9
pin_d0 GPIO_NUM_8
pin_vsync GPIO_NUM_6
pin_href GPIO_NUM_7
pin_pclk GPIO_NUM_13

三、通讯协议和原理

在这里插入图片描述

3.1 模组拍照上传服务器

协议: HTTP

POST /index.php HTTP/1.1
Host: www.domain.com
Content-Type: image/jpeg
Name-Pic: name
Content-Length: 12540


"<file contents here>"

3.2 小程序下发指令给模组拍照给服务器

协议:MQTT
Topic:/light/deviceIn
payload:

{
    "action" : "0" ,
    "name" : "pic-name"
}

3.3 模组把上传服务器结果回调给小程序

协议:MQTT
Topic:/light/deviceOut
payload:

{
  "url" : "base64(url)" 
}

url 是拍照之后的可外网访问的图片地址,使用 base64 加密。


四、服务器准备

3.1 接收图片处理

本代码以HTTP 协议POST提交 ,二进制形式把图片上传到服务器。其格式如下:

POST /index.php HTTP/1.1
Host: www.domain.com
Content-Type: image/jpeg
Name-Pic: name
Content-Length: 12540

"<file contents here>"

因此,服务器要以数据流接收,以 PHP语言为例:

//接受数据流
$stream = file_get_contents('php://input');
//数据流转化为png格式,并保存在指定的位置
$len = file_put_contents('/www/wwwroot/static/' . time() . ".png", $stream); 

3.2 接收图片处理

    public function upload()
    {
    
    
        $getPostDataArry = apache_request_headers();

        try {
    
    
            $name = $getPostDataArry['Name-Pic'];
        } catch (Exception $e) {
    
    
            if (empty($name)) {
    
    
                $response_data['code'] = 1;
                $response_data['des'] = ' Name-Pic is not exist';
                return json($response_data);
            }
        }
        //接受数据流
        $stream = file_get_contents('php://input');
        //数据流转化为png格式,并保存在指定的位置
        $len = file_put_contents('/www/wwwroot/www.xuhongv.com/public/icon/' . $name . ".png", $stream);
        $response_data = [];
        if ($len) {
    
    
            $accessKeyId = "LTAI4Fg*********YJBLPoTo5";
            $accessKeySecret = "OT7s9vkQd*******4p8KQ31qoTIL4";
            $endpoint = "we****ong.oss-cn-hongkong.aliyuncs.com";
            $bucket = 'web****hong';
            try {
    
    
                $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, true);
                //判断存储空间是否存在
                $isExist = $ossClient->doesBucketExist($bucket);
                if (!$isExist) {
    
    
                    $response_data['code'] = 1;
                    $response_data['des'] = $endpoint . ' is not exist';
                    return json($response_data);
                }
                $options = array();
                //oss 存储文件路径
                $object = "images/" . $name . ".png";
                $ossClient->uploadFile($bucket, $object, '/www/wwwroot/www.xuhongv.com/public/icon/' . $name . ".png", $options);
            } catch (OssException $e) {
    
    
                $response_data['code'] = 1;
                $response_data['des'] = $e->getMessage();
                return json($response_data);
            }
            $response_data['code'] = 0;
            $response_data['des'] = 'uploadup ok';
            $response_data['url'] = base64_encode("https://" . $endpoint . '/' . $object);
            return json($response_data);
        }
        $response_data['code'] = 1;
        $response_data['des'] = "error , the upload file length is" . $len;
        return json($response_data);
    }
}

3.3 服务器业务逻辑

  1. 接受到S3模组发过来的图片,存储到本地服务器某个文件夹里面。
  2. 同时把这个图片,发送到阿里云对象存储,返回一个可远程访问图片的地址给模组。

五、嵌入式开发准备

配置服务器信息,然后拍照上传。

    //配置服务器相关信息
    esp_http_client_config_t config = {
        .url = "http://domain.xuhongv.com/api/upload",
        .method = HTTP_METHOD_POST,
        .event_handler = _http_event_handler,
        .buffer_size = 4096,
        .user_data = local_response_buffer, 
        .buffer_size_tx = 4096 * 5,
        .timeout_ms = 10000
    };

    //开始拍照
    pic = esp_camera_fb_get();

    if (!pic)
    {
        ESP_LOGE(TAG, "Camera capture failed");
        goto end;
    }
    else
    {
        esp_camera_fb_return(pic);

        pic = esp_camera_fb_get();

        if (!pic)
        {
            ESP_LOGE(TAG, "Camera capture failed");
         }
        else
        {
            //拍照成功,获取其大小、尺寸等信息
            ESP_LOGI(TAG, "Camera capture OK , Its size was: %zu bytes", pic->len);
            ESP_LOGI(TAG, "Camera capture OK , Its width was: %d", pic->width);
            ESP_LOGI(TAG, "Camera capture OK , Its height was: %d ", pic->height);

            esp_http_client_handle_t esp_client = esp_http_client_init(&config);

            //设置HTTP请求头为image/jpg表示图片类型
            esp_http_client_set_header(esp_client, "Content-Type", "image/jpg");

            //设置图片名字
            esp_http_client_set_header(esp_client, "Name-Pic", &(test_task_param->pic_name_p));

            //把图片放在body里面
            esp_http_client_set_post_field(esp_client, (const char *)pic->buf, pic->len);

            //开始执行请求服务器
            res = esp_http_client_perform(esp_client);

            //判断是否请求成功
            if (res == ESP_OK)
            {
                ESP_LOGI(TAG, "HTTPS Status = %d", esp_http_client_get_status_code(esp_client));
            }
            else
            {
                ESP_LOGE(TAG, "perform http request %s", esp_err_to_name(res));
            }
            ESP_ERROR_CHECK(esp_http_client_cleanup(esp_client));
        }
    }

六、微信小程序开发准备

配置服务器信息,然后拍照上传。

    data: {
    host: 'a0je61b5.mqtt.iot.gz.baidubce.com',
    subTopic: '/light/deviceOut',
    pubTopic: '/light/deviceIn',
    msg: 'Hello! I am from WeChat miniprogram',
    //默认显示的图片
    img_url: 'https://docs.ai-thinker.com/_media/o1cn01faxszt1ls4mym2mkb_2922621297.png',
    mqttOptions: {
      protocolVersion: 4, //MQTT连接协议版本
      clientId: 'DeviceId-jviujtntjy',
      clean: true,
      password: 'sM2hrD6kcRFlmIgR2F',
      username: 'a0je61a/wechat',
      reconnectPeriod: 1000, // 1000毫秒,两次重新连接之间的间隔
      connectTimeout: 30 * 1000, // 1000毫秒,两次重新连接之间的间隔
      resubscribe: true // 如果连接断开并重新连接,则会再次自动订阅已订阅的主题(默认true)
     }
    }
    
    let that = this

    client = mqtt.connect(`wxs://${this.data.host}/mqtt`, this.data.mqttOptions)

    client.on('reconnect', (error) => {
      console.log('Reconnecting...')
    })

    client.on('error', (error) => {
      console.log('连接失败:', error)
    })

    client.on('connect', () => {
      wx.showToast({
        title: '连接成功'
      })

      client.subscribe(this.data.subTopic, (err) => {
      })
      client.on('message', (topic, payload) => {
        let object = JSON.parse(payload)
        //base64解码url地址
        let url = that.base64_decode(object.url)
        console.log(url)
        that.setData({
          img_url: url
        })
        wx.showModal({
          content: `收到 Topic: ${topic}, Payload:  ${url}`,
          showCancel: false,
        });
      })
    })

源码下载

模组代码:https://github.com/xuhongv/StudyInEsp32/tree/master/24_esp32s2_s3_camera_wechat_mini

微信小程序代码:https://github.com/xuhongv/RemoteWeChatForESP

服务器代码:见本文章服务器代码介绍章节。

另外,不要把我的博客作为学习标准,我的只是笔记,难有疏忽之处,如果有,请指出来,也欢迎留言哈!

  • 玩转esp8266带你飞、加群QQ群,不喜的朋友勿喷勿加:434878850
  • 个人邮箱:[email protected] 24小时在线,有发必回复!
  • esp8266源代码学习汇总(持续更新,欢迎star):https://github.com/xuhongv/StudyInEsp8266
  • esp32源代码学习汇总(持续更新,欢迎star):https://github.com/xuhongv/StudyInEsp32
  • 关注下面微信公众号二维码,干货多多,第一时间推送!

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/xh870189248/article/details/120481155