这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【Let'sdo第3期-拾色播放器DIY】过程贴2:颜色传感器驱动以及按键获取

共2条 1/1 1 跳转至

【Let'sdo第3期-拾色播放器DIY】过程贴2:颜色传感器驱动以及按键获取

助工
2025-12-14 17:17:55     打赏

基础任务一:

实现颜色传感器驱动,按键获取当前颜色数据并可以通过串口或屏幕进行打印;

这个任务我们拆解一下就是我们要学习:

开发板按键使用与TCS3200颜色识别


板载按键功能与使用说明

在第20-22页有专门介绍D1、D2和D0按钮的章节。板子上有三个用户按钮:D0、D1和D2。

D0按钮
  • 具有双重功能:既可作为BOOT按钮进入ROM引导加载程序,也可在代码中作为输入使用。

  • 在CircuitPython中,可通过 board.D0、board.BOOT0 和 board.BUTTON 访问;在Arduino中为引脚0。

  • 默认为上拉高电平,按下时信号变低。进入ROM引导加载程序时,需要同时按住D0和Reset按钮。

image.png

D1和D2按钮
  • 作为普通输入使用。

  • 默认下拉低电平,按下时信号变高。检测时需判断信号是否变高。

image.png

注意事项

  • D1/D2与D0在代码检测方式上有区别,因逻辑电平不同,需采用不同的检测代码。

image.png



硬件引脚映射与配置

在Arduino IDE中使用时,按键对应的数字引脚编号如下:

按键板子标注Arduino引脚编号内部电路类型
D0BOOT0/BUTTONGPIO0内部上拉电阻
D1D1GPIO1内部下拉电阻
D2D2GPIO2内部下拉电阻
  • 基本按键检测程序:

    • D0:按下为低电平

    • D1/D2:按下为高电平


//按键检测程序
#include <Arduino.h>

// 定义按键引脚
const int buttonD0 = 0; // BOOT键
const int buttonD1 = 1; // 注意:这两个“高电平有效”
const int buttonD2 = 2;

void setup() {
  Serial.begin(115200);
  while (!Serial) delay(10); // 等待串口连接
  Serial.println("\n 按键测试开始...");
  
  // 关键配置:必须与硬件匹配
  pinMode(buttonD0, INPUT_PULLUP);   // D0 按下 = 低电平
  pinMode(buttonD1, INPUT_PULLDOWN); // D1 按下 = 高电平
  pinMode(buttonD2, INPUT_PULLDOWN); // D2 按下 = 高电平
  
  Serial.println("配置完成: D0(上拉), D1/D2(下拉)");
  Serial.println("按下按键,观察串口输出...\n");
}

void loop() {
  // 读取三个引脚的状态
  int stateD0 = digitalRead(buttonD0);
  int stateD1 = digitalRead(buttonD1);
  int stateD2 = digitalRead(buttonD2);
  
  // 根据配置,判断按键是否被按下
  bool d0Pressed = (stateD0 == LOW);  // D0低电平表示按下
  bool d1Pressed = (stateD1 == HIGH); // D1高电平表示按下
  bool d2Pressed = (stateD2 == HIGH); // D2高电平表示按下
  
  // 如果有任意按键被按下,则输出信息
  if (d0Pressed || d1Pressed || d2Pressed) {
    Serial.print("检测到按下: ");
    
    if (d0Pressed) Serial.print("D0 ");
    if (d1Pressed) Serial.print("D1 ");
    if (d2Pressed) Serial.print("D2 ");
    
    Serial.println(); // 换行
    
    // 简单的防抖:等待按键释放
    delay(200);
  }
  
  delay(10); // 短延时,减少CPU占用
}


image.pngimage.pngimage.png



常见问题:按键无响应

可能原因:
  • 上拉/下拉配置错误

  • 引脚模式未正确设置


TCS3200颜色传感器:

什么是Color Sensor?

ColorSensor是一块静态识别物体颜色,不同颜色输出不同频率,采用TCS3200D,所有IO口均引出。TCS3200D是TAOS(TexasAdvancedOptoelectronicSolutions)公司推出的可编程彩色光到频率的转换器。它把可配置的硅光电二极管与电流频率转换器集成在一个单一的CMOS电路上,同时在单一芯片上还集成了红绿蓝(RGB)三种滤光器,是业界第一个有数字兼容接口的RGB彩色传感器。TCS3200D的输出信号是数字量,可以驱动标准的TTL或CMOS逻辑输入,因此可直接与微处理器或其它逻辑电路相连接。由于输出的是数字量,并且能够实现每个彩色信道10位以上的转换精度,因而不再需要A/D转换电路,使电路变得更简单。

性能描述

1.输出频率的占空比选择S0-S1。

