Arduino 合宙 ESP32 S3 + OV2640 实现低成本SD存储卡相机(ESP32连接SD模块引脚)

这篇具有很好参考价值的文章主要介绍了Arduino 合宙 ESP32 S3 + OV2640 实现低成本SD存储卡相机(ESP32连接SD模块引脚)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

合宙ESP32 S3 板载16M flash,8m psram和一个FPC相机接口,价格却不到30元,无疑比价格将近50元的第三方ESP32 S3和将近30的ESP32 Cam更具性价比。

但是虽然板载FPC,由于接口冲突,导致相机与psram不能同时开启,作为ESP32 Cam的替代品来看,还缺少了板载SD卡,而且作为一块发布不久的开发板,网上资料资料非常少,甚至连乐鑫的ESP32 S3开发板关于如何用Arduino配置连接SD卡模块的资料都很少。

但是经过多次试错终于发现了连接方法,Arduino ESP32中默认使用VSPI模式连接,而且官方示例中也没有怎么定义引脚,但是S3中用VSPI模式连接会报错,只能用HSPI连接

//SDCard
#include <SD.h>
#include <SPI.h>
 
SPIClass sdSPI(HSPI);    // 使用vspi模式会报错
#define SD_MISO     17
#define SD_MOSI     16
#define SD_SCLK     18
#define SD_CS       14

void SDCheck() {    // 测试SD卡连接
  uint8_t cardType = SD.cardType();
 
  if (cardType == CARD_NONE)
  {
    Serial.println("未连接存储卡");
    return;
  }
  else 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("挂载了未知存储卡");
  }
  Serial.printf("存储卡总大小是: %lluMB \n", SD.cardSize() / (1024 * 1024)); // "/ (1024 * 1024)"可以换成">> 20"
  Serial.printf("文件系统总大小是: %lluB \n", SD.totalBytes());
  Serial.printf("文件系统已用大小是: %lluB \n", SD.usedBytes());
}

void setup() {
  bool SDstart = false;
  Serial.begin(115200);
  sdSPI.begin(SD_SCLK, SD_MISO, SD_MOSI, SD_CS);
  if (!SD.begin(SD_CS, sdSPI))
  {
    Serial.println("存储卡挂载失败");
    return;
  }

  SDCheck();

 相机部分配置:

//Cam
#include "esp_camera.h"
#include "esp_timer.h"
#include "soc/soc.h"           // Disable brownour problems
#include "soc/rtc_cntl_reg.h"  // Disable brownour problems

//cam gpio
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 39
#define SIOD_GPIO_NUM 21
#define SIOC_GPIO_NUM 46

#define Y2_GPIO_NUM 34
#define Y3_GPIO_NUM 47
#define Y4_GPIO_NUM 48
#define Y5_GPIO_NUM 33
#define Y6_GPIO_NUM 35
#define Y7_GPIO_NUM 37
#define Y8_GPIO_NUM 38
#define Y9_GPIO_NUM 40

#define VSYNC_GPIO_NUM 42
#define HREF_GPIO_NUM 41
#define PCLK_GPIO_NUM 36

void setup() {    // 相机配置
  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_sccb_sda = SIOD_GPIO_NUM;
  config.pin_sccb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.frame_size = FRAMESIZE_SVGA;
  config.pixel_format = PIXFORMAT_JPEG;
  // config.grab_mode = CAMERA_GRAB_LATEST;
  config.grab_mode = config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
  config.fb_location = CAMERA_FB_IN_DRAM;
  config.jpeg_quality = 30;
  config.fb_count = 1;    // 没有psram建议写1

  // Camera init
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Camera init failed with error 0x%x", err);
    return;
  }
}

获取图片帧函数:

void getimg(){
  camera_fb_t *fb = NULL;
  fb = esp_camera_fb_get();

  // if (!fb)
  // {
  //   Serial.println("Camera capture failed");
  //   return;
  // }
  // else
  // {
  //   Serial.println("Camera Captured");
  // }

  String filePath = dirPath + "/" + String(count) + ".jpg";

  // Serial.println(filePath);

  File file = SD.open(filePath,FILE_WRITE);
  if(file){
    file.write(fb->buf,fb -> len);
  }
  file.close();
  count ++;
  esp_camera_fb_return(fb);
  fb = NULL;
}

