这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【Let'sdo第3期-拾色播放器DIY】成果贴:ESP32-S3制作会“唱歌”

共2条 1/1 1 跳转至

【Let'sdo第3期-拾色播放器DIY】成果贴:ESP32-S3制作会“唱歌”的拾色播放器

助工
2025-12-14 23:57:24     打赏

一、项目简介

基于 ESP32-S3 的互动音频视觉项目。只需将磁铁靠近设备,系统即可通过 TCS3200 颜色传感器 读取物体颜色,并实现以下互动:

  • 板载 RGB LED(NeoPixel):同步显示识别到的颜色;

  • 蜂鸣器模块:演奏与该颜色对应的音符或旋律。

你可以用它为彩色积木、卡片、甚至水果“配乐”,是入门嵌入式交互的理想项目。

二、硬件清单


模块功能连接说明
ESP32-S3开发板主控制器-
TCS3200颜色传感器识别RGB颜色S0-S3、OUT接指定GPIO12.11.10.9.6
板载RGB LED(NeoPixel)显示识别到的颜色GPIO 33(固定)
DFRobot蜂鸣器模块播放音符SIGNAL → GPIO 13
Littelfuse接近传感器磁控开关(触发/停止)接任意GPIO(GPIO 5)

image.png



三、核心功能与代码整合

本项目代码集成了四大核心功能:

  1. 颜色识别(TCS3200)

  2. RGB视觉反馈(NeoPixel)

  3. 声音输出(蜂鸣器与音阶映射)

  4. 磁控开关(接近传感器)

主要逻辑流程:
  • 磁铁靠近接近传感器时,启动检测;

  • TCS3200 读取 R、G、B 三通道频率;

  • 判断主色,点亮对应颜色 LED;

  • 按颜色索引(0-7)从 C 大调音阶中选取频率,驱动蜂鸣器发声;

  • 磁铁离开后,停止发声并关闭 LED。

#include <Adafruit_NeoPixel.h>

// ===== 1. 引脚定义 =====
// TCS3200颜色传感器引脚
#define S0_PIN 12
#define S1_PIN 11
#define S2_PIN 10
#define S3_PIN 9
#define OUT_PIN 6

// 蜂鸣器引脚
#define SPEAKER_PIN 13

// 接近传感器引脚 
#define PROXIMITY_PIN 5

// 板载RGB LED (固定引脚)
#define RGB_PIN 33
#define NUMPIXELS 1

// ===== 2. 全局变量与对象初始化 =====
// 颜色传感器变量
volatile unsigned long pulseCount = 0;
unsigned long redFreq = 0, greenFreq = 0, blueFreq = 0;

// RGB LED对象
Adafruit_NeoPixel pixels(NUMPIXELS, RGB_PIN, NEO_GRB + NEO_KHZ800);

// 音阶频率定义 (C大调)
int musicalScale[] = {262, 294, 330, 349, 392, 440, 494, 523}; // C4到C5
const char* noteNames[] = {"C4", "D4", "E4", "F4", "G4", "A4", "B4", "C5"};

// ===== 3. 中断函数:用于计数颜色传感器输出的脉冲 =====
void IRAM_ATTR countPulse() {
  pulseCount++;
}

// ===== 4. 关键功能函数 =====
/**
 * 读取颜色传感器某一通道的频率值
 */
unsigned long readFrequency() {
  unsigned long count;
  noInterrupts(); // 进入临界区
  pulseCount = 0;
  interrupts();
  delay(100); // 采样100ms
  noInterrupts();
  count = pulseCount; // 获取脉冲数
  interrupts();
  return count;
}

/**
 * 识别颜色并更新RGB LED
 * @return 返回识别到的颜色索引 (0-7对应音阶)
 */
int detectColorAndShow() {
  // 读取红色分量
  digitalWrite(S2_PIN, LOW);
  digitalWrite(S3_PIN, LOW);
  redFreq = readFrequency();
  
  // 读取绿色分量
  digitalWrite(S2_PIN, HIGH);
  digitalWrite(S3_PIN, HIGH);
  greenFreq = readFrequency();
  
  // 读取蓝色分量
  digitalWrite(S2_PIN, LOW);
  digitalWrite(S3_PIN, HIGH);
  blueFreq = readFrequency();
  
  // 简单判断主色并显示
  int colorIndex = 7; // 默认其他颜色,对应最高音
  if (redFreq > greenFreq && redFreq > blueFreq) {
    pixels.setPixelColor(0, pixels.Color(255, 0, 0)); // 红色
    colorIndex = 0; // 可映射为低音
    Serial.println("识别: 红色");
  } else if (greenFreq > redFreq && greenFreq > blueFreq) {
    pixels.setPixelColor(0, pixels.Color(0, 255, 0)); // 绿色
    colorIndex = 2;
    Serial.println("识别: 绿色");
  } else if (blueFreq > redFreq && blueFreq > greenFreq) {
    pixels.setPixelColor(0, pixels.Color(0, 0, 255)); // 蓝色
    colorIndex = 4;
    Serial.println("识别: 蓝色");
  } else {
    pixels.setPixelColor(0, pixels.Color(255, 255, 255)); // 白色
    Serial.println("识别: 其他/白色");
  }
  pixels.show(); // 更新LED显示
  return colorIndex;
}

