本帖最后由 名动神界 于 2025-5-27 11:15 编辑  
 
测试时比较仓促,加之能力有限、经验不足,测试结果不具备普遍意义,这是一次简易的试用报告。相信dfrobot的产品质量都是过硬的,我没有把它的性能发挥出来。本案例中用到的所有头文件在此,下面不再重复 
			
			
			- #include <WiFi.h>
 - #include <WebServer.h>
 - #include <HTTPClient.h>
 - #include <ArduinoJson.h>
 - #include "ESP_I2S.h"
 - #include "esp_camera.h"
 - #include "FS.h"
 - #include "SD.h"
 - #include "SPI.h"
 
  复制代码 所有引脚的配置如下图: 
- // 摄像头引脚配置(ESP32-S3默认)
 - #define PWDN_GPIO_NUM -1
 - #define RESET_GPIO_NUM -1
 - #define XCLK_GPIO_NUM 5
 - #define Y9_GPIO_NUM 4
 - #define Y8_GPIO_NUM 6
 - #define Y7_GPIO_NUM 7
 - #define Y6_GPIO_NUM 14
 - #define Y5_GPIO_NUM 17
 - #define Y4_GPIO_NUM 21
 - #define Y3_GPIO_NUM 18
 - #define Y2_GPIO_NUM 16
 - #define VSYNC_GPIO_NUM 1
 - #define HREF_GPIO_NUM 2
 - #define PCLK_GPIO_NUM 15
 - #define SIOD_GPIO_NUM 8
 - #define SIOC_GPIO_NUM 9
 - 
 - // TF卡SPI引脚配置
 - #define SCK_PIN 12
 - #define MISO_PIN 13
 - #define MOSI_PIN 11
 - #define CS_PIN 10
 - // 麦克风引脚
 - #define MIC_DATA 39
 - #define MIC_CLK 38
 
  复制代码
  
- 第一步,是测试延时拍摄,因为板子不具备h264等编码器,录制mp4需占用80%以上的cpu且工作非常不稳定。
 
 
 - void setup() {
 -   Serial.begin(115200);
 - 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_sscb_sda = SIOD_GPIO_NUM;
 -   config.pin_sscb_scl = SIOC_GPIO_NUM;
 -   config.pin_pwdn = PWDN_GPIO_NUM;
 -   config.pin_reset = RESET_GPIO_NUM;
 -   config.xclk_freq_hz = 20000000;
 -   config.pixel_format = PIXFORMAT_JPEG;
 -   config.frame_size = FRAMESIZE_UXGA;
 -   config.jpeg_quality = 10;
 -   config.fb_count = 2;
 - esp_err_t err = esp_camera_init(&config);
 -   if (err != ESP_OK) {
 -     Serial.printf("Camera init failed: 0x%x", err);
 -     return;}
 -   SPI.begin(SCK_PIN, MISO_PIN, MOSI_PIN, CS_PIN);  //初始化sd卡
 -   if(!SD.begin(CS_PIN)){
 -     Serial.println("SD Card Mount Failed");
 -     return;}}
 - void loop() {
 -   // 捕获帧并保存
 -   camera_fb_t *fb = esp_camera_fb_get();  
 -   if(!fb) {
 -     Serial.println("Camera capture failed");
 -     return;}
 - String path = "/video_" + String(millis()) + ".jpg"; // 创建唯一文件名
 -   File file = SD.open(path.c_str(), FILE_WRITE);// 写入SD卡
 -   if(!file){
 -     Serial.println("Failed to open file");
 -   } else {
 -     file.write(fb->buf, fb->len);
 -     Serial.println("Saved: " + path);}
 -   file.close();
 -   esp_camera_fb_return(fb);
 - delay(100);} // 控制帧率
 
  复制代码
   
录了6000多张,不过由于昨晚角度没放好,一直录的是距离桌面2米高的屋顶,红外夜视效果就出不来了,官方公布的红外夜视距离是2米以内。后面的图片是选取的典型状态图,第一张是晚上10点,最后一张是早上7点过。 
  
(典型的延时拍摄截图) 
 
- 第二步是测试远程喊话,这个费了点时间,因为我本人硬件调试经验薄弱,有些瞎子摸象的窘态,不过最终还是成功地使用百度语音合成生成了声音。
 
 
  
