eew_9XVJps 发表于 2024-12-3 09:00

【Follow me第二季第4期】在Arduino下使用SD卡录制声音

本帖最后由 eew_9XVJps 于 2024-12-3 09:02 编辑

<p align="left"><b>自定任务:</b>Arduino Nano RP2040 Connect板载的PDM麦克风实现录音功能</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 看到板载有麦克风为什么不试一下录制声音呢,因此想通过板载的PDM麦克风实现声音拾取,并将收集到的数据以WAV格式形式存储在SD卡中。SD卡通过SPI接口实现与主控板通讯,SPI引脚直接使用了默认引脚。</p>

<p> &nbsp;</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我使用的SD卡外置模块为5V供电,需要将主控板的VBUS焊盘连接上来进行供电,否则3V3无法启动。</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 流程顺序大体如下:</p>

<p> &nbsp;</p>

<p>目前程序还是有点问题不知道是出在哪里,录音的长度和设定长度一致,但是播放录制的程序明显速度变快了,哪位大佬有空帮我看看问题出在哪里了,程序如下:</p>

<pre>
<code>#include &lt;PDM.h&gt;
#include "wave.h"
#include &lt;SPI.h&gt;
#include "SdFat.h"
const int chipSelect = 10;

// default number of output channels
static const char channels = 1;

// default PCM output frequency
static const int frequency = 20000;
// Buffer to read samples into, each sample is 16-bits
short sampleBuffer;
const int record_time = 30;// second
const char filename[] = "/record.wav";
const int waveDataSize = record_time * 40000;
char partWavData;
// Number of audio samples read
volatile int samplesRead;

FsFile file;// 录音文件
SdFs sd;
void setup() {
Serial.begin(9600);

delay(2000);
if(!sd.begin(SdSpiConfig(chipSelect, DEDICATED_SPI, SD_SCK_MHZ(16))))//初始化SD
{
    Serial.println(F("sd init error"));
    return;
}
sd.remove(filename);
file = sd.open(filename, O_WRITE|O_CREAT);
if(!file)
{
    Serial.println("crate file error");
    return;
}
// Configure the data receive callback
auto header = CreateWaveHeader(1, 20000, 16);
header.riffSize = waveDataSize + 44 - 8;
header.dataSize = waveDataSize;
file.write(&amp;header,44);
PDM.onReceive(onPDMdata);

// Optionally set the gain
// Defaults to 20 on the BLE Sense and 24 on the Portenta Vision Shield
PDM.setGain(10);

// Initialize PDM with:
// - one channel (mono mode)
// - a 16 kHz sample rate for the Arduino Nano 33 BLE Sense
// - a 32 kHz or 64 kHz sample rate for the Arduino Portenta Vision Shield
if (!PDM.begin(channels, frequency)) {
    Serial.println("Failed to start PDM!");
    while (1);
}
else{
    Serial.println("start");
}
}
int count = waveDataSize/128;
void loop() {
// Wait for samples to be read
if(count==0){
    samplesRead=0;
    file.close();
    Serial.println("finish");
}
if (samplesRead) {
    file.write((const byte*)sampleBuffer, 128);
    count--;
    // Clear the read count
    samplesRead = 0;
}
// if (samplesRead) {
//   Serial.println(samplesRead);
//   samplesRead=0;
// }

}

/**
* Callback function to process the data from the PDM microphone.
* NOTE: This callback is executed as part of an ISR.
* Therefore using `Serial` to print messages inside this function isn't supported.
* */
void onPDMdata() {
// Query the number of available bytes
int bytesAvailable = PDM.available();

// Read into the sample buffer
PDM.read(sampleBuffer, bytesAvailable);//每次64样本

// 16-bit, 2 bytes per sample
samplesRead = bytesAvailable / 2;
}
</code></pre>

<p align="left">对应的WAVE文件内容</p>

<pre>
<code>#include "wave.h"

WAV_HEADER CreateWaveHeader(int numChannels,                  //声道数
                            unsigned int sampleRate,            //采样率
                            unsigned short bitsPerSample)       //采样位宽
{
WAV_HEADER header;
header.riffSize = 0;
header.numChannels = numChannels;
header.sampleRate = sampleRate;
header.bitsPerSample = bitsPerSample;
header.bytesPerSecond = sampleRate * numChannels * bitsPerSample /8 ;
header.blockAlign = numChannels * bitsPerSample/8;
header.dataSize = 0;
return header;
}</code></pre>

<p align="left">效果图如下,动态效果见视频:</p>

<p> &nbsp;d37d54d962efd3f80ff9f3471e1cf882</p>

yilonglucky 发表于 2024-12-3 17:28

<p>有更新了吗?换成14k就好了?</p>

<div style="position: fixed; opacity: 1; height: 300px; width: 100%; font-size: 25px; text-align: center; bottom: 200px; left: 0px; display: none; flex-direction: column; justify-content: center; z-index: 1661789940; top: calc(50% + 0px);">&nbsp;</div>

eew_9XVJps 发表于 2024-12-4 12:54

yilonglucky 发表于 2024-12-3 17:28
有更新了吗?换成14k就好了?

&nbsp;

<p>是的换成14000速率就好了,下面是新录制的视频5e77f76763898e5239c236209725ea1f。</p>

<p>就是没搞明白明明麦克风和WAVE文件里面设置的声道数和速度都一致为啥只有14000采样率才正常。</p>
页: [1]
查看完整版本: 【Follow me第二季第4期】在Arduino下使用SD卡录制声音