基于Arduino与TCS3200的颜色识别系统:从原理到实践
1. 项目概述与核心思路
颜色识别,听起来像是机器视觉或者高端工业相机才玩得转的东西,但其实它的底层原理离我们并不遥远。简单来说,就是让机器“看见”并“理解”颜色。在自动化生产线分拣不同颜色的零件、智能家居根据环境光调节灯光色温,甚至是我们手机屏幕的自动亮度调节,背后都有颜色识别的影子。这个项目的核心价值,在于用最低的成本和最易懂的方式,亲手搭建一套能完成“感知-处理-输出”全流程的嵌入式系统,把抽象的信号处理和数据转换过程,变成看得见、摸得着的实物。
我这次搭建的系统,核心是 Arduino UNO 和 TCS3200颜色传感器 。Arduino负责“大脑”的运算和控制,而TCS3200则是系统的“眼睛”。整个工作流程非常直观:TCS3200传感器探测目标物体的反射光,将其分解为红、绿、蓝(RGB)三个通道的原始频率信号;Arduino读取这些频率值,通过一套校准和计算逻辑,将其转换为我们可以理解的RGB数值或颜色名称;最后,通过一个 I2C接口的LCD屏幕 将结果实时显示出来。我还额外增加了一个 按钮 ,用来手动触发单次测量,这样在观察特定颜色时结果会更稳定清晰,避免了连续刷屏带来的视觉干扰。
这个项目非常适合嵌入式入门者、电子爱好者,或者任何想了解传感器如何与微控制器“对话”的人。它不涉及复杂的图像处理算法,而是聚焦于最基础的信号采集、数模转换和串行通信,是理解现代智能硬件工作原理的一块绝佳敲门砖。
2. 核心器件选型与原理深析
一套系统能否稳定可靠地工作,器件选型是第一步,也是最关键的一步。这里的每一个选择,背后都有其明确的工程考量。
2.1 主控单元:为何是Arduino UNO?
在众多开发板中选择Arduino UNO,是基于以下几个硬核理由:
- 生态与社区支持 :Arduino拥有全球最庞大的开源硬件社区。几乎你遇到的任何问题,都能找到现成的库、代码示例和讨论帖。对于项目实践来说,这能极大降低开发门槛,把精力集中在核心逻辑而非底层驱动上。
- 接口与性能平衡 :UNO板载的ATmega328P微控制器,主频16MHz,内存2KB SRAM,32KB Flash。处理TCS3200输出的频率信号并驱动LCD显示,其性能绰绰有余。它提供了14路数字I/O口(其中6路可作PWM输出)和6路模拟输入口,完全满足本项目连接传感器、LCD和按钮的需求。
- 供电与稳定性 :UNO可通过USB或外部7-12V电源供电,并内置了5V和3.3V稳压电路,能为传感器和LCD模块提供干净、稳定的电源,这是系统稳定运行的基础。
注意 :虽然像ESP32这类功能更强的板子也能用,但对于初学者,UNO简单的架构和明确的引脚定义,更能帮助你理解“信号从哪来到哪去”,避免被Wi-Fi、蓝牙等额外功能分散注意力。
2.2 “电子眼”TCS3200:从光到频率的转换
TCS3200是本项目的灵魂器件,它的工作原理值得深入拆解。它并不是直接输出一个电压值来代表颜色,而是输出一个 频率信号 。
核心结构 :传感器表面集成了一个8x8的光电二极管阵列。这些二极管并非随意排列,而是被覆盖了四种滤镜:16个带红色滤镜、16个带绿色滤镜、16个带蓝色滤镜,另外16个是透明滤镜(用于测量光强)。这种结构允许它同时对RGB三原色分量进行采样。
工作流程 :
- 光电流产生 :当光线照射到二极管上,会产生与光强成正比的光电流。
- 电流-频率转换 :芯片内部集成了一个可编程的电流-频率转换器。这个转换器将输入的光电流转换成方波信号,其输出频率(F0)与输入光电流成正比。也就是说,光越强,输出的脉冲频率就越高。
- 频率输出与选择 :通过两个控制引脚S2和S3,我们可以选择让芯片输出哪种滤镜对应的频率信号。例如,设置
S2=LOW, S3=LOW时,选择红色滤波器阵列;S2=LOW, S3=HIGH选择蓝色;S2=HIGH, S3=LOW选择绿色;S2=HIGH, S3=HIGH选择透明(用于白光校准)。 - 输出频率缩放 :引脚S0和S1用于选择输出频率的缩放比例(100%, 20%, 2%)。这相当于一个“量程选择”开关。在光线很强、输出频率过高可能导致Arduino无法准确读取时,可以降低缩放比例,反之亦然。通常我们选择20%或2%以获得更稳定的读数。
为什么选择频率输出而不是模拟电压输出? 这是一个关键设计。模拟电压信号容易受到电源噪声、线路干扰和温度漂移的影响。而频率信号是一种数字化的表示方式,抗干扰能力更强。Arduino通过测量固定时间窗口内脉冲的个数(即频率),就能得到稳定的数值,这比读取一个容易波动的模拟电压值要可靠得多。
2.3 人机界面:I2C LCD与交互按钮
LCD1602 with I2C适配器 :标准的1602液晶屏需要连接7-10根线,会大量占用宝贵的I/O口。I2C适配板的核心是一个PCF8574或类似的I/O扩展芯片,它通过仅有的两根线(SDA数据线,SCL时钟线)与Arduino通信,将并行数据转换为串行传输。这节省了接线,也简化了代码(使用现成的 LiquidCrystal_I2C 库)。选择带背光的型号,在光线不足的环境下也能清晰阅读。
按钮与电阻 :按钮用于手动触发单次颜色测量。这里有一个重要细节:按钮一端接5V,另一端通过一个 10kΩ的上拉电阻 接到Arduino的输入引脚,同时该引脚直接连接按钮的另一端到地。当按钮未按下时,输入引脚通过上拉电阻稳定在 HIGH (5V);按下时,引脚直接接地,变为 LOW (0V)。这个10kΩ的上拉电阻至关重要,它确保了引脚在悬空(未连接)时有一个确定的高电平状态,防止因静电干扰产生误触发。如果使用Arduino内部上拉电阻(通过代码设置 pinMode(pin, INPUT_PULLUP) ),则可以省略这个外部电阻,但外部电阻方案更直观,抗干扰能力也略强。
3. 硬件系统搭建与电路连接实战
理论清晰后,动手搭建是下一步。正确的连接是系统工作的物理基础,这里我会详细到每一根线的走向和目的。
3.1 物料清单与工具准备
除了项目正文中提到的核心物料,为了顺利完成搭建,你还需要准备以下物品:
- 面包板及跳线 :用于原型搭建和测试,建议使用公-公杜邦线。
- USB数据线 (A to B型):为Arduino UNO供电和上传程序。
- 一个纯白色的校准板 :可以是白色瓷砖、白色亚克力板或一张白纸。这是后续软件校准的基准。
- 万用表(可选但推荐) :用于检查电源和通断,排查硬件问题。
- 一个能放置传感器和被测物体的暗箱或遮光罩(强烈推荐) :环境光的变化是颜色识别最大的干扰源。一个简单的纸盒或3D打印的罩子,能极大提升测量的稳定性和重复性。
3.2 分步电路连接详解
请务必在断电状态下进行所有连接。我们可以将连接分为三个部分:电源与地、传感器、LCD与按钮。
第一部分:建立公共的电源和地
- 将Arduino UNO的
5V引脚连接到面包板的 正极电源轨 。 - 将Arduino UNO的
GND引脚连接到面包板的 负极地线轨 。
实操心得 :养成习惯,先搭建好电源和地线“骨架”。这能确保所有器件都有正确的参考电位,避免后续接线混乱。
第二部分:连接TCS3200颜色传感器 TCS3200模块通常有8个引脚(有些模块可能标号不同,但功能一致):
S0-> Arduino D4S1-> Arduino D5 (S0和S1共同决定输出频率分频)S2-> Arduino D6S3-> Arduino D7 (S2和S3共同选择滤波器类型)OUT-> Arduino D8 (这是频率信号输出线,是关键数据线)VCC-> 面包板 5V 电源轨GND-> 面包板 GND 地线轨OE(Output Enable, 输出使能,如果有的话) -> 接GND(使其一直有效)
第三部分:连接I2C LCD显示屏 I2C模块通常只有4个引脚:
VCC-> 面包板 5V 电源轨GND-> 面包板 GND 地线轨SDA-> Arduino A4 (在UNO上,A4引脚同时兼任I2C的SDA功能)SCL-> Arduino A5 (在UNO上,A5引脚同时兼任I2C的SCL功能)
第四部分:连接触发按钮
- 按钮的一个引脚连接到面包板 5V 电源轨。
- 按钮的同一个引脚,通过一个 10kΩ的金属膜电阻 ,连接到Arduino的 D2 引脚。这个电阻就是上拉电阻。
- 按钮的另一个引脚连接到面包板 GND 地线轨。
- (可选但推荐)在D2引脚和GND之间再并联一个约0.1uF的瓷片电容,可以进一步滤除按钮抖动产生的毛刺。
连接完成后,你的系统拓扑应该是:Arduino作为中心处理器,通过数字引脚控制并读取TCS3200,通过I2C总线与LCD通信,并通过另一个数字引脚监听按钮状态。所有器件共享同一个5V电源和GND。
4. 软件逻辑剖析与代码实现
硬件是躯体,软件是灵魂。这里的代码不仅要让系统跑起来,更要理解其每一步背后的数学和逻辑。
4.1 库文件引入与引脚定义
首先,我们需要包含驱动LCD的库,并定义所有用到的引脚。
#include <Wire.h> // Arduino内置的I2C通信库
#include <LiquidCrystal_I2C.h> // 控制I2C LCD的库
// 初始化LCD对象:地址通常是0x27或0x3F,16列2行
LiquidCrystal_I2C lcd(0x27, 16, 2);
// TCS3200引脚定义
#define S0 4
#define S1 5
#define S2 6
#define S3 7
#define sensorOut 8
// 按钮引脚定义
#define buttonPin 2
// 用于存储RGB频率值的变量
int redFrequency = 0;
int greenFrequency = 0;
int blueFrequency = 0;
int whiteFrequency = 0; // 用于校准的“白平衡”参考值
// 校准因子(初始为1.0,校准后更新)
float redCalibrate = 1.0;
float greenCalibrate = 1.0;
float blueCalibrate = 1.0;
// 按钮状态及防抖变量
int buttonState = HIGH;
int lastButtonState = HIGH;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50; // 防抖延时50毫秒
bool measureTriggered = false;
关键点解释 :
LiquidCrystal_I2C库需要单独安装。在Arduino IDE中,通过“项目” -> “加载库” -> “管理库”,搜索“LiquidCrystal I2C”并安装。I2C地址可能需要根据你的模块调整,0x27和0x3F是最常见的。
4.2 初始化设置(setup函数)
在 setup() 函数中,我们需要配置所有引脚的模式,初始化传感器和LCD,并进行关键的白平衡校准。
void setup() {
Serial.begin(9600); // 开启串口调试,便于观察数据
// 配置TCS3200控制引脚为输出模式
pinMode(S0, OUTPUT);
pinMode(S1, OUTPUT);
pinMode(S2, OUTPUT);
pinMode(S3, OUTPUT);
// 配置传感器输出引脚为输入模式
pinMode(sensorOut, INPUT);
// 配置按钮引脚为输入模式,并使用内部上拉电阻(如果未接外部上拉电阻)
// pinMode(buttonPin, INPUT_PULLUP);
// 如果接了外部上拉电阻,则使用:
pinMode(buttonPin, INPUT);
// 设置TCS3200输出频率缩放为20%(S0=HIGH, S1=LOW)
// 这个比例在大多数室内光线下比较合适
digitalWrite(S0, HIGH);
digitalWrite(S1, LOW);
// 初始化LCD,点亮背光
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Color Sensor");
lcd.setCursor(0, 1);
lcd.print("Press to Measure");
// 执行白平衡校准(非常重要!)
performCalibration();
delay(1000);
lcd.clear();
}
白平衡校准函数 performCalibration() 详解 : 这是保证颜色识别准确度的核心步骤。TCS3200每个颜色通道的原始响应并不一致,且受环境光影响。校准的目的是找到一个参考点。
void performCalibration() {
lcd.clear();
lcd.print("Calibrating...");
lcd.setCursor(0, 1);
lcd.print("Put White Ref.");
delay(3000); // 给用户时间放置白色参考物
// 读取在白色参考物下的RGB原始频率值
whiteFrequency = getRawFrequency(LOW, LOW); // 读透明滤镜值作为总光强参考(可选)
redFrequency = getRawFrequency(LOW, LOW); // 读红色通道值
greenFrequency = getRawFrequency(HIGH, HIGH); // 读绿色通道值
blueFrequency = getRawFrequency(LOW, HIGH); // 读蓝色通道值
// 计算校准因子:目标是让在白色下,RGB三通道的值“相等”或达到一个标准比例。
// 这里采用一种简单方法:让最强的通道为基准(因子为1.0),其他通道按比例放大。
// 注意:频率值与光强成反比(光越强,频率越高),但我们要的是“响应强度”,所以用倒数关系。
float ref = (redFrequency + greenFrequency + blueFrequency) / 3.0; // 取平均值作为参考
redCalibrate = ref / redFrequency;
greenCalibrate = ref / greenFrequency;
blueCalibrate = ref / blueFrequency;
// 通过串口输出校准因子,方便调试
Serial.print("Calibration Factors - R: ");
Serial.print(redCalibrate);
Serial.print(" G: ");
Serial.print(greenCalibrate);
Serial.print(" B: ");
Serial.println(blueCalibrate);
lcd.clear();
lcd.print("Calibration OK!");
delay(1000);
}
核心原理 :假设在理想白光下,RGB三色的反射强度应该相等。但传感器本身和光源都有偏差。我们测量白板下的原始值,计算出三个修正系数(
redCalibrate,greenCalibrate,blueCalibrate)。后续测量任何颜色时,都将原始读数乘以对应的系数,从而抵消硬件和环境光造成的系统误差。
4.3 主循环与核心测量函数
loop() 函数主要负责检测按钮动作,并在被触发时执行一次完整的颜色测量与显示流程。
void loop() {
// 1. 读取按钮状态并进行防抖处理
int reading = digitalRead(buttonPin);
if (reading != lastButtonState) {
lastDebounceTime = millis(); // 重置防抖计时器
}
if ((millis() - lastDebounceTime) > debounceDelay) {
// 防抖时间过后,状态稳定
if (reading != buttonState) {
buttonState = reading;
if (buttonState == LOW) { // 按钮被按下(假设低电平有效)
measureTriggered = true;
}
}
}
lastButtonState = reading;
// 2. 如果测量被触发
if (measureTriggered) {
measureTriggered = false; // 重置触发标志
performMeasurement(); // 执行测量和显示
}
}
核心测量函数 performMeasurement() :
void performMeasurement() {
// 获取校准后的RGB频率值(已转换为“强度”概念,数值越大表示该颜色分量越强)
int redVal = getCalibratedFrequency(LOW, LOW, redCalibrate); // 红色分量
int greenVal = getCalibratedFrequency(HIGH, HIGH, greenCalibrate); // 绿色分量
int blueVal = getCalibratedFrequency(LOW, HIGH, blueCalibrate); // 蓝色分量
// 将频率强度映射到0-255的RGB标准范围(可选,更直观)
// 首先找到本次测量中RGB的最大值
int maxVal = max(redVal, max(greenVal, blueVal));
int mappedR = map(redVal, 0, maxVal, 0, 255);
int mappedG = map(greenVal, 0, maxVal, 0, 255);
int mappedB = map(blueVal, 0, maxVal, 0, 255);
// 在LCD上显示结果
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("R:");
lcd.print(mappedR);
lcd.print(" G:");
lcd.print(mappedG);
lcd.print(" B:");
lcd.print(mappedB);
// 第二行显示识别出的颜色名称(简单的阈值判断)
lcd.setCursor(0, 1);
String colorName = getColorName(mappedR, mappedG, mappedB);
lcd.print(colorName);
// 同时通过串口输出,方便深度调试
Serial.print("Raw(R,G,B): ");
Serial.print(redVal); Serial.print(", ");
Serial.print(greenVal); Serial.print(", ");
Serial.println(blueVal);
Serial.print("Mapped(R,G,B): ");
Serial.print(mappedR); Serial.print(", ");
Serial.print(mappedG); Serial.print(", ");
Serial.println(mappedB);
Serial.print("Color: ");
Serial.println(colorName);
}
底层频率读取函数 getRawFrequency 和 getCalibratedFrequency :
// 读取原始频率值
int getRawFrequency(int s2State, int s3State) {
digitalWrite(S2, s2State);
digitalWrite(S3, s3State);
delay(10); // 短暂延时,让传感器滤波器稳定
// 使用pulseIn函数测量脉冲宽度,并转换为频率
// pulseIn测量高电平或低电平的持续时间,这里测量半个周期
int pulseWidth = pulseIn(sensorOut, LOW, 80000); // 超时80ms
if (pulseWidth == 0) { // 超时,可能光线太弱或传感器故障
return 0;
}
int frequency = 1000000 / (2 * pulseWidth); // 计算频率 (Hz)
return frequency;
}
// 获取校准后的“强度”值(原始频率的倒数乘以校准因子)
int getCalibratedFrequency(int s2State, int s3State, float calFactor) {
int freq = getRawFrequency(s2State, s3State);
if (freq == 0) return 0;
// 频率越高,光强越强。为了得到“强度”值,我们取频率的倒数,并应用校准。
// 为避免浮点运算,可以先乘后除。
int intensity = (int)((100000.0 / freq) * calFactor); // 放大倍数便于整数处理
return intensity;
}
简单的颜色判断函数 getColorName : 这是一个非常基础的阈值判断法,适用于区分几种纯色。对于复杂的颜色,需要更复杂的算法(如HSV颜色空间判断)。
String getColorName(int r, int g, int b) {
// 判断黑色/白色/灰色
if (r < 30 && g < 30 && b < 30) return "Black";
if (r > 200 && g > 200 && b > 200) return "White";
if (abs(r-g) < 30 && abs(g-b) < 30 && abs(r-b) < 30) return "Gray";
// 判断彩色,使用分量差值法
if (r > g && r > b) {
if (r - g > 50 && r - b > 50) return "Red";
else if (g > b) return "Yellow";
else return "Pink";
} else if (g > r && g > b) {
if (g - r > 50 && g - b > 50) return "Green";
else return "Cyan";
} else if (b > r && b > g) {
if (b - r > 50 && b - g > 50) return "Blue";
else return "Purple";
}
return "Mixed";
}
5. 系统校准、调试与性能优化
代码上传后,系统能跑起来只是第一步。要想获得准确可靠的结果,精细的校准和调试必不可少。
5.1 校准流程实战与技巧
校准是颜色识别的“定盘星”。不校准的系统就像一把没归零的尺子,测量毫无意义。
- 环境准备 :将传感器和白色校准板放入 遮光罩 内。确保光源固定且均匀。理想情况是使用标准D65光源,但一个亮度足够的白色LED台灯也能满足入门需求。关键是要保证每次测量时光照条件一致。
- 执行校准 :上传包含
performCalibration()函数的代码。打开Arduino IDE的串口监视器(波特率9600)。按照LCD提示,将白色校准板正对传感器,距离约1-2厘米,然后保持静止。 - 记录与分析 :校准完成后,串口会打印出三个校准因子。观察它们:
- 如果某个因子远大于1(比如>1.5),说明该通道原始响应 偏弱 ,需要被放大。
- 如果某个因子远小于1(比如<0.7),说明该通道原始响应 过强 ,需要被抑制。
- 理想情况下,三个因子都接近1。如果某个因子异常(如>3或<0.3),检查传感器滤镜是否有脏污,或光源是否严重偏色。
- 固化校准值 :将计算出的
redCalibrate,greenCalibrate,blueCalibrate三个值,直接写入代码中setup()函数开头的变量初始化处,并注释掉setup()里调用performCalibration()的那一行。这样以后上电就不需要每次都执行校准了,除非光照环境发生重大改变。
高级技巧:多点校准 。对于要求更高的应用,可以采集多个标准色卡(如24色卡)的数据,建立一张“原始频率值-RGB真值”的查找表,或者用最小二乘法拟合出一个转换矩阵。这能大幅提升识别精度,尤其是对于中间色调。
5.2 常见问题排查指南
在调试过程中,你几乎一定会遇到下面这些问题。别担心,这是学习的一部分。
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| LCD不显示或乱码 | 1. I2C地址错误。 2. 接线错误或接触不良。 3. 背光未开启。 |
1. 使用I2C扫描程序确认模块地址。 2. 检查SDA、SCL、VCC、GND四根线是否接牢。 3. 在代码中确认执行了 lcd.backlight() 和 lcd.init() 。 |
| 串口读数全为0或异常大 | 1. TCS3200的OUT引脚未正确连接或接触不良。 2. S0-S3引脚设置错误,导致输出频率超出测量范围。 3. 传感器损坏或光源极弱。 |
1. 用万用表或示波器检查D8引脚是否有脉冲信号。 2. 确保S0=HIGH, S1=LOW(20%输出)。尝试改为S0=LOW, S1=LOW(100%输出)看读数是否变小。 3. 用手电筒照射传感器,看读数是否有变化。 |
| 识别颜色不稳定,数值跳动大 | 1. 环境光干扰 (最主要原因)。 2. 被测物体距离或角度变化。 3. 电源噪声。 |
1. 必须使用遮光罩! 这是提升稳定性的最有效手段。 2. 固定传感器与被测物的相对位置。可以考虑增加一个简单的机械结构。 3. 在Arduino的5V和GND之间并联一个100uF的电解电容,滤除电源波动。 |
| 校准后识别白色仍不准 | 1. 校准时光源不稳定或校准板不标准。 2. 传感器透镜有污渍。 3. 颜色判断阈值设置不合理。 |
1. 重新在稳定均匀光源下,用纯白亚光陶瓷片校准。 2. 用棉签蘸酒精轻轻清洁传感器窗口。 3. 通过串口监视器观察识别“白色”时的RGB值,调整 getColorName 函数中的阈值(如200改为220)。 |
| 按钮按下无反应或连发 | 1. 上拉电阻未接或接触不良。 2. 代码中防抖逻辑未生效或延时不当。 3. 引脚模式设置错误。 |
1. 确认10kΩ电阻一端接5V,一端接按钮和D2引脚。 2. 检查 debounceDelay 值,可尝试从50ms调整到100ms。 3. 确认使用 pinMode(buttonPin, INPUT) (外接上拉)或 INPUT_PULLUP (内接上拉)。 |
5.3 性能优化与扩展思路
当基础功能实现后,可以考虑以下方向让项目变得更“聪明”、更实用:
- 动态环境光补偿 :在传感器旁边增加一个普通的光敏电阻或环境光传感器,实时监测环境光强。在计算颜色时,将RGB读数除以环境光强读数,可以在一定程度上抵消环境光变化的影响。
- 切换至HSV颜色空间 :RGB对亮度非常敏感。将RGB转换为HSV(色相、饱和度、明度)后,主要根据 色相(Hue) 来判断颜色,这样即使物体明暗变化,只要颜色没变,识别结果就稳定。Arduino上有现成的RGB到HSV转换函数库。
- 增加学习模式 :通过按钮组合,让系统进入“学习”状态。当按下按钮时,将当前物体的RGB值存储到EEPROM中,并为其命名(如“我的水杯”)。之后识别时,通过计算与存储值的欧氏距离,找出最匹配的已学习颜色。这就实现了一个简单的可训练颜色分类器。
- 输出标准化与通信 :将处理后的RGB或颜色名称,通过串口发送给电脑(用于Python/Processing可视化),或通过蓝牙/Wi-Fi模块发送给手机,实现远程监控。
- 机械结构集成 :设计一个3D打印外壳,将传感器、Arduino、LCD和电池集成在一起,做成一个便携的“颜色识别笔”或固定的“分拣检测头”。
6. 项目总结与核心收获
走完从硬件连接到软件调试的完整流程,这个项目带给你的远不止一个能识别颜色的小装置。它是一次典型的嵌入式系统开发全流程演练: 需求分析 -> 器件选型 -> 电路设计 -> 编程实现 -> 校准调试 -> 优化扩展 。
最深刻的体会是, 校准和抗干扰设计在传感器应用中有多重要 。最初我在环境光下测试,数据跳得简直像在跳舞,一度怀疑传感器坏了。直到加上遮光罩,数据立刻变得温顺。这让我明白,很多情况下不是传感器不准,而是我们使用的方法太“粗糙”。另一个收获是对 信号类型 的理解。TCS3200的频率输出方式,让我直观感受到了数字信号在抗干扰上的优势,以及 pulseIn() 函数在频率测量中的应用。
这个系统的天花板很高。你现在看到的只是一个用阈值判断颜色的“玩具”,但它的骨架——传感器数据采集、微控制器处理、人机交互——是许多工业设备的简化版。你可以基于此,尝试更复杂的颜色匹配算法,连接云平台,或者把它作为机器人视觉的一部分。希望这次动手实践,能成为你探索更广阔嵌入式世界的一块坚实跳板。
更多推荐
所有评论(0)