198|2

18

帖子

1

TA的资源

一粒金砂(中级)

楼主
 

【Follow me第二季第4期】任务四 RGB LED亮度显示PDM麦克风收到的声音大小 [复制链接]

  本帖最后由 Netseye 于 2024-12-6 16:11 编辑

要在 Arduino Nano RP2040 Connect 上通过 RGB LED 显示 PDM 麦克风 收到的声音大小,可以通过读取麦克风的音量数据,并根据音量调整 RGB LED 的颜色和亮度。

主要步骤:

  1. 读取 PDM 麦克风音频数据

  2. 计算音频信号的强度(音量)

  3. 调整 RGB LED 的颜色和亮度,根据音量大小显示不同的效果。

实现

计算声音的大小(音量或振幅)通常需要对采样数据进行处理。在数字音频处理中,声音的大小可以通过计算振幅的平均值最大值来近似表示。以下是几种常见的计算方法:

1. 峰值振幅法(Peak Amplitude)

计算采样数据中的最大或最小振幅,取绝对值的最大值。

int16_t getMaxAmplitude(short *buffer, int length) {
  int16_t maxAmplitude = 0;
  for (int i = 0; i < length; i++) {
    int16_t amplitude = abs(buffer[i]);
    if (amplitude > maxAmplitude) {
      maxAmplitude = amplitude;
    }
  }
  return maxAmplitude;  // 返回最大振幅
}
  • 优点:简单、直观。

  • 缺点:容易受短时间内的尖锐噪声影响。

