当前位置: 首页 > article >正文

一个基于ESP32S3和INMP441麦克风实现音频强度控制RGB灯带律动的代码及效果展示

一个基于ESP32S3和INMP441麦克风实现音频强度控制RGB灯带律动的代码示例,使用Arduino语言:

硬件连接

  • INMP441 VCC → ESP32的3.3V
  • INMP441 GND → ESP32的GND
  • INMP441 SCK → ESP32的GPIO 17
  • INMP441 WS → ESP32的GPIO 18
  • INMP441 SD → ESP32的GPIO 16
  • RGB LED灯带 → ESP32的GPIO 2

代码示例

#include <Arduino.h>
#include <driver/i2s.h>
#include <Adafruit_NeoPixel.h>  // RGB灯带库

// 定义I2S引脚
#define I2S_WS 18
#define I2S_SD 16
#define I2S_SCK 17
#define I2S_LED_BCK I2S_SCK
#define I2S_LED_WS I2S_WS
#define I2S_LED_SD I2S_SD
#define I2S_PORT I2S_NUM_0
// 灯带定义
#define LED_PIN    2       // 灯带连接的GPIO引脚
#define LED_COUNT  30     // 灯带LED数量

Adafruit_NeoPixel pixels(LED_COUNT, LED_PIN, NEO_RGB + NEO_KHZ800);  // 初始化灯带

// I2S配置
const i2s_port_t i2s_port = I2S_PORT;  // 使用I2S端口0
#define I2S_SAMPLE_RATE (48000)        // 采样率
#define I2S_DMA_BUF_LEN (100)          // DMA缓冲区长度
#define I2S_DMA_BUF_CNT (16)           // DMA缓冲区计数

// 变量声明
int16_t audioBuffer[100];  // 音频缓冲区
uint32_t audioStrength = 0;  // 音频强度

// 初始化I2S
void initI2S() {
  i2s_config_t i2s_config = {
    .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
    .sample_rate = I2S_SAMPLE_RATE,
    .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
    .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
    .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S_MSB),
    .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
    .dma_buf_count = I2S_DMA_BUF_CNT,
    .dma_buf_len = I2S_DMA_BUF_LEN,
    .use_apll = false,
    .tx_desc_auto_clear = false,
    .fixed_mclk = 0
  };

  i2s_pin_config_t pin_config = {
    .bck_io_num = I2S_LED_BCK,
    .ws_io_num = I2S_LED_WS,
    .data_out_num = I2S_PIN_NO_CHANGE,
    .data_in_num = I2S_LED_SD
  };

  i2s_driver_install(i2s_port, &i2s_config, 0, NULL);
  i2s_set_pin(i2s_port, &pin_config);
  i2s_start(i2s_port);
}

// 获取音频强度
void getAudioStrength() {
  size_t bytes_read;
  i2s_read(i2s_port, (void*)&audioBuffer, 50 * sizeof(int16_t), &bytes_read, portMAX_DELAY);

  // 计算音频强度
  audioStrength = 0;
  for (size_t i = 0; i < 50; i++) {
    audioStrength += abs(audioBuffer[i]);
  }
  audioStrength /= 50;  // 取平均值
}

// 控制灯带根据音频强度律动
void controlPixels() {
  static uint32_t lastUpdate = 0;
  uint32_t currentMillis = millis();

  // 每100毫秒更新一次
  if (currentMillis - lastUpdate >= 1) {
    lastUpdate = currentMillis;

    getAudioStrength();  // 获取音频强度

    // 根据音频强度点亮灯带
    for (int i = 0; i < LED_COUNT; i++) {
      if (i < (audioStrength / 20)) {  // 根据音频强度调整点亮范围
        //pixels.setPixelColor(i, pixels.Color(255, 0, 0));  // 红色
        // 设置所有LED为彩虹色
        uint8_t r, g, b;
        // 计算当前LED在颜色轮盘中的位置
        int wheelPos = (i * 256 / pixels.numPixels()); // 获得0-255的值
        Wheel(wheelPos, r, g, b); // 转换为RGB值
        pixels.setPixelColor(i, pixels.Color(r, g, b)); // 设置颜色
      } else {
        pixels.setPixelColor(i, pixels.Color(0, 0, 0));  // 关闭
      }
    }
    pixels.show();  // 更新灯带
  }
}

