FireBeetle 摄像头及音频扩展板

简介

DFRobot FireBeetle萤火虫系列是专为物联网设计的低功耗开发组件。此款FireBeetle Covers扩展板,集成NAU8822高品质IIS解码芯片、OV7725高清摄像头接口、SD(SDIO接口)插槽、以及耳机和话筒接口,还板载了一个小型咪头输入接口。NAU8822集成12@8Ω的BTL扬声器驱动,以及40mW@16Ω的耳机驱动接口,可以直接插接8Ω的扬声器和耳机。同时,NAU8822还支持DAC语音信号采集,集成可编程麦克风放大器,可以通过板载的咪头或者话筒接口,输入语音,并将文件保存在SD卡中,实现录音功能。其次,模块提供的OV7725接口,可以直接插接OV7725摄像头,实现简单拍照功能。FireBeetle Covers-Camera&Audio Media Board是定位在物联网的多媒体设备。搭配FireBeetle主板(如ESP32主控),可以做一款MP3、简易的录音笔、照相机,结合网络功能,可以DIY一个网络收音机,亦或是做一款云图像识别。

warning_yellow.png
注意:

本产品目前只支持FireBeetle-ESP32主板,其他主板由于没有IIS接口,目前还不支持

摄像头扁平线比较脆弱,连接时请小心,不要用力过猛。插入扩展板时注意方向,摄像头镜头背对SD卡插槽,不要插反。

当前暂不支持视频拍摄和传输

技术规格

  • VCC输入/输出电压范围:3.7V~5.5V
  • 3V3输入电压:3.3V
  • 1个用户按钮:使用数字口IO16检测
  • 1个复位按钮
  • SD卡:
    • 总线接口:SDIO协议
    • 默认传输速率:10MHZ
    • 最高传输速率:20MHZ
  • 摄像头OV7725:(参数仅供参考,由于ESP32性能有限,部分功能无法实现)
    • 感光阵列:640*480
    • 光学尺寸:1/6"
    • 视场角:25°
    • SCCB标准接口
    • 输出格式:Raw RGB,RGB(RGB4:2:2 ,RGB565/555/444),YCbCr(4:2:2)
    • 图像尺寸:VGA,QVGA,和从CIF到40×30的各种格式
    • VarioPixel 子采样方式
    • 自动图像控制功能:自动曝光控制、自动增益控制、自动白平衡、自动带式过滤器、和自动黑电平校准
    • 图像质量控制:颜色饱和度,色调,伽玛,清晰度,以及抗信号干扰
    • ISP包括降噪和缺陷校正
    • 镜头阴影校正
    • 饱和度自动调节
    • 帧同步能力
    • 固定焦距,不可调节
  • NAU8822:
    • DAC:94dB SNR , -84db THD
    • ADC:90dB SNR , -80dB THD
    • 集成BTL扬声器驱动:1W @ 8Ω
    • 集成耳机驱动:40mW @ 16Ω
    • 集成可编程麦克风放大器
    • 典型采样率:8KHz,48KHz,96KHz,192KHz
    • 标准音频接口:PCM和I2S
  • MIC:
    • 类型:驻极体电容
    • 输出类型:模拟
    • 方向:全向
    • 频率范围:100Hz ~ 15KHz
    • 灵敏度:-43dB ±5dB @ 94dB SPL
    • 信噪比:58dB

功能示意图

Fig2:DFR0498功能示意图.png

warning_yellow.png
注:NC不连接,VCC为电源电压输出(5V-USB供电时, 3.7V-锂电池供电时)

PinOut

Fig3:DFR0498 PinOut.png

ESP32引脚 SD卡引脚 NAU8822引脚 摄像头引脚
IO0 DACIN RST
IO1
IO2 DATA0
IO3
IO4 DATA1
IO5 BLCK D3
IO6
IO7
IO8
IO9
IO10
IO11
IO12 DATA2
IO13 DATA3
IO14 CLK
IO15 CMD
IO16
IO17 LRCK D2
IO18 D4
IO19 D5
IO21 XCLK
IO22 MCLK PCLK
IO23 HREF
IO25 VSYNC
IO26 SDIO SDA
IO27 SCLK SCL
IO34 D8
IO35 D9
IO36 D6
IO39 ADCOUT D7

ESP32引脚使用情况

使用教程

准备