2.颜色滤镜选择:S2~S3。

3.频率输出端口OUT。

4.频率输出使能引脚OE(低电平有效),模块已经置低,使用时可以悬空。

5.支持LED灯补光控制。

6.工作电压2.7-5.5V。

功能框图:

image.png

TCS3200核心内容总结为:

  • 工作原理TCS3200通过四色滤光片阵列,将光强转换为频率信号输出。

  • 控制逻辑

    • S0/S1:输出频率比例选择

    • S2/S3:滤光片类型选择

    • OE:输出使能(低电平有效)

  • 颜色识别流程需白平衡校准,依次读取R/G/B通道频率,通过比较或映射识别颜色。


image.png

  • // 引脚定义
    int s0 = 12, s1 = 11, s2 = 10, s3 = 9;
    int outPin = 6;
    
    // 频率测量变量
    volatile unsigned long pulseCount = 0;
    unsigned long redFrequency = 0, greenFrequency = 0, blueFrequency = 0;
    
    // 中断函数
    void IRAM_ATTR countPulse() {
      pulseCount++;
    }
    
    unsigned long readFrequency() {
      unsigned long count;
      noInterrupts(); // 禁用中断
      count = pulseCount;
      pulseCount = 0;
      interrupts(); // 启用中断
      delay(100);   // 等待100ms
      noInterrupts();
      count = pulseCount; // 获取100ms内的脉冲数
      pulseCount = 0;
      interrupts();
      return count;
    }
    
    void setup() {
      Serial.begin(115200);
      
      pinMode(s0, OUTPUT);
      pinMode(s1, OUTPUT);
      pinMode(s2, OUTPUT);
      pinMode(s3, OUTPUT);
      
      digitalWrite(s0, HIGH);
      digitalWrite(s1, LOW);
      
      pinMode(outPin, INPUT);
      attachInterrupt(digitalPinToInterrupt(outPin), countPulse, FALLING);
      
      Serial.println("TCS3200颜色传感器");
    }
    
    void loop() {
      // 读取红色
      digitalWrite(s2, LOW);
      digitalWrite(s3, LOW);
      delay(10); // 等待滤波器稳定
      redFrequency = readFrequency();
      
      // 读取绿色
      digitalWrite(s2, HIGH);
      digitalWrite(s3, HIGH);
      delay(10);
      greenFrequency = readFrequency();
      
      // 读取蓝色
      digitalWrite(s2, LOW);
      digitalWrite(s3, HIGH);
      delay(10);
      blueFrequency = readFrequency();
      
      // 简单的颜色判断
      if (redFrequency > greenFrequency && redFrequency > blueFrequency) {
        Serial.println("红色");
      } else if (greenFrequency > redFrequency && greenFrequency > blueFrequency) {
        Serial.println("绿色");
      } else if (blueFrequency > redFrequency && blueFrequency > greenFrequency) {
        Serial.println("蓝色");
      } else {
        Serial.println("其他颜色");
      }
      
      delay(1000);
    }

下面就是将按键程序和颜色传感器融合起来:基于TCS3200的颜色识别系统:硬件与软件实现


项目背景与目标

本项目旨在实现基于TCS3200颜色传感器颜色识别系统,通过按键触发检测,并将结果通过串口输出。适用于分拣、智能家居等场景。


硬件组件与连接

所需硬件

  • ESP32开发板(主控)

  • TCS3200颜色传感器模块

  • 按钮/开关(触发检测)

  • 杜邦线(连接各组件)

    image.png

引脚连接表

ESP32引脚TCS3200引脚功能说明
GPIO12S0输出频率比例控制
GPIO11S1输出频率比例控制
GPIO10S2滤波器选择控制
GPIO9S3滤波器选择控制
GPIO6OUT频率输出(接中断)
GPIO1-按键D1输入

软件实现详解

1. 按键检测模块

// 关键配置:必须与硬件匹配
pinMode(buttonD0, INPUT_PULLUP);   // D0 按下 = 低电平
pinMode(buttonD1, INPUT_PULLDOWN); // D1 按下 = 高电平
pinMode(buttonD2, INPUT_PULLDOWN); // D2 按下 = 高电平
提示
  • BOOT按钮(D0)为上拉设计,按下为低电平

  • D1/D2为下拉设计,按下为高电平

  • 检测代码需与硬件逻辑一致


2. 颜色传感器驱动核心频率测量机制

TCS3200输出方波频率表示颜色强度,采用中断计数实现:
volatile unsigned long pulseCount = 0;

// 中断服务函数
void IRAM_ATTR countPulse() {
  pulseCount++;
}

中断保护

操作共享变量时需临界区保护,确保数据一致性:

volatile unsigned long pulseCount = 0;