- // 配置参数
 - #define BAIDU_TTS_URL "http://tsn.baidu.com/text2audio"
 - #define API_KEY "***"
 - #define SECRET_KEY "***"
 - #define SAMPLE_RATE 16000
 - 
 - I2SClass i2s;
 - WiFiClient client;
 - 
 - String getToken() {
 -   HTTPClient http;
 -   String url = "https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials";
 -   url += "&client_id=" + String(API_KEY);
 -   url += "&client_secret=" + String(SECRET_KEY);
 -   
 -   http.begin(url);
 -   int httpCode = http.GET();
 -   
 -   if(httpCode == HTTP_CODE_OK) {
 -     String payload = http.getString();
 -     int tokenStart = payload.indexOf("access_token") + 15;
 -     int tokenEnd = payload.indexOf(""", tokenStart);
 -     String accessToken = payload.substring(tokenStart, tokenEnd);
 -     return accessToken;
 -   }
 -   return "";
 - }
 - 
 - void playAudio(uint8_t* data, size_t len) {
 -   i2s.write(data, len);
 - }
 - 
 - void textToSpeech(String text) {
 -   String token = getToken();
 -   if(token == "") {
 -     Serial.println("Failed to get token");
 -     return;
 -   }
 - 
 -   HTTPClient http;
 -   String url = BAIDU_TTS_URL "?tex=" + text;
 -   url += "&tok=" + token;
 -   url += "&cuid=esp32_device_zzq";
 -   url += "&ctp=1";
 -   url += "&lan=zh";
 -   url += "&spd=5";
 -   url += "&pit=5";
 -   url += "&vol=5";
 -   url += "&per=0";
 -   url += "&aue=4"; // mp3格式
 - 
 -   http.begin(client, url);
 -   int httpCode = http.GET();
 -   
 -   if(httpCode == HTTP_CODE_OK) {
 -     WiFiClient* stream = http.getStreamPtr();
 -     uint8_t buffer[512];
 -     while(stream->available()) {
 -       size_t len = stream->readBytes(buffer, sizeof(buffer));
 -       playAudio(buffer, len);
 -     }
 -   }
 -   http.end();
 - }
 - 
 - void setup() {
 -   Serial.begin(115200);
 -   WiFi.begin("qzezsteam", "qzez@1953");
 -   while(WiFi.status() != WL_CONNECTED) delay(500);
 -   Serial.println(WiFi.localIP());
 -   i2s.setPins(45, 46, 42);
 -   if(!i2s.begin(I2S_MODE_STD, SAMPLE_RATE, I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO)) {
 -     Serial.println("I2S init failed");
 -   }
 - }
 - 
 - void loop() {
 -   if(Serial.available()) {
 -     String input = Serial.readStringUntil('\n');
 -     Serial.println(input);
 -     textToSpeech(input);
 -   }
 - }
 
  复制代码 主要的难点是把百度语音合成的音频流格式,也就是aue,和板子的播放命令(playmp3,playwav,playaudio)相匹配。本人水平有限,使用aue=3,也就是mp3格式,aue=36,也就是wav格式,都调试失败。最后我把aue设置了无压缩的pcm格式,这是一种没有文件头、原汗原味的声音流,通过i2s.write命令播放成功。 
 i2s.write- 功能:直接向I2S总线发送原始PCM音频数据流。
 - 数据要求:输入数据必须是未经压缩的PCM格式(如16位/32位量化、单/双声道)35。
 - 处理流程:需手动完成音频数据的解码、格式转换(如调整字节序、声道排列)和缓冲区管理57。
 - 典型应用:播放自定义音频流或需要低延迟控制的场景,如实时语音传输或音频合成
 - 第三步:测试web远程喊话,这个可以通过特殊手段把服务端html模板写入固件来实现,不过我还没学会。我是通过arduino ide中定义了html网页变量来做成功的。
 - void handleRoot() {
 -   String html = R"rawliteral(
 -   <!DOCTYPE html>
 -   <html>
 -   <head>
 -     <meta charset="UTF-8">
 -     <title>远程监控系统</title>
 -   </head>
 -   <body>
 -     <div>
 -       <div>
 -         <h2>远程喊话</h2>
 -         <form action="/speak" method="POST">
 -           <input type="text" name="text" placeholder="输入文字"><br>
 -           <select name="preset">
 -             <option value="">--选择预设短语--</option>
 -             <option value="坏人,请赶快离开!">警告短语</option>
 -             <option value="你有什么事么?">询问短语</option>
 -             <option value="你好我是实验室主人">欢迎短语</option>
 -           </select><br>
 -           <input type="submit" value="播放">
 -         </form>
 -       </div>
 -       <div>
 -   </body>
 -   </html>
 -   )rawliteral";
 -   server.send(200, "text/html; charset=utf-8", html);
 - }
 
  复制代码 第四步就是制作延时拍摄了,开始走了弯路,总想用板子向web发送更新命令,失败n次,换成web端向板子请求数据,最后终于成功了<h2>实时监控</h2> 
<img id='stream' src='/capture' onload='setTimeout(function(){ document.getElementById(\"stream\").src = \"/capture?\" + new Date().getTime(); }, 100);'> 
  
onload这个回调函数,可以让图片实时更新,更新的频是100毫秒,也就是每秒钟回传10张。- 最后就制作完成了,下面是视频演示
  
  
 
 
 
 |