/**
 * 播放与颜色对应的音符
 */
void playCorrespondingNote(int colorIndex) {
  // 确保索引在音阶范围内
  int noteIndex = colorIndex % 8;
  Serial.print("播放音符: ");
  Serial.println(noteNames[noteIndex]);
  
  tone(SPEAKER_PIN, musicalScale[noteIndex], 500); // 播放500ms
  delay(600); // 留一点间隔
}

// ===== 5. Arduino标准 setup() 和 loop() =====
void setup() {
  Serial.begin(115200);
  
  // 初始化颜色传感器
  pinMode(S0_PIN, OUTPUT);
  pinMode(S1_PIN, OUTPUT);
  pinMode(S2_PIN, OUTPUT);
  pinMode(S3_PIN, OUTPUT);
  digitalWrite(S0_PIN, HIGH);
  digitalWrite(S1_PIN, LOW); // 设置频率缩放为20%
  pinMode(OUT_PIN, INPUT);
  attachInterrupt(digitalPinToInterrupt(OUT_PIN), countPulse, FALLING);
  
  // 初始化RGB LED
  pixels.begin();
  pixels.setBrightness(30); // 设置适中亮度
  
  // 初始化蜂鸣器引脚
  pinMode(SPEAKER_PIN, OUTPUT);
  
  // 初始化接近传感器引脚
  pinMode(PROXIMITY_PIN, INPUT_PULLUP); // 假设传感器常态断开
  
  Serial.println("拾色播放器就绪!");
  Serial.println("将磁铁靠近接近传感器以开始/停止播放...");
}

void loop() {
  // 检测接近传感器状态(磁铁是否靠近)
  bool isMagnetNear = (digitalRead(PROXIMITY_PIN) == LOW); // 根据实际接线调整逻辑
  
  if (isMagnetNear) {
    Serial.println("--- 检测到磁铁,开始工作 ---");
    // 1. 识别颜色
    int detectedColorIndex = detectColorAndShow();
    // 2. 播放对应音符
    playCorrespondingNote(detectedColorIndex);
    delay(1000); // 循环间隔
  } else {
    // 磁铁远离时,可以停止声音或进入低功耗模式
    noTone(SPEAKER_PIN); // 停止发声
    pixels.clear();      // 关闭RGB LED
    pixels.show();
    delay(200); // 检测间隔
  }
}
 

四、注意事项 & 调试建议

  1. TCS3200 校准:不同光照环境下,颜色频率基准会变化。建议先打印 redFreq, greenFreq, blueFreq 到串口,根据实际情况调整判断阈值。

  2. 传感器干扰:TCS3200 对光源敏感,建议在稳定光源下测试,避免阴影或反光影响识别。

  3. 蜂鸣器类型:本项目需使用无源蜂鸣器(可通过频率发声)。如使用有源蜂鸣器,只能发出固定音调,需更改驱动方式。

  4. 接近传感器逻辑:根据实际模块常开/常闭特性,可能需要调整 digitalRead(PROXIMITY_PIN) 的判断逻辑(示例假定磁铁靠近时为低电平)。

  5. 扩展建议

    • 可将颜色映射为一段旋律,而非单音;

    • 加入 Wi-Fi,将识别颜色上传服务器或手机;

    • 用舵机制作“颜色转盘”,自动转到对应颜色位置。


五、实际效果

实测时,用红、绿、蓝三色卡片分别触发了 C4、E4、G4 三个音符,LED 同步显示颜色,效果直观。磁控开关的加入让操作更有“仪式感”,仿佛启动一个音乐盒。

IMG_8744.JPG

image.png

本项目涵盖了 GPIO 控制、外部中断、脉冲计数、PWM 发声、NeoPixel 驱动 等多个基础知识点,非常适合作为 ESP32-S3 的综合练习。


视频请查收~

【【Let'sdo第3期-拾色播放器DIY】成果贴:ESP32-S3制作会“唱歌”的拾色播放器】 https://www.bilibili.com/video/BV1PzqWBvE8M/?share_source=copy_web&vd_source=0c8eb7b44ac841939fb3482cf31385a9





关键词: 拾色     播放器     成果    

菜鸟
2025-12-15 09:06:29     打赏
2楼

顶,你最准时了


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]