播放

  • 将下列程序下载到ESP32控制板上,插入带有test1.wav和test2.wav文件的SD卡
  • 播放音乐示例

    /*!
     * @file DFRobot_IIS.h
     * @brief DFRobot's IIS Player Module
     * @n IIS Module for how to begin to play a WAV file,how to excute orders pause,continue,stop and play the next
     *    Insert sd card with test1.wav and test2.wav.
     *    Call the function by pressing user key to control music player
     *    The Module would operate as follows when pressed: play test1.wav>>pause>>continue>>mute>>Volume:50>>stop>>play test2.wav
     */

    #include <Wire.h>
    #include "DFRobot_IIS.h"

    DFRobot_IIS iis;
    const int buttonPin = 16;
    int i=0;

    void setup() {
      Serial.begin(115200);
      iis.SDCardInit();                                // Init SD card
      iis.init(AUDIO);                                 // Init Audio mode
      iis.setHeadphonesVolume(50);                     // Set Headphones Volume from 0 to 99
      iis.setSpeakersVolume(50);                       // Set Speakers   Volume from 0 to 99
      iis.initPlayer();                                // Init Music player
      Serial.println("Init player");
      iis.playMusic("/test1.WAV");                     // Choose music file
      Serial.println("Ready to play");
      delay(500);
    }

    void loop(){
        static unsigned long timepoint = millis();
        static byte count = 0;
        if(millis()-timepoint > 200){
            if((!digitalRead(buttonPin))&&(i==0||i==2)){
                timepoint = millis();
                iis.playerControl(PLAY);               // Start or continue playing Music
                Serial.println("play");
                i++;
            }else if((!digitalRead(buttonPin))&&i==1){
                timepoint = millis();
                iis.playerControl(PAUSE);              // Pause playing
                Serial.println("pause");
                i++;
            }else if((!digitalRead(buttonPin))&&i==3){
                timepoint = millis();
                iis.muteSpeakers();                    // Mute mode
                iis.muteHeadphones();
                Serial.println("mute mode");
                i++;
            }else if((!digitalRead(buttonPin))&&i==4){
                timepoint = millis();
                iis.setHeadphonesVolume(50);
                iis.setSpeakersVolume(50);
                Serial.println("Volume=50");
                i++;
            }else if((!digitalRead(buttonPin))&&i==5){
                timepoint = millis();
                iis.playerControl(STOP);               // Stop playing
                Serial.println("Stop");
                i++;
            }else if((!digitalRead(buttonPin))&&i==6){
                timepoint = millis();
                iis.playMusic("/test2.WAV");           // Change music file
                iis.playerControl(PLAY);               // Play test2.wav
                i=1;
            }
            delay(100);
        }
    }

  • 程序功能:程序下载完成后在按键时会依次做出以下操作:播放test1.wav>>暂停播放>>继续播放>>静音>>还原音量>>停止播放>>播放test2.wav
  • 函数功能:

SDCardInit():

  • 初始化SD卡,在最开始进行SD卡初始化。

init(AUDIO):

  • 进入AUDIO模式,在初始化SD卡后声明使用的模式(AUDIO CAMERA)。

setHeadphonesVolume(50),setSpeakersVolume(0):

  • 分别设置耳机与扬声器音量,二者可同时使用,音量从0至99。需在播放器初始化前设置,可在播放过程中使用更改音量。

muteSpeakers(),muteHeadphones():

  • 静音函数,分别使扬声器和耳机进入静音模式,可在播放过程中使用。

initPlayer():

  • 初始化播放器,AUDIO模式下使用播放器功能时调用。

playMusic("/test1.WAV"):

  • 选择SD卡中所播放的音乐文件(此处为SD卡中的test1.wav),调用后准备进行播放。

playerControl(PLAY),playerControl(PAUSE),playerControl(STOP):

  • 播放器控制函数,依次使播放器开始播放、暂停播放、停止播放。

录音

  • 若外接麦克风,板载麦克风将禁用

