3.26 haas506 2.0开发教程-example- 串口控制ESP32-CAM OV2640拍照

news2024/11/15 17:20:28

haas506串口控制ESP32-CAM OV2640拍照

  • 介绍
      • ESP32-CAM开发板
  • 硬件连接
  • 代码流程
  • 代码
      • ESP32-CAM开发板代码
      • HaaS506开发板代码
  • 测试
      • ESP32-CAM开发板测试

介绍

  • 通过HaaS506串口发送指令,控制ESP32-CAM进行拍照,并将照片储存在SD卡中。
  • ESP32-CAM需要5V供电才能正常使用,可以使用HaaS506直接进行供电。

ESP32-CAM开发板

  • ESP32-CAM开发板自带OV2640摄像头。ESP32-CAM采用DIP封装,直接插上底板即可使用。

在这里插入图片描述

  • 本案例使用Arduino环境进行开发。需要自行安装开发环境,配置ESP32编程环境。

  • 可参考ESP32-CAM烧录测试视频 密码:897399
    在这里插入图片描述

  • 选择开发板:ESP32 Wrover Module,选择CH340对应下载端口

  • 在这里插入图片描述
    在这里插入图片描述

硬件连接

在这里插入图片描述

代码流程

  • ESP32-CAM开发板上电连接WIFI,联网自动校准网络时间。
  • 按下HaaS506开发板KEY键,开发板串口向ESP32-CAM开发板发送指令。
  • ESP32-CAM开发板收到指令后拍照,获取当前时间作为文件名,将照片保存至SD卡。

代码

ESP32-CAM开发板代码

  • 代码需要更改WiFi密码
  • 使用Arduino环境下载
#include "esp_camera.h"
#include "FS.h"
#include <SPI.h>
#include <SD.h>
#include "SD_MMC.h"
#include <time.h> 
#include <WiFi.h>
#include "string.h"

const char* ntpServer = "cn.pool.ntp.org";  //pool.ntp.org为获取时间得接口,可以尝试更多得接口。比如微软的time.windows.com,美国国家标准与技术研究院的time.nist.gov
const long  gmtOffset_sec = 8*60*60;//这里采用UTC计时,中国为东八区,就是 8*60*60
const int   daylightOffset_sec = 0*60*60;
struct tm timeinfo;  //创建一个结构体用于存储时间
char * path = "/2020_6_18_TIME_19_0_47.jpg";
char timr_str[40] = "test.jpg";

//uart接收初始化
String inputString = "";
bool stringComplete = false;

//**************************************************************************************************************************************  wifi初始化

//以下是WIFI的链接用户名和密码
#define ssid "*********"
#define password "***********" 


void connectToNetwork(){
  WiFi.begin(ssid,password);
  WiFi.setAutoReconnect(true);
  while (WiFi.status()!= WL_CONNECTED) {
    delay(1000);
    Serial.println("try to connecting ...");
  }
  Serial.println("Connectedto network");
}

void wifi_connect(){
  connectToNetwork();//链接到wifi
  Serial.println(WiFi.macAddress());    //打印出mac地址
  Serial.println(WiFi.localIP());    //打印出本地ip地址
  Serial.println("wifi连接成功");    //打印出本地ip地址
}
//**************************************************************************************************************************************  摄像头初始化参数
static camera_config_t camera_config = {
    .pin_pwdn = 32,
    .pin_reset = -1,
    .pin_xclk = 0,
    .pin_sscb_sda = 26,
    .pin_sscb_scl = 27,
    
    .pin_d7 = 35,
    .pin_d6 = 34,
    .pin_d5 = 39,
    .pin_d4 = 36,
    .pin_d3 = 21,
    .pin_d2 = 19,
    .pin_d1 = 18,
    .pin_d0 = 5,
    .pin_vsync = 25,
    .pin_href = 23,
    .pin_pclk = 22,
    
    .xclk_freq_hz = 20000000,
    .ledc_timer = LEDC_TIMER_0,
    .ledc_channel = LEDC_CHANNEL_0,
    
    .pixel_format = PIXFORMAT_JPEG,
    .frame_size = FRAMESIZE_XGA,    // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA      320×240|  |640×480|800×600|1024×768|1400×1050|1600×1200
    .jpeg_quality = 12,             //10-63 lower number means higher quality
    .fb_count = 1,
};