SD卡中文件夹存储代码,合宙这块板貌似没有板载RTC,获取不了准确的时间,而且不连接WiFi,所以只能计数命名

void setup() {
  bool SDstart = false;
  Serial.begin(115200);
  sdSPI.begin(SD_SCLK, SD_MISO, SD_MOSI, SD_CS);
  if (!SD.begin(SD_CS, sdSPI))
  {
    Serial.println("存储卡挂载失败");
    return;
  }else{
    while (!SD.exists("/Camera")) {
      SD.mkdir("/Camera");
      SDstart = true;
      Serial.print(".");
    }
    if(!SPIFFS.begin()){
      Serial.println("mount SPIFFS failed!");
    }else {
      if(!SPIFFS.exists("/Statue")){
        SPIFFS.mkdir("/Statue");
        File file = SPIFFS.open("/Statue",FILE_WRITE);
        file.write(1);
        file.close();
      }
      File file = SPIFFS.open("/Statue",FILE_READ);
      if(file.read() == 1){
        file = SPIFFS.open("/Statue",FILE_WRITE);
        file.write(0);
        file.close();
        Serial.println("start");
      } else {
        file = SPIFFS.open("/Statue",FILE_WRITE);
        file.write(1);
        file.close();
        Serial.println("stop");
        while (1);
      }
      if(SDstart == true){
        file = SPIFFS.open("/count.txt",FILE_WRITE);
        file.println("1");
        file.close();
      }else{
        if(!SPIFFS.exists("/count.txt")){
          Serial.println("create file Success!");
          file = SPIFFS.open("/count.txt",FILE_WRITE);
          file.println((String)fileCount);
          Serial.println(fileCount);
          file.close();
        }else{
          Serial.println("file exist!");
          File file = SPIFFS.open("/count.txt",FILE_READ);
          fileCount = atoi(file.readStringUntil('\n').c_str());
          file.close();
          Serial.println(fileCount);
          file = SPIFFS.open("/count.txt",FILE_WRITE);
          file.println(String(++fileCount));
          file.close();
        }
      }
    }
    SPIFFS.end();
    dirPath = "/Camera/" + (String)fileCount;
    while (!SD.exists(dirPath.c_str())) {
      SD.mkdir(dirPath.c_str());
      Serial.print(".");
    }
  }

完整代码:文章来源地址https://www.toymoban.com/news/detail-766614.html

//SDCard
#include <SD.h>
#include <SPI.h>
//File
#include "SPIFFS.h"
//Cam
#include "esp_camera.h"
#include "esp_timer.h"
#include "soc/soc.h"           // Disable brownour problems
#include "soc/rtc_cntl_reg.h"  // Disable brownour problems

SPIClass sdSPI(HSPI);
#define SD_MISO     17
#define SD_MOSI     16
#define SD_SCLK     18
#define SD_CS       14

//cam gpio
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 39
#define SIOD_GPIO_NUM 21
#define SIOC_GPIO_NUM 46

#define Y2_GPIO_NUM 34
#define Y3_GPIO_NUM 47
#define Y4_GPIO_NUM 48
#define Y5_GPIO_NUM 33
#define Y6_GPIO_NUM 35
#define Y7_GPIO_NUM 37
#define Y8_GPIO_NUM 38
#define Y9_GPIO_NUM 40

#define VSYNC_GPIO_NUM 42
#define HREF_GPIO_NUM 41
#define PCLK_GPIO_NUM 36

String dirPath;
uint32_t count = 0;
uint16_t fileCount = 1;

void getimg(){
  camera_fb_t *fb = NULL;
  fb = esp_camera_fb_get();
  String filePath = dirPath + "/" + String(count) + ".jpg";
  // Serial.println(filePath);
  File file = SD.open(filePath,FILE_WRITE);
  if(file){
    file.write(fb->buf,fb -> len);
  }
  file.close();
  count ++;
  esp_camera_fb_return(fb);
  fb = NULL;
}

void setup() {
  bool SDstart = false;
  Serial.begin(115200);
  sdSPI.begin(SD_SCLK, SD_MISO, SD_MOSI, SD_CS);
  if (!SD.begin(SD_CS, sdSPI))
  {
    Serial.println("存储卡挂载失败");
    return;
  }else{
    while (!SD.exists("/Camera")) {
      SD.mkdir("/Camera");
      SDstart = true;
      Serial.print(".");
    }
    if(!SPIFFS.begin()){
      Serial.println("mount SPIFFS failed!");
    }else {
      if(!SPIFFS.exists("/Statue")){
        SPIFFS.mkdir("/Statue");
        File file = SPIFFS.open("/Statue",FILE_WRITE);
        file.write(1);
        file.close();
      }
      File file = SPIFFS.open("/Statue",FILE_READ);
      if(file.read() == 1){
        file = SPIFFS.open("/Statue",FILE_WRITE);
        file.write(0);
        file.close();
        Serial.println("start");
      } else {
        file = SPIFFS.open("/Statue",FILE_WRITE);
        file.write(1);
        file.close();
        Serial.println("stop");
        while (1);
      }
      if(SDstart == true){
        file = SPIFFS.open("/count.txt",FILE_WRITE);
        file.println("1");
        file.close();
      }else{
        if(!SPIFFS.exists("/count.txt")){
          Serial.println("create file Success!");
          file = SPIFFS.open("/count.txt",FILE_WRITE);
          file.println((String)fileCount);
          Serial.println(fileCount);
          file.close();
        }else{
          Serial.println("file exist!");
          File file = SPIFFS.open("/count.txt",FILE_READ);
          fileCount = atoi(file.readStringUntil('\n').c_str());
          file.close();
          Serial.println(fileCount);
          file = SPIFFS.open("/count.txt",FILE_WRITE);
          file.println(String(++fileCount));
          file.close();
        }
      }
    }
    SPIFFS.end();
    dirPath = "/Camera/" + (String)fileCount;
    while (!SD.exists(dirPath.c_str())) {
      SD.mkdir(dirPath.c_str());
      Serial.print(".");
    }
  }
  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_sccb_sda = SIOD_GPIO_NUM;
  config.pin_sccb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.frame_size = FRAMESIZE_SVGA;
  config.pixel_format = PIXFORMAT_JPEG; 
  config.grab_mode = config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
  config.fb_location = CAMERA_FB_IN_DRAM;
  config.jpeg_quality = 30;
  config.fb_count = 1;

  // Camera init
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Camera init failed with error 0x%x", err);
    return;
  }
}