将下列程序下载到ESP32控制板上,插入SD卡


    /*!
     * @file DFRobot_IIS.h
     * @brief DFRobot's IIS Record Module
     * @n IIS Module for Record sound and Save WAV file in SD card
     *    Insert sd card
     *    Call the function by pressing user key to control recorder
     *    This Module will record sound and save it as record1.wav record2.wav by pressing user key
     */

    #include <Wire.h>
    #include <DFRobot_IIS.h>

    DFRobot_IIS iis;
    const int buttonPin = 16;
    enum Status{
        ePrepare,
        eRecording,
        eStop
    }eState=ePrepare;

    void setup(){
        Serial.begin(115200);
        iis.SDCardInit();                              // SD card init
        iis.init(AUDIO);                               // Init Audio mode
        iis.initRecorder();                            // Init recorder
        iis.record("/record1.WAV");                    // Enter file name to save recording
        Serial.println("Ready to record");
    }

    void loop(){
        if((!digitalRead(buttonPin))&&eState==ePrepare){
            while((!digitalRead(buttonPin))){
                delay(10);
            }
            iis.recorderControl(BEGIN);                // Begin recording
            Serial.println("Recording");
            eState=eRecording;
        }
        delay(100);
        if((!digitalRead(buttonPin))&&eState==eRecording){
            while((!digitalRead(buttonPin))){
                delay(10);
            }
            iis.recorderControl(STOP);                 // eStop recording
            Serial.println("Stop and save data");
            eState=eStop;
        }
        if((!digitalRead(buttonPin))&&eState==eStop){
            while((!digitalRead(buttonPin))){
                delay(10);
            }
            iis.record("/record2.WAV");                // Change file name
            eState=ePrepare;
        }
        delay(100);
    }

  • 程序功能:程序下载完成后按下按键开始录音,再次按键停止录音并将录音文件record1.wav保存到SD卡中,再次按下按键继续开始录音,按键停止录音并将录音文件record2.wav保存到SD卡中。
  • 函数功能:

SDCardInit():

  • 初始化SD卡,在最开始进行SD卡初始化。

init(AUDIO):

  • 进入AUDIO模式,在初始化SD卡后声明使用的模式(AUDIO CAMERA)。

initRecorder():

  • 初始化录音机,AUDIO模式下使用录音机功能时调用。

record("/record.WAV"):

  • 输入要存储在SD卡中的录音文件名(此处存为SD卡中的record.wav),调用后准备进行录音。

recorderControl(BEGIN),recorderControl(STOP):

  • 录音机控制函数,开始录音或停止录音并存储。

拍照

  • 目前只能拍摄最大分辨率为QVGA(320*240)的图片,还不支持VGA(640*480)的图片
  • 网络传输图片当前只支持GRAYSCALE灰度图,下个软件库版本支持彩色图
  • 固定焦距,客户不需要调节

将下列程序下载到ESP32控制板上,插入SD卡


    /*!
     * @file DFRobot_IIS.h
     * @brief DFRobot's IIS Camera Module
     * @n IIS Module for take photo and save BMP file in SD card
     *    Insert sd card
     *    Call the function by pressing user key to take photo
     *    This Module will take photo and save as photo1.bmp,photo2.bmp by pressing user key
     */

    #include <Wire.h>
    #include "DFRobot_IIS.h"

    DFRobot_IIS iis;
    const int buttonPin = 16;
    int i=0;
    const char* SSID    ="yourSSID";
    const char* PASSWORD="SSID password";
    void setup(){
        Serial.begin(115200);
        pinMode(buttonPin, INPUT);
        iis.SDCardInit();                                //SD card init
        iis.init(CAMERA);                                //Init Camera mode
        iis.connectNet(SSID,PASSWORD);                   //Connect wifi
        iis.setFramesize(QVGA);                          //Set photo size QVGA:320x240
        iis.setPixformat(GRAYSCALE);                     //Set pixelformat GRAYSCALE
        iis.sendPhoto();                                 //Send photo to net
        delay(100);
        Serial.println("Ready to take photo");
    }

    void loop(){
        static unsigned long timepoint = millis();
        static byte count = 0;
        if(millis()-timepoint > 20){
           timepoint = millis();
           if(!digitalRead(buttonPin)&& i == 0){
              Serial.println("take photo1");
              iis.snapshot("/photo1.bmp");               //Take photo and save it as photo1.bmp in SD card
              Serial.println("done");
              i=1;
            }
            if(!digitalRead(buttonPin)&& i == 1){
              Serial.println("take photo2");
              iis.snapshot("/photo2.bmp");               //Take photo and save it as photo1.bmp in SD card
              Serial.println("done");
              i=0;
            }
       }
    }

  • 程序功能:程序下载完成后按下按键拍照并将照片photo1.bmp保存到SD卡中,再次按下按键拍照并将照片photo2.bmp保存到SD卡中。此后的按键依然会拍照,并循环覆盖photo1.bmp和photo2.bmp保存到SD卡中。
  • 函数功能:

SDCardInit():

  • 初始化SD卡,在最开始进行SD卡初始化。

init(CAMERA):

  • 进入CAMERA模式,在初始化SD卡后声明使用的模式(AUDIO CAMERA)。

connectNet(SSID,PASSWORD):

  • 连接wifi,SSID为选择使用的wifi名称,PASSWORD为该wifi的密码

setFramesize(QVGA):

  • 设置照片大小规格,进入CAMERA模式后需调用,目前支持的照片尺寸为:QQVGA(160x120) QQVGA2(128x160) QICF(176x144) HQVGA(240x160) QVGA(320x240)。

iis.setPixformat(GRAYSCALE):

  • 设置照片像素格式,进入CAMERA模式后需调用,目前支持的像素格式为:RGB555(彩图),GRAYSCALE(灰度图)。

sendPhoto():

  • 传输摄像头数据至网络,连接wifi后可使用,配合提供的图像获取软件及下文提供的教程可实时查看摄像头的拍摄(暂支持灰度图)。

snapshot("/photo1.bmp"):

  • 拍照函数,输入要存储的照片文件名(此处存为SD卡中的photo1.bmp)。调用后进行拍照并存储照片。
  • 图像获取教程:

  - 运行Arduino程序,并打开串口查看IP

  - 输入IP地址(注意您的PC和ESP32必须在同一网段,才能通过网络查看到图像),点击start即可实时拍照