esp_err_t camera_init() {
    //initialize the camera
    esp_err_t err = esp_camera_init(&camera_config);
    if (err != ESP_OK) {
        Serial.print("Camera Init Failed");
        return err;
    }
    sensor_t * s = esp_camera_sensor_get();
    //initial sensors are flipped vertically and colors are a bit saturated
    if (s->id.PID == OV2640_PID) {
    //        s->set_vflip(s, 1);//flip it back
    //        s->set_brightness(s, 1);//up the blightness just a bit
    //        s->set_contrast(s, 1);
    }
    Serial.print("Camera Init OK");
    return ESP_OK;
}
//**************************************************************************************************************************************  SD卡初始化参数
void sd_init()
{
  if(!SD_MMC.begin()){
    Serial.println("Card Mount Failed");
    return;
  }
  uint8_t cardType = SD_MMC.cardType();
  if(cardType == CARD_NONE){
    Serial.println("No SD card attached");
    return;
  }
  Serial.print("SD Card Type: ");
  if(cardType == CARD_MMC){
    Serial.println("MMC");
    } 
  else if(cardType == CARD_SD){  Serial.println("SDSC");  }
  else if(cardType == CARD_SDHC){  Serial.println("SDHC");  } 
  else {  Serial.println("UNKNOWN");  }
  
  uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024);    //获取SD卡大小,大小单位是MB
  Serial.printf("SD 卡容量大小: %lluMB\n", cardSize);  
  }
//**************************************************************************************************************************************  获取当前时间作为返回的函数部分
void get_time_path()  //获取目前时间返回字符串
{
    memset(timr_str, 0, sizeof(timr_str));
    configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
    if(!getLocalTime(&timeinfo))
    {
      Serial.println("Failed to obtain time");
      sprintf(timr_str, "/TIME_get_failed.jpg");
    }
    else
    {
      //Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
      Serial.print("现在时间是:");
      Serial.print("年份是:");Serial.println(timeinfo.tm_year + 1900);
      Serial.print("月份是:");Serial.println(timeinfo.tm_mon + 1);
      Serial.print("号数是:");Serial.println(timeinfo.tm_mday);
      Serial.print("小时数是:");Serial.println(timeinfo.tm_hour );  //中国区
      Serial.print("分钟数是:");Serial.println(timeinfo.tm_min);
      Serial.print("分钟数是:");Serial.println(timeinfo.tm_sec);
      sprintf(timr_str, "/%d_%d_%d_TIME_%d_%d_%d.jpg",timeinfo.tm_year+1900,timeinfo.tm_mon + 1,timeinfo.tm_mday,timeinfo.tm_hour,timeinfo.tm_min,timeinfo.tm_sec);
      }
  }
//**************************************************************************************************************************************  主函数部分
void setup() {
    Serial.begin(115200);
    wifi_connect();
    camera_init();  //摄像头初始化
    sd_init();  //SD卡初始化
}


void loop()              //接收uart传输过来的字符信息,如果inputString字符为123则进行拍照,时间作为文件名,将照片保存在SD中。 
{
    if (Serial.available()) { 
    // get the new byte:
    char inChar = (char)Serial.read();
    // add it to the inputString:
    if (inChar != '\n')     
    {
      inputString += inChar;
    }
    // if the incoming character is a newline, set a flag
    // so the main loop can do something about it:
    if (inChar == '\n') 
    {
      stringComplete = true;
    }
    
    if (stringComplete) 
    {
      inputString=String(inputString);
      if (inputString == "123")  //进行拍照
      {
        //拍照并且把图片保存到SD卡当中,而照片名字就保存为目前的时间
        Serial.println("即将进行拍照!!!");
        camera_fb_t * fb = esp_camera_fb_get();
        get_time_path();
        Serial.print("存入的图片名称为:");Serial.println(timr_str);
        path = timr_str;    
        if(fb == NULL)
        {
          Serial.println( "get picture failed");  //代表获取图片失败
        }else{ 
           //char * path = time_str;
           fs::FS &fs = SD_MMC;
           Serial.printf("Writing file: %s\n", path);
           File file = fs.open(path, FILE_WRITE);
           if (!file) 
           {
             Serial.println("文件创建失败");
            }
           else
           {
             file.write(fb->buf , fb->len); //payload , lengte vd payload
             Serial.println("成功写入照片");
           }
           //return the frame buffer back to the driver for reuse
           esp_camera_fb_return(fb);
        } 
      }
      inputString = "";
      stringComplete = false;
    }
  }
}

HaaS506开发板代码

main.py

import utime as time
from driver import GPIO
from driver import UART


#串口实例化
uart=UART()
uart.open("serial1")
writeBuf = bytearray('123\n')
readBuf = bytearray(4)
#按键功能初始化
key1=GPIO(10,10)
key1.open("KEY1")
#按键中断回调函数
def key1_callback(args):
    uart.write(writeBuf)
    print("Photo taken successfully !!!")
    key1.disableIrq()
    key1.clearIrq()


def enable_key():
    #开启中断
    key1.enableIrq(key1_callback)