// Wheel函数根据颜色轮盘的位置返回对应的颜色
void Wheel(byte pos, byte &r, byte &g, byte &b) {
    if (pos < 85) {
        r = 255 - pos * 3;
        g = pos * 3;
        b = 0;
    } else if (pos < 170) {
        pos -= 85;
        r = 0;
        g = 255 - pos * 3;
        b = pos * 3;
    } else {
        pos -= 170;
        r = pos * 3;
        g = 0;
        b = 255 - pos * 3;
    }
}

void setup() {
  Serial.begin(115200);
  pixels.begin();  // 初始化灯带
  initI2S();  // 初始化I2S
}

void loop() {
  controlPixels();  // 控制灯带律动
}

代码说明

  1. I2S初始化

    • 配置I2S以读取麦克风音频数据。
    • 采样率为48000Hz,16位深度,单声道。
  2. 音频强度计算

    • 使用麦克风采集的音频数据计算平均强度。
    • 通过绝对值平均法计算音频强度。
  3. 灯带控制

    • 根据音频强度动态调整点亮的LED数量。
    • 音频强度越高,点亮的LED越多。

可调参数

  • LED_COUNT:灯带的LED数量,根据实际硬件调整。
  • LED_PIN:灯带连接的GPIO引脚。
  • 音频强度映射公式(audioStrength / 50)可以根据实际情况调整,以达到最佳效果。

注意事项

  • 确保RGB灯带连接到ESP32的正确GPIO引脚,并供电充足。
  • 调试时可通过Serial.println(audioStrength)打印音频强度值,观察效果并调整参数。
  • 可以进一步优化音频强度计算和灯带控制,实现更复杂的律动效果。

实验结果:
视频效果
在这里插入图片描述


http://www.kler.cn/a/539313.html

相关文章:

  • 工业相机在工业生产制造过程中的视觉检测技术应用
  • 十二、Docker Compose 部署 SpringCloudAlibaba 微服务
  • springboot 事务管理
  • 并查集题目
  • 在CT107D单片机综合训练平台上,8个数码管分别单独依次显示0~9的值,然后所有数码管一起同时显示0~F的值,如此往复。
  • 2025.1.8(qt图形化界面之消息框)
  • 【Java基础】为什么不支持多重继承?方法重载和方法重写之间区别、Exception 和 Error 区别?
  • 【SQLite】设置本地时间戳默认值
  • 【PDF提取内容】如何批量提取PDF里面的文字内容,把内容到处表格或者批量给PDF文件改名,基于C++的实现方案和步骤
  • DeepSeek与Vue.js携手:打造高效分页组件之旅
  • 在CT107D单片机综合训练平台上,8个数码管分别单独依次显示0~9的值,然后所有数码管一起同时显示0~F的值,如此往复。
  • stm32编译过程剖析 MicroPython openmv运行逻辑分析 MicroPython和传统c语言编译的比较 头脑风暴
  • 本地部署DeepSeek-R1模型(新手保姆教程)
  • 树与二叉树的概念
  • Netty:高性能网络应用框架的深度解析
  • C++病毒
  • Chirpy3D:用于创意 3D 鸟类生成的连续部分潜在特征
  • Unity 基础编程
  • 334递增的三元子序列贪心算法(思路解析+源码)
  • feign Api接口中注解问题:not annotated with HTTP method type (ex. GET, POST)
  • 【系统设计】使用Spring Boot连接MySQL数据库
  • IT行业方向细分,如何做到专家水平——1.运维
  • MySQL时间类型相关总结(DATETIME, TIMESTAMP, DATE, TIME, YEAR)
  • CANoe工具使用技巧 --- 如何使用 “on ethernetPacket “事件处理程序
  • “深入浅出”系列之C++:(20)C++17
  • 四种垄断组织形式的简洁解释-AI