void loop() {
  getimg();
  delay(100);
}

到了这里,关于Arduino 合宙 ESP32 S3 + OV2640 实现低成本SD存储卡相机(ESP32连接SD模块引脚)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 新上架的简约版合宙ESP32C3使用arduino开发的教程

    经过两个月的缺货下架后,9块9包邮的合宙ESP32C3又重新上架了,真香。这一批都是没有带串口芯片的简约版(9块9要啥自行车)。在下架前,简约版要使用2.0.0版本的ESP32开发板库才能下载,而2.0.0版本有一些丢失arduino自带库的诡异BUG,所以一直没法用于下载。现在由于发布了2

    2024年02月05日
    浏览(92)
  • Arduino利用USB接口直接为ESP32-S3下载和调试程序

    ESP32-S3使用Arduino编程时可以直接使用USB连接。不用使用USB-UART的芯片进行转换。非常方便。但有些软开关还是要注意。下面来说一下使用USB直接连接串口并下载程序及使用串口。 要在下载程序时使用USB,选择Upload Mode: UART0/Hardware CDC 还要注意,USB mode也要选择Hardware CDC and JTA

    2024年02月11日
    浏览(137)
  • 【研究开源机器臂】(3):低成本实现200多元实现,开源机械臂,使用Wemos D1 R32 ESP32 +Arduino CNC,可以控制机械臂往复运动了,有视频介绍和演示说明

    文章分类: https://blog.csdn.net/freewebsys/category_5782941.html 前面讨论了相关的技术调研。 或者这样的: 第一次折腾,价格便宜就行。 https://detail.1688.com/offer/656424665619.html v3 雕刻机扩展板+ A4988套件 21 元: https://detail.1688.com/offer/710743362308.html http://www.taichi-maker.com/homepage/reference-in

    2024年02月03日
    浏览(47)
  • [022] [STM32] 使用DCMI(DVP)驱动OV2640

    OV2640为CMOS类型数字图像传感器,支持输出最大为200万像素(1600*1200分辨率)的图像,支持使用 VGA 时序输出图像数据,输出图像的数据格式支持YUV(422/420)、YCbCr422、RGB565以及JPEG格式,若直接输出JPEG格式的图像时可大大减少数据量。 可进行 图像补偿 :支持伽玛曲线、白平衡、

    2024年02月06日
    浏览(61)
  • STM32连接OV2640摄像头串口方式在PyQt5界面上展示视频界面 以及使用MQTT方式进行展示

    STM32连接OV2640 视频源接入到PyQt5界面中 作为AI模型的输入,视频流是非常重要的。在本文中,我们将介绍如何将STM32连接到OV2640摄像头,并将视频流接入到PyQt5界面中。 硬件连接 首先,我们需要将OV2640摄像头连接到STM32上。我们可以使用以下连接方式: OV2640 | STM32 ------|------

    2024年02月06日
    浏览(60)
  • STM32+ov7725+ESP8266实现无线图传-完成上位机图像显示

    stm32f407探索者开发板和STM32F103ZET6战舰开发板。接正点原子ov5640、OV7725、OV2640摄像头,通过esp8266Wi-Fi模块(透传模式)将摄像头采集到的rgb565格式图片通过tcp/ip协议上传到上位机显示。 【1】使用QT开发上位机,建立TCP服务器,接收ESP8266发送过来的图像数据显示。 【2】编写S

    2024年02月08日
    浏览(88)
  • 基于OV2640/ OV5640 的图像采集显示系统

    基于OV2640/ OV5640 的图像采集显示系统系列文章目录: (1)基于 OV5640 摄像头理论知识讲解-成像和采样原理 (2)基于 OV5640 摄像头理论知识讲解-数字接口和控制接口 (3)基于 OV5640 摄像头理论知识讲解-典型工作模式配置 (4)基于OV2640/ OV5640 的图像采集显示系统 本节将在实

    2024年02月11日
    浏览(45)
  • ov2640子设备视频操作详细分析

    这段代码定义了一个名为ov2640_subdev_video_ops的结构体变量,该变量是struct v4l2_subdev_video_ops类型的,用于配置与视频子设备相关的操作。 这个结构体包含了多个成员函数,每个函数都对应一个特定的操作: .s_stream: 用于开始流传输的函数,对应的函数名是ov2640_s_stream。 .g_mbus

    2024年02月13日
    浏览(38)
  • 【Arduino 时间函数】ESP32怎么实现微秒级延时,适用于ESP8266等

    如果基于 Arduino 开发 ESP32 ,则延时函数可以直接使用 Arduino 提供的时间函数。 Arduino提供四种不同的时间操作函数。 delay() 函数 delayMicroseconds() 函数 一毫秒内有一千微秒,一秒内有一百万微秒。 millis() 函数 此函数用于返回Arduino板开始运行当前程序时的毫秒数。 micros() 函数

    2024年02月13日
    浏览(47)
  • 使用 ESP32 Arduino 和机器学习实现WIFI室内定位

      在这个 Arduino 机器学习项目中,我们将使用附近的 WiFi 接入点来定位我们所在的位置。为了使该项目正常运行,您需要一块配备 WiFi 的板,例如 ESP8266、ESP32 或 MKR WiFI 1010。 什么是室内定位? 我们都习惯了 GPS 定位,我们的设备将使用卫星来跟踪我们在地球上的位置。GPS 工

    2024年02月14日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包