if __name__ == '__main__':
    enable_key()
    print('Press key to start taking pictures')
    uart.write(writeBuf)
    while True:
        time.sleep(1)

board.json

  • 使用485读取log
{
  "name": "haas506",
  "version": "2.0.0",
  "io": {       
    "KEY1": {
      "type": "GPIO",
      "port": 44,
      "dir": "irq",
      "pull": "pullup",
      "intMode": "falling"
    },
  "serial1":{
    "type":"UART",
    "port":0,
    "dataWidth":8,
    "baudRate":115200,
    "stopBits":1,
    "flowControl":"disable",
    "parity":"none"
  }
  },
  "debugLevel": "ERROR",
  "repl": "enable",
  "replPort": 2
}

测试

总的测试情况,按下HaaS506开发板key键后可以通过485串口读取到log

在这里插入图片描述

U盘中会增加当前时间的照片。
在这里插入图片描述

ESP32-CAM开发板测试

ESP32-CAM程序运行测试,打开串口监视器。
在这里插入图片描述
发送指令,打印相关log
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/188543.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

小程序开发常见问题总结(超实用)

小程序开发常见问题总结&#xff08;超实用&#xff09; 文章目录小程序开发常见问题总结&#xff08;超实用&#xff09;1.小程序user agent stylesheet问题。2.this.setData is not function错误3.flex布局3.1flex布局原理3.2flex父项属性3.3flex布局子项元素4.自定义组件1.在…

白银k线图基础知识梳理:包覆形态

伦敦银价格走势是国际市场上所有参与者多方合力的结果&#xff0c;这些参与者包括银行、白银商、期货交易商、对冲基金等金融机构、各种法人机构以及个人投资者。一根简单的K线&#xff0c;能够把所有市场参与者博弈的结果展示出来&#xff0c;并且反映出银价运行和变化的各个细…

node后端接收到axios的post请求体为空

node后端接收到axios的post请求体为空&#xff1f;&#xff1f;&#xff1f; 使用axios发送post请求&#xff0c;传入了Object格式的参数&#xff0c;在node后端req.body接收到的参数为空&#xff0c;但是网页上抓包检查时&#xff0c;发现请求的body确实是携带了参数的&#x…

【工具】2023开年利器,重写收藏逻辑和内置白板应用的Arc浏览器

目录一、为什么你需要一款新的浏览器&#xff1f;二、重写的收藏夹逻辑三、自带笔记和白板的浏览器四、如何获得Arc浏览器一、为什么你需要一款新的浏览器&#xff1f; 人生漫漫&#xff0c;三年混乱。在经历了这些起伏之后&#xff0c;你一定有一个不断进取的决心。 工欲善其…

如何设置将SAP红灯报错改为黄灯(OBA5 更改消息控制 )

在SAP的业务操作中或者后台配置经常遇到SAP校验报红灯的错误导致业务进行不下去。可以通过OBA5 更改消息控制事务修改消息报错类型&#xff0c;例如把红灯报错改为黄灯&#xff0c;这样业务就可以进行下去了。 举两个例子来说明一下如何配置。 目录 例子1&#xff1a;固定资…

【stl -- 内建函数对象】

目录&#xff1a;前言一、仿函数二、算数仿函数三、关系仿函数四、逻辑仿函数总结前言 概念 stl内建了一些仿函数 分类 算数仿函数、 关系仿函数、 逻辑仿函数 用法 这些仿函数所产生的对象&#xff0c;用法和普通函数完全一样&#xff1b; 使用内建仿函数需要包含头文件 一、…

拉伯证券|A股大涨!外资30分钟爆买百亿!汽车股狂飙

在很多利好音讯的轮番影响下&#xff0c;兔年首个交易日&#xff0c;A股迎来大涨。沪指开盘便站上3300点整数关口&#xff0c;尔后继续高位震动。深证成指、创业板指涨势更甚&#xff0c;到午盘涨幅均超1.5%。 外资继续“高调”抢筹。Choice数据显现&#xff0c;今天开盘仅5分…

Maven基础学习——依赖管理

本专栏主要是记录学习完JavaSE后学习JavaWeb部分的一些知识点总结以及遇到的一些问题等&#xff0c;如果刚开始学习Java的小伙伴可以点击下方连接查看专栏 本专栏地址&#xff1a;&#x1f525;JavaWeb Java入门篇&#xff1a; &#x1f525;Java基础学习篇 Java进阶学习篇&…

18个 SpringBoot项目中遇到的BUG,你试试

有人说&#xff1a;一个人从1岁活到80岁很平凡&#xff0c;但如果从80岁倒着活&#xff0c;那么一半以上的人都可能不凡。 生活没有捷径&#xff0c;我们踩过的坑都成为了生活的经验&#xff0c;这些经验越早知道&#xff0c;你要走的弯路就会越少。 1.启动项目的时候报错 1.E…

