96|1

16

帖子

1

TA的资源

一粒金砂(中级)

楼主
 

【Follow me第二季第4期】-任务4:选做任务一(非必做):通过RGB LED不同颜色、亮... [复制链接]

 

由于任务3是PDM麦克风相关任务,所以本次选择的可选任务是通过LED显示麦克风收到声音大小。

本次任务是在任务3 的基础上,结合任务1,对代码进行修改。

主要思路是对麦克风的取值进行存储,然后控制LED灯亮度。本次只用到红灯和绿灯。

观测到任务3中,麦克风采集的数据有两个问题;

1、麦克风采集到的声音波动非常大,不利于LED的控制,如下图(图片来自任务3的内容);

2、采集到的数值会出现负值。

所以需要对采集到的数值进行处理。

本次处理的方式是,先求绝对值,将负值变为正值,再进行滑动平均滤波。

 

 

全部带码如下:

#include "PDM.h"
#include "WiFiNINA.h"

#define Led1  LEDR
#define Led2  LEDG
#define Led3  LEDB

#define MAX_SIZE 10

int head = 0;
int tail = 0;
int count = 0;

int queue[MAX_SIZE];

static const char channels = 1;
static const int frequncy  = 24000;
short sampleBuffer[512];
volatile int samplesRead;

int LEDR_Value;
int LEDG_Value;

double MIC_Value;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

  pinMode(Led1, OUTPUT);
  pinMode(Led2, OUTPUT); 


  PDM.onReceive(onPDMdata);
  if(!PDM.begin(channels,frequncy))
  {
    Serial.println("Failed to start PDM!!!");
    while(1);


  }

}

void loop() {
  // put your main code here, to run repeatedly:

  if(samplesRead)
  {
    for(int i = 0; i < samplesRead; i++)
    {
      //Serial.println(sampleBuffer[i]);
      MIC_Value=get_sliding_average(sampleBuffer[i]);

      Serial.println(MIC_Value);

      LEDR_Value=map(MIC_Value, 1, 3000, 1, 255);
      LEDG_Value=map(MIC_Value, 1, 3000, 255, 1);

 //     analogWrite(Led1 ,LEDR_Value);
 //     analogWrite(Led2 ,LEDG_Value);

      analogWrite(Led2 ,LEDR_Value);
      analogWrite(Led1 ,LEDG_Value);


    }
    samplesRead=0;

  }
  delay(1);

}

void onPDMdata(){
  int bytesAvailable = PDM.available();
  PDM.read(sampleBuffer,bytesAvailable);
  samplesRead = bytesAvailable / 2;

}

void enqueue(int value) {
    if ((tail + 1) % MAX_SIZE == head) {
        // 队列已满,需要先移除一个元素
        head = (head + 1) % MAX_SIZE;
    }
    queue[tail] = value;
    tail = (tail + 1) % MAX_SIZE;
    count++;
}

int dequeue() {
    int value = queue[head];
    head = (head + 1) % MAX_SIZE;
    count--;
    return value;
}

double get_sliding_average(int new_value) {
    static int init = 1;
    if (init) {
        // 初始化添加MAX_SIZE-1个0,保证头尾指针不会相遇
        for (int i = 0; i < MAX_SIZE - 1; i++) {
            enqueue(0);
        }
        init = 0;
    }
 
    // 添加新的样本值
    enqueue(sqrt(new_value * new_value));
 
    // 计算滑动平均值
    double sum = 0;
    for (int i = 0; i < count; i++) {
        sum += queue[(head + i) % MAX_SIZE];
    }
    return sum / count;
}

滑动平均滤波函数中,直接对采集到的数值进行取绝对值;

 

在主程序中,通过映射,将数值转换为1-255,控制LEDR和LEDG;当声音小的时候,绿灯亮,声音大的时候,红灯亮。

 

下面看一下演示视频。

最新回复

下面看一下演示视频。 没有视频上传吧   详情 回复 发表于 2 小时前
点赞 关注
 
 

回复
举报

6785

帖子

0

TA的资源

五彩晶圆(高级)

沙发
 

下面看一下演示视频。

没有视频上传吧

 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

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

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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

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

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

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