SD卡读写

  • FireBeetle Covers-Camera&Audio Media Board 的SD卡槽可直接使用Arduino 自带的ESP32 SDMMC库的函数
  • 插入SD卡,将下面程序下载到ESP32控制板中

    #include "FS.h"
    #include "SD_MMC.h"

    /*打印文件列表*/
    void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
        Serial.printf("Listing directory: %s\n", dirname);

        File root = fs.open(dirname);
        if(!root){
            Serial.println("Failed to open directory");
            return;
        }
        if(!root.isDirectory()){
            Serial.println("Not a directory");
            return;
        }

        File file = root.openNextFile();
        while(file){
            if(file.isDirectory()){
                Serial.print("  DIR : ");
                Serial.println(file.name());
                if(levels){
                    listDir(fs, file.name(), levels -1);
                }
            } else {
                Serial.print("  FILE: ");
                Serial.print(file.name());
                Serial.print("  SIZE: ");
                Serial.println(file.size());
            }
            file = root.openNextFile();
        }
    }

    /*创建目录*/
    void createDir(fs::FS &fs, const char * path){
        Serial.printf("Creating Dir: %s\n", path);
        if(fs.mkdir(path)){
            Serial.println("Dir created");
        } else {
            Serial.println("mkdir failed");
        }
    }

    /*删除目录*/
    void removeDir(fs::FS &fs, const char * path){
        Serial.printf("Removing Dir: %s\n", path);
        if(fs.rmdir(path)){
            Serial.println("Dir removed");
        } else {
            Serial.println("rmdir failed");
        }
    }

    /*读取文件*/
    void readFile(fs::FS &fs, const char * path){
        Serial.printf("Reading file: %s\n", path);

        File file = fs.open(path);
        if(!file){
            Serial.println("Failed to open file for reading");
            return;
        }

        Serial.print("Read from file: ");
        while(file.available()){
            Serial.write(file.read());
        }
    }

    /*写入文件*/
    void writeFile(fs::FS &fs, const char * path, const char * message){
        Serial.printf("Writing file: %s\n", path);

        File file = fs.open(path, FILE_WRITE);
        if(!file){
            Serial.println("Failed to open file for writing");
            return;
        }
        if(file.print(message)){
            Serial.println("File written");
        } else {
            Serial.println("Write failed");
        }
    }

    /*追加写入文件*/
    void appendFile(fs::FS &fs, const char * path, const char * message){
        Serial.printf("Appending to file: %s\n", path);

        File file = fs.open(path, FILE_APPEND);
        if(!file){
            Serial.println("Failed to open file for appending");
            return;
        }
        if(file.print(message)){
            Serial.println("Message appended");
        } else {
            Serial.println("Append failed");
        }
    }

    /*重命名文件*/
    void renameFile(fs::FS &fs, const char * path1, const char * path2){
        Serial.printf("Renaming file %s to %s\n", path1, path2);
        if (fs.rename(path1, path2)) {
            Serial.println("File renamed");
        } else {
            Serial.println("Rename failed");
        }
    }

    /*删除文件*/
    void deleteFile(fs::FS &fs, const char * path){
        Serial.printf("Deleting file: %s\n", path);
        if(fs.remove(path)){
            Serial.println("File deleted");
        } else {
            Serial.println("Delete failed");
        }
    }

    /*测试文件读写速度*/
    void testFileIO(fs::FS &fs, const char * path){
        File file = fs.open(path);
        static uint8_t buf[512];
        size_t len = 0;
        uint32_t start = millis();
        uint32_t end = start;
        if(file){
            len = file.size();
            size_t flen = len;
            start = millis();
            while(len){
                size_t toRead = len;
                if(toRead > 512){
                    toRead = 512;
                }
                file.read(buf, toRead);
                len -= toRead;
            }
            end = millis() - start;
            Serial.printf("%u bytes read for %u ms\n", flen, end);
            file.close();
        } else {
            Serial.println("Failed to open file for reading");
        }


        file = fs.open(path, FILE_WRITE);
        if(!file){
            Serial.println("Failed to open file for writing");
            return;
        }

        size_t i;
        start = millis();
        for(i=0; i<2048; i++){
            file.write(buf, 512);
        }
        end = millis() - start;
        Serial.printf("%u bytes written for %u ms\n", 2048 * 512, end);
        file.close();
    }

    void setup(){
        Serial.begin(115200);
        if(!SD_MMC.begin()){
            Serial.println("Card Mount Failed");
            return;
        }
        uint8_t cardType = SD_MMC.cardType();

        if(cardType == CARD_NONE){
            Serial.println("No SD_MMC card attached");
            return;
        }

        Serial.print("SD_MMC 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);
        Serial.printf("SD_MMC Card Size: %lluMB\n", cardSize);
        //打印文件列表
        listDir(SD_MMC, "/", 0);
        //在根目录下创建mydir文件夹
        createDir(SD_MMC, "/mydir");
        //打印文件列表,可以看到新建的mydir文件夹
        listDir(SD_MMC, "/", 0);
        //删除刚才创建的mydir目录
        removeDir(SD_MMC, "/mydir");
        //打印文件列表,可以看到mydir文件夹消失了
        listDir(SD_MMC, "/", 2);
        //创建hello.txt文件,向里边写入Hello
        writeFile(SD_MMC, "/hello.txt", "Hello ");
        //在hello.txt文件尾部追加World!\r
        appendFile(SD_MMC, "/hello.txt", "World!\n");
        //读取hello.txt文件,文件内容Hello World!会被打印到串口
        readFile(SD_MMC, "/hello.txt");
        //删除sd卡中原有的foo.txt文件
        deleteFile(SD_MMC, "/foo.txt");
        //将hello.txt重命名为foo.txt
        renameFile(SD_MMC, "/hello.txt", "/foo.txt");
        //读取foo.txt文件,文件内容Hello World!会被打印到串口
        readFile(SD_MMC, "/foo.txt");
        //测试这个SD卡中文件的读写速度
        testFileIO(SD_MMC, "/test.txt");
    }

    void loop(){

    }

  • 测试结果

兼容性测试

MCU 测试通过 不支持
FireBeetle-Board328P
FireBeetle-ESP32
FireBeetle-ESP8266

尺寸图

  • pin脚间距:2.54mm
  • 安装孔间距:24mm/53mm
  • 安装孔尺寸:3.1mm
  • 主板尺寸:29.00mm×58.00mm
  • 板厚:1.6mm

Fig1:DFR0498尺寸图.png

常见问题

warning_yellow.png
注:

由于目前仅ESP32支持IIS接口,故扩展板仅支持Firebe Board-ESP32主板

如果出现插上主板后,主板不能下载程序,请拔下该扩展板下载成功后再插上。

由于管脚资源有限,无法同时支持拍照与录音功能。

更多问题及有趣的应用,可以 访问论坛 进行查阅或发帖。

更多

DFshopping_car1.png DFRobot商城购买链接