从零到一,臻于至善|网易邮箱基于StarRocks 开发大数据平台的实践

作者&#xff1a;网易邮箱 黄贤康。现任职网易邮件事业部资深数据开发工程师&#xff0c;作为主要开发人员参与网易邮箱大数据平台的建立、优化、重构等工作&#xff0c;并取得相当的成效。他长期从事服务端应用及大数据领域的架构研发工作&#xff0c;对相关领域的底层架构、开…

什么是一站式人力资源管理系统?

首先什么是人力资源管理系统&#xff1f;简单来讲&#xff0c;人力资源管理系统就是帮助企业人力资源部门进行日常管理的辅助工具。人力资源部门通常需要负责企业员工管理的各个方面&#xff0c;无论是招聘&#xff0c;培训&#xff0c;考勤还是薪资绩效&#xff0c;都需要企业…

Jmeter使用手册

Jmeter使用手册Jmeter使用手册1.Jmeter安装教程下载地址Jmeter环境变量配置启动应用实例1.Jmeter安装教程下载地址https://jmeter.apache.org/download_jmeter.cgiJmeter环境变量配置新建变量名称:JMETER_HOME值为:D:\work_tools\apache-jmeter-5.5添加到path:%JMETER_HOME%\bi…

服务器应该如何做好防护以及被攻击之后如何处理

服务器是每个软件运行的基础&#xff0c;也是运行过程中最重要的一部分&#xff0c;所以在运行的过程中&#xff0c;服务器会受到黑客的不法攻击&#xff0c;那么服务器我们应该如何做好防护以防被攻击呢&#xff01;接下来小蚁君给大家一一讲解。首先可以安装最新的安全补丁&a…

仪表板展示 | DataEase看中国:数据呈现中国能源发展情况

背景介绍 能源是经济发展的基石&#xff0c;能源的供给与人们生活和经济发展息息相关。二十大报告强调&#xff1a;“要积极稳妥推进碳达峰碳中和&#xff0c;立足我国能源资源禀赋&#xff0c;坚持先立后破&#xff0c;有计划分步骤地实施碳达峰行动。深入推进能源革命&#…

Elasticsearch使用篇 - 更新文档

更新的内部机制 注意&#xff1a;实际使用 murmurhash 算法 注意&#xff1a;更新任何一个字段都是全部删除。并发更新操作之间无事务隔离保证&#xff0c;会产生数据错位问题。 更新操作 1、单条覆盖更新 1、覆盖式更新&#xff0c;由客户端完成所有数据的组装&#xff0c;…

35. 实战:Python实现视频去水印(文末源码)

目录 前言 目的 思路 代码实现 1. 请求URL&#xff0c;查看源代码 2. 源代码中没有就去抓包工具 3. 拿到视频源链接&#xff0c;继续检索来源 4. 拿到数据和链接&#xff0c;二进制写入到本地 完整源码 运行效果 总结 前言 我们在刷某短视频平台时&#xff0c;有些…

SpringCloud搭建微服务之Vault密钥管理

1. 概述 Vault是一款管理密钥和保护敏感数据的组件&#xff0c;用于保护、存储和严格控制对令牌、密码、证书和加密密钥的访问&#xff0c;可以使用UI客户端、CLI和HTTP API访问密钥和其他敏感数据。更多详细介绍&#xff0c;可以参阅vault官网 2. Vault下载与安装 本文以wi…

【Python学习笔记】6. Python3 基本数据类型(下)——列表、元组、集合、字典、数据类型转换

前言 本文介绍Python3基本数据类型——列表、元组、集合、字典、数据类型转换。 List&#xff08;列表&#xff09; List&#xff08;列表&#xff09; 是 Python 中使用最频繁的数据类型。 列表可以完成大多数集合类的数据结构实现。列表中元素的类型可以不相同&#xff0…

MySQL存储结构

数据结构 数据结构可视化&#xff1a;https://www.cs.usfca.edu/~galles/visualization/ 树 二叉树缺点&#xff1a; 单边节点过多时无法提高效率 红黑树&#xff1a; 具有平衡功能的二叉树&#xff0c;解决了单边节点过多导致的效率无法提高的问题&#xff0c;缺点是平衡算法…

移动端 自适应布局方案

文章目录DPRrem布局实现机理优点缺点相关技术方案viewport 布局优点缺点相关技术方案媒体查询等比缩放原理DPR DPR 设备物理像素 / CSS像素 DPR 2 为例&#xff0c;把 4&#xff08;2x2&#xff09;个物理像素当一个 CSS 像素使用 rem布局 rem 就是相对于根元素 html 的…