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卡插槽,不要插反。

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

技术规格

功能示意图

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引脚使用情况

使用教程

准备

播放


    /*!
     * @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);
        }
    }

SDCardInit():

init(AUDIO):

setHeadphonesVolume(50),setSpeakersVolume(0):

muteSpeakers(),muteHeadphones():

initPlayer():

playMusic("/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);
    }

SDCardInit():

init(AUDIO):

initRecorder():

record("/record.WAV"):

recorderControl(BEGIN),recorderControl(STOP):

拍照

将下列程序下载到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;
            }
       }
    }

SDCardInit():

init(CAMERA):

connectNet(SSID,PASSWORD):

setFramesize(QVGA):

iis.setPixformat(GRAYSCALE):

sendPhoto():

snapshot("/photo1.bmp"):

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

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

SD卡读写


    #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

尺寸图

Fig1:DFR0498尺寸图.png

常见问题

warning_yellow.png 注:

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

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

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

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

更多

DFshopping_car1.png DFRobot商城购买链接