// 中断服务函数
void IRAM_ATTR countPulse() {
  pulseCount++;
}
经验教训
  • 添加中断保护后系统稳定性显著提升


3. 颜色读取流程

依次切换滤波器,读取不同颜色分量:

// 读取红色分量
digitalWrite(s2, LOW);
digitalWrite(s3, LOW);
redFrequency = readFrequency();

// 读取绿色分量
digitalWrite(s2, HIGH);
digitalWrite(s3, HIGH);
greenFrequency = readFrequency();

// 读取蓝色分量
digitalWrite(s2, LOW);
digitalWrite(s3, HIGH);
blueFrequency = readFrequency();



4. 优化后的 readFrequency 函数

unsigned long readFrequency() {
  unsigned long count;
  
  // 第一次保护:重置计数器
  noInterrupts();
  pulseCount = 0;
  interrupts();
  
  delay(100);  // 采集100ms的脉冲
  
  // 第二次保护:读取计数值
  noInterrupts();
  count = pulseCount;
  pulseCount = 0;  // 可选:为下次测量准备
  interrupts();
  
  return count;
}

5.完整代码:

#include <Arduino.h>

// 颜色传感器引脚定义
const int s0 = 12, s1 = 11, s2 = 10, s3 = 9;
const int outPin = 6;

// 按键引脚 - 只保留D1
const int buttonD1 = 1;  // 按下为高电平

// 频率测量变量
volatile unsigned long pulseCount = 0;
unsigned long redFrequency = 0, greenFrequency = 0, blueFrequency = 0;

// 中断函数
void IRAM_ATTR countPulse() {
  pulseCount++;
}

void setup() {
  Serial.begin(115200);
  
  // 颜色传感器初始化
  pinMode(s0, OUTPUT);
  pinMode(s1, OUTPUT);
  pinMode(s2, OUTPUT);
  pinMode(s3, OUTPUT);
  
  digitalWrite(s0, HIGH);
  digitalWrite(s1, LOW);
  
  pinMode(outPin, INPUT);
  attachInterrupt(digitalPinToInterrupt(outPin), countPulse, FALLING);
  
  // 按键初始化
  pinMode(buttonD1, INPUT_PULLDOWN);  // D1按下=高电平
  
  Serial.println("就绪: 按下D1读取颜色");
}

void readColor() {
  // 读取红色
  digitalWrite(s2, LOW);
  digitalWrite(s3, LOW);
  delay(10);
  
  noInterrupts();
  pulseCount = 0;
  interrupts();
  delay(100);
  
  noInterrupts();
  redFrequency = pulseCount;
  interrupts();
  
  // 读取绿色
  digitalWrite(s2, HIGH);
  digitalWrite(s3, HIGH);
  delay(10);
  
  noInterrupts();
  pulseCount = 0;
  interrupts();
  delay(100);
  
  noInterrupts();
  greenFrequency = pulseCount;
  interrupts();
  
  // 读取蓝色
  digitalWrite(s2, LOW);
  digitalWrite(s3, HIGH);
  delay(10);
  
  noInterrupts();
  pulseCount = 0;
  interrupts();
  delay(100);
  
  noInterrupts();
  blueFrequency = pulseCount;
  interrupts();
  
  // 显示频率值
  Serial.print("R:");
  Serial.print(redFrequency);
  Serial.print(" G:");
  Serial.print(greenFrequency);
  Serial.print(" B:");
  Serial.print(blueFrequency);
  Serial.print(" - ");
  
  // 颜色判断逻辑
  if (redFrequency > greenFrequency && redFrequency > blueFrequency) {
    Serial.println("红色");
  } else if (greenFrequency > redFrequency && greenFrequency > blueFrequency) {
    Serial.println("绿色");
  } else if (blueFrequency > redFrequency && blueFrequency > greenFrequency) {
    Serial.println("蓝色");
  } else {
    Serial.println("其他颜色");
  }
}

void loop() {
  // 检测D1按键
  if (digitalRead(buttonD1) == HIGH) {
    Serial.print("检测到按键D1,");
    readColor();
    delay(200);  // 防抖延时
  }
  
  delay(10);
}

此处我才用的是电脑屏幕上展示红绿蓝纯色图片,让ESP32+模块在按键按下时识别颜色。

串口输出:

系统运行时输出格式:



QQ20251214-215224.pngQQ20251214-215241.png72ee229e-1794-49d3-a854-1c76a6b33316.png




关键词: 拾色     播放器     过程     按键     TCS3200     颜色    

菜鸟
2025-12-15 09:43:20     打赏
2楼

看到你调试按键了,这个板子的按键上拉下拉,也让我困惑了一会。

python 可以通过 frequency 模块获取频率也可以试试


共2条 1/1 1 跳转至

回复

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