2. 均方根法(RMSRoot Mean Square

RMS 是衡量声音能量的常用方法,它计算采样值的平方平均再开方,能更稳定地反映声音的大小。

float getRMSAmplitude(short *buffer, int length) {
  long sum = 0;
  for (int i = 0; i < length; i++) {
    sum += (long)buffer[i] * buffer[i];  // 计算平方和
  }
  float rms = sqrt(sum / (float)length);  // 计算平方平均值并开方
  return rms;
}
  • 优点:更稳定,能更准确地反映整体音量。

  • 缺点:计算稍微复杂一些。

3. 平均绝对振幅法(Mean Absolute Amplitude)

计算所有采样值的绝对值平均。

float getAverageAmplitude(short *buffer, int length) {
  long sum = 0;
  for (int i = 0; i < length; i++) {
    sum += abs(buffer[i]);  // 计算绝对值和
  }
  return sum / (float)length;  // 返回平均值
}
  • 优点:简单且能消除正负波形的抵消影响。

  • 缺点:没有 RMS 稳定,但比峰值法好。

 

能够更灵敏一些我们采用峰值振幅法(Peak Amplitude) 来计算音量

  您可以根据 音量 值的大小划分不同的等级。例如,设置 4 个等级:

  • 低音量音量 值在 0 到 300 范围内

  • 中低音量音量 值在 300 到 500 范围内

  • 中高音量音量 值在 500 到 3000 范围内

  • 高音量音量 值大于 3000

  1. 音量 值映射到 LED 亮度或颜色:

  根据音量等级,设置 LED 的颜色或亮度。例如:

  • 低音量:红色 LED 亮起

  • 中低音量:绿色 LED 亮起

  • 中高音量:蓝色 LED 亮起

  • 高音量:RGB 全亮

代码示例:

以下代码实现了通过 RGB LED 显示声音的强度,根据声音的大小变化调整 LED 的亮度和颜色。

#include <PDM.h>
#include <WiFiNINA.h>

// 默认输出通道数
static const char channels = 1;

// 默认 PCM 输出频率
static const int frequency = 20000;

// 用于读取样本的缓冲区,每个样本是 16 位
short sampleBuffer[512];

// 已读取的音频样本数量
volatile int samplesRead;

void setup() {
  Serial.begin(9600);  // 初始化串口通信
  while (!Serial);  // 等待串口连接

  pinMode(LEDR, OUTPUT);  // 设置红色 LED 引脚为输出
  pinMode(LEDG, OUTPUT);  // 设置绿色 LED 引脚为输出
  pinMode(LEDB, OUTPUT);  // 设置蓝色 LED 引脚为输出
  // 配置数据接收回调函数
  PDM.onReceive(onPDMdata);

  // 初始化 PDM 麦克风:
  // - 一个通道(单声道模式)
  // - 20 kHz 采样率
  if (!PDM.begin(channels, frequency)) {
    Serial.println("无法启动 PDM!");
    while (1);  // 启动失败时停止程序
  }
}

void loop() {
  // 等待读取样本
  if (samplesRead) {
    float rms = getMaxAmplitude(sampleBuffer, samplesRead);
    controlLEDs(rms);
    Serial.println(rms);
    // 清空已读取的样本数量
    samplesRead = 0;
  }
}

void onPDMdata() {
  // 查询可用字节数
  int bytesAvailable = PDM.available();

  // 从 PDM 麦克风读取数据到样本缓冲区
  PDM.read(sampleBuffer, bytesAvailable);

  // 16 位样本,每个样本占 2 字节
  samplesRead = bytesAvailable / 2;
}

int16_t getMaxAmplitude(short *buffer, int length) {
  int16_t maxAmplitude = 0;
  for (int i = 0; i < length; i++) {
    int16_t amplitude = abs(buffer[i]);
    if (amplitude > maxAmplitude) {
      maxAmplitude = amplitude;
    }
  }
  return maxAmplitude;  // 返回最大振幅
}
void controlLEDs(float rms) {
  // 按 RMS 值进行分级
  if (rms < 300) {
    digitalWrite(LEDR, HIGH);
    digitalWrite(LEDG, LOW);
    digitalWrite(LEDB, LOW);
  } 
  else if (rms < 500) {
    digitalWrite(LEDR, LOW);
    digitalWrite(LEDG, HIGH);
    digitalWrite(LEDB, LOW);
  }
  else if (rms < 3000) {
    digitalWrite(LEDR, LOW);
    digitalWrite(LEDG, LOW);
    digitalWrite(LEDB, HIGH);
  } 
  else {
    digitalWrite(LEDR, HIGH);
    digitalWrite(LEDG, HIGH);
    digitalWrite(LEDB, HIGH);
  }
}

代码说明:

  1. 初始化 PDM 麦克风

    1. PDM.begin(1, 16000) 启动单声道,采样率为 16kHz。

    2. 设置回调函数 PDM.onReceive(onPDMdata) 处理采样数据。

  2. 计算最大振幅

    1. getMaxAmplitude() 函数计算采样数据中的最大振幅,反映音频信号的强度。

  3. RGB LED 控制

    1. setLEDColor() 函数将音量值映射到 LED 的亮度。map() 函数将音量值(0 到 255)映射到 RGB LED 的亮度值。

    2. 使用红色和绿色 LED 显示不同的颜色,蓝色 LED 不随音量变化。

  4. 音量和颜色映射

    1. 随着音量的增大,红色和绿色 LED 的亮度增亮,从而实现声音大小与 RGB LED 亮度和颜色的动态显示。

调试:

  1. 上传代码:将代码上传到 Arduino Nano RP2040 Connect 板子。

  2. 串口监视器:打开串口监视器查看音量数据。

  3. LED 反馈:观察 RGB LED 的颜色和亮度变化,根据麦克风拾取到的音频信号显示不同的颜色和亮度。

 

最新回复

调试的时候应该配个图说下哈   详情 回复 发表于 2024-12-7 10:55
点赞 关注
 
 

回复
举报

6694

帖子

0

TA的资源

五彩晶圆(高级)

沙发
 

调试的时候应该配个图说下哈

 
 
 

回复

18

帖子

1

TA的资源

一粒金砂(中级)

板凳
 

想着视频总结的时候发一下好了.

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表