💡 划重点
- 项目定位:基于ESP32-S3与INMP441麦克风阵列的卧室睡眠呼吸声监测夜灯,通过FFT频谱分析识别呼吸节律,以WS2812灯带输出柔光渐变反馈。
- 核心能力:非接触式呼吸声采集、实时频谱分析、灯光情绪化响应、Wi-Fi数据上报。
- 目标成本:90元以内(不含运费)。
- 关键参数:I2S采样率16kHz、FFT点数512、灯带亮度可调、呼吸检测周期5秒滑动窗口。
- 适用场景:卧室夜灯、睡眠辅助、呼吸健康初筛、智能家居联动。
- 技术栈:Arduino框架、I2S音频、FFT(arduinoFFT库)、WS2812(FastLED库)、Wi-Fi(WiFiManager)、HTTP上报。
需求洞察
目标用户
- 关注睡眠质量的都市白领、有打鼾或疑似呼吸暂停症状的轻度用户、智能家居爱好者。
- 需要低成本、非侵入式呼吸监测,同时又希望卧室设备具备氛围灯功能的人群。
真实痛点
- 市售睡眠监测设备(如手环、脑电头带)多为穿戴式,佩戴不适且影响入睡。
- 高端非接触式呼吸监测雷达(如毫米波)价格动辄千元以上,无法普及。
- 已有的夜灯产品仅具备照明功能,缺乏数据感知和反馈能力,无法满足用户对“睡眠可视化”的好奇与需求。
为什么值得做
- 呼吸声是睡眠质量的重要指标(呼吸频率、节律、暂停事件),通过麦克风采集和FFT分析可以实现低成本的初步监测。
- 结合灯光渐变,能提供“可感知”的睡眠状态反馈,提升用户体验和粘性。
- 硬件成本低,方案具备科普性和DIY可复制性,适合作为创客项目和睡眠健康入门方案。
方案设计
感知层
- 使用INMP441 I2S数字麦克风,通过ESP32-S3的I2S外设连续采集环境音频数据。
- 采样率设定为16kHz,单声道,位深32bit(实际使用24bit有效数据)。
- 在固件层对音频数据进行高通滤波(截止频率约100Hz)以滤除低频干扰,保留呼吸气流声和轻微鼾声。
控制层
- ESP32-S3作为主控,运行Arduino框架。
- 每隔5秒对采集到的音频块(512样本)执行FFT变换,提取频谱特征。
- 根据频谱能量在特定频段(200Hz~800Hz)的分布,计算呼吸声能量包络,进而估算呼吸频率和节律稳定性。
- 若检测到呼吸暂停事件(能量包络连续10秒低于阈值),在日志中记录并上报。
执行层
- 通过GPIO 10驱动WS2812灯带(建议30灯/米,长度0.5米),实现柔光呼吸效果。
- 灯光亮度随呼吸节奏自动同步:吸气时渐亮,呼气时渐暗,形成“视觉呼吸”反馈。
- 支持手动调节色温和亮度(通过板载按键或手机APP接口预留)。
日志/联网层
- 使用WiFiManager自动连接Wi-Fi。
- 通过HTTP POST将每分钟的呼吸频率、节律稳定指数、暂停事件上报至本地MQTT broker或公共平台(可选)。
- 板载4MB Flash可存储最近7天的睡眠摘要日志(使用Preferences库)。
物料清单
| 编号 | 名称 | 数量 | 用途 | 估算单价(元) |
|---|---|---|---|---|
| 1 | ESP32-S3-DevKitC-1 | 1 | 主控芯片及开发板 | 45.0 |
| 2 | INMP441 I2S麦克风模块 | 1 | 音频采集 | 12.0 |
| 3 | WS2812灯带(30灯/米,0.5米) | 1 | 柔光呼吸反馈 | 15.0 |
| 4 | 5V 2A USB电源适配器 | 1 | 供电 | 8.0 |
| 5 | 杜邦线 / 跳线(若干) | 1 | 接线 | 3.0 |
| 6 | 亚克力灯罩(定制或手工制作) | 1 | 柔光扩散 | 5.0 |
| 7 | 33Ω电阻 | 1 | WS2812数据线保护 | 0.2 |
| 8 | 1000μF/10V电解电容 | 1 | 电源滤波 | 0.8 |
| 9 | 轻触按键 | 1 | 手动调节模式 | 0.5 |
| 合计 | — | — | — | 89.5 |
接线与结构
| ESP32-S3引脚 | 外设引脚 | 说明 |
|---|---|---|
| GPIO 4 (I2S SCK) → INMP441 SCK | 串行位时钟 | 原方案SCK=4,保持不变 |
| GPIO 5 (I2S SD) → INMP441 SD | 串行数据输出 | 原方案SD=5,保持不变 |
| GPIO 6 (I2S WS) → INMP441 WS | 声道选择 | 原方案WS=6,保持不变 |
| GPIO 10 → WS2812 DIN | 灯带数据输入 | 原方案WS2812=10,保持不变 |
| 3.3V → INMP441 VDD, GND → GND | 麦克风供电 | 麦克风工作电压3.3V |
| 5V → WS2812 VCC, GND → GND | 灯带供电 | 灯带需5V供电,注意共地 |
接线微调说明:原方案GPIO分配无需改动,但在灯带供电端增加1000μF电容可有效防止峰值电流导致复位。INMP441的LOW POWER模式引脚直接拉高至3.3V,以启用低功耗模式。
结构建议:
- 使用亚克力灯罩包裹灯带,形成漫反射柔光。
- 麦克风固定于灯罩底部,朝向床侧,距床头约50cm处最佳。
- 整体外壳采用3D打印或手工木制底座,避免硬质反光面。
核心代码
以下为Arduino框架下可编译的骨架代码(PlatformIO / Arduino IDE均可):
#include <Arduino.h>
#include <driver/i2s.h>
#include <FastLED.h>
#include <arduinoFFT.h>
#include <WiFiManager.h>
// 常量定义
#define I2S_WS 6
#define I2S_SCK 4
#define I2S_SD 5
#define LED_PIN 10
#define NUM_LEDS 15
#define SAMPLE_RATE 16000
#define FFT_SIZE 512
// 全局对象
arduinoFFT FFT = arduinoFFT();
CRGB leds[NUM_LEDS];
float real[FFT_SIZE];
float imag[FFT_SIZE];
volatile bool breathDetected = false;
float breathFreqEstimate = 0.2f; // Hz
// I2S初始化
void setupI2S() {
i2s_config_t i2sConfig = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = SAMPLE_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = I2S_COMM_FORMAT_I2S,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 8,
.dma_buf_len = 256,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0
};
i2s_pin_config_t pinConfig = {
.bck_io_num = I2S_SCK,
.ws_io_num = I2S_WS,
.data_out_num = -1,
.data_in_num = I2S_SD
};
i2s_driver_install(I2S_NUM_0, &i2sConfig;, 0, NULL);
i2s_set_pin(I2S_NUM_0, &pinConfig;);
}
// 采集音频数据
bool readAudioBlock(int32_t* buffer, int len) {
size_t bytesRead = 0;
i2s_read(I2S_NUM_0, buffer, len * 4, &bytesRead;, portMAX_DELAY);
return bytesRead == len * 4;
}
// FFT频谱分析
void analyzeFFT(int32_t* audioData) {
for (int i = 0; i < FFT_SIZE; i++) {
real[i] = (float)(audioData[i] >> 14) / 32768.0f;
imag[i] = 0.0f;
}
float peakFreq = FFT.MajorPeak(real, FFT_SIZE, SAMPLE_RATE);
// 限制在呼吸频段 0.1~0.8 Hz
if (peakFreq > 0.1f && peakFreq < 0.8f) {
breathFreqEstimate = peakFreq;
breathDetected = true;
} else {
breathDetected = false;
}
}
// 灯光渐变反馈
void updateLights() {
int breathPhase = (millis() % 5000) / 10; // 0~500 对应 5秒周期
uint8_t brightness = map(breathPhase, 0, 250, 30, 200);
// 吸气渐亮(前2.5秒),呼气渐暗(后2.5秒)
if (breathPhase > 250) brightness = map(breathPhase, 250, 500, 200, 30);
uint8_t hue = 160; // 浅蓝色调
FastLED.show();
}
// WiFi连接
void setupWiFi() {
WiFiManager wm;
bool res = wm.autoConnect("SleepLamp");
if (!res) {
// 无法连接时使用默认配置
}
}
void setup() {
FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
setupI2S();
setupWiFi();
Serial.begin(115200);
}
void loop() {
int32_t audioBuffer[FFT_SIZE];
if (readAudioBlock(audioBuffer, FFT_SIZE)) {
analyzeFFT(audioBuffer);
}
updateLights();
// 每6秒上报一次呼吸频率(简化)
static unsigned long lastReport = 0;
if (millis() - lastReport > 6000 && breathDetected) {
Serial.print("Breath Freq: ");
// TODO: HTTP POST 上报数据
lastReport = millis();
}
delay(10);
}
调试步骤
- I2S音频测试:先注释FFT和灯带逻辑,使用Serial Plotter查看实时音频波形,确认麦克风有信号且无明显直流偏置。
- FFT功能验证:播放已知频率音频(如手机App发出0.5Hz的脉冲音),验证peakFreq输出是否接近设定值。
- 呼吸检测校准:在安静卧室环境下,呼吸平稳时观察呼吸频率是否落在0.15~0.35Hz(即每分钟9~21次)范围内;若偏大,检查高通滤波参数或FFT窗口。
- 灯带同步测试:将呼吸频率估计值映射到灯光渐变速度,确认画面变化平滑、无闪烁。
- Wi-Fi上报测试:确认WiFiManager连接成功,使用手机热点验证上报数据是否可见。
- 整机联调:模拟仰卧与侧卧不同睡姿,验证麦克风角度调整后仍能有效捕捉呼吸声。
- 功耗与发热验证:连续运行24小时,检查ESP32-S3和灯带温度是否正常,确保不发生热降频。
设计图
睡眠呼吸声监测夜灯结构flow
1
感知输入
→
2
控制处理
→
3
执行反馈
→
4
数据上报