TCS230/TCS3200 颜色传感器与 Arduino 的接口
颜色传感器为复杂的自动化挑战提供更可靠的解决方案。它们用于食品和饮料、汽车和制造业等各个行业,用于检测材料、检测零件上的颜色标记、验证制造过程中的步骤等。
虽然工业应用中使用昂贵的颜色传感器,但 TCS230 颜色传感器等廉价传感器可用于不太严格的应用。
TCS230 颜色传感器(也称为 TCS3200)非常流行、便宜且易于使用。在我们在 Arduino 项目中使用此颜色传感器之前,最好先了解一下颜色传感器的实际工作原理。
颜色传感器的工作原理
白光由三种基色(红、绿、蓝)组成,它们具有不同的波长。这些颜色相互结合形成不同深浅的颜色。
当白光照射到任何表面时,一些波长的光会被吸收,一些会被反射,具体取决于表面材料的特性。我们看到的颜色是波长反射回我们眼睛的结果。
现在回到传感器,典型的颜色传感器包括一个高强度白色 LED,可将调制光投射到物体上。为了检测反射光的颜色,几乎所有颜色传感器都由颜色敏感滤光片网格(也称为“拜耳滤光片”)和下方的光电二极管阵列组成,如下图所示。
单个像素由 4 个滤镜组成,1 个红色、1 个蓝色、1 个绿色和 1 个透明滤镜(无滤镜)。这种模式也称为“拜耳模式”。每个滤光片仅将单一颜色的光传递到下方的光电二极管,而透明滤光片则按原样传递光,如下所示。通过透明滤光片的额外光线是弱光条件下的一个主要优势。
然后处理芯片对每个光电二极管进行寻址(一次一种颜色),并测量光的强度。由于存在光电二极管阵列,因此首先对结果进行平均,然后发送出去进行处理。通过测量红、绿、蓝光的相对水平,可以确定物体的颜色。
TCS230 颜色传感器模块
该模块的核心是来自德克萨斯先进光电解决方案公司的廉价 RGB 传感器芯片 – TCS230。TCS230 颜色传感器是一款完整的颜色检测器,可以检测和测量几乎无限范围的可见颜色。
传感器本身位于模块的中心,周围环绕着四个白色 LED。当模块通电时,LED 会亮起,用于照亮被感测的物体。借助这些 LED,传感器还可以在完全黑暗的环境中工作,以确定物体的颜色或亮度。
TCS230 的工作电源电压为 2.7 至 5.5 V,并提供 TTL 逻辑电平输出。
TCS230操作
TCS230 借助 8 x 8 光电二极管阵列来检测颜色,其中 16 个光电二极管具有红色滤光片,16 个光电二极管具有绿色滤光片,16 个光电二极管具有蓝色滤光片,其余 16 个光电二极管是透明的,没有滤光片。
每 16 个光电二极管都是并联连接的,因此您可以使用两个控制引脚 S2 和 S3 选择读取其中的一个。例如,如果您只想检测红色,则可以根据表格将两个引脚设置为低电平来选择 16 个红色滤光光电二极管。
同样,可以通过S2和S3的不同组合来选择不同类型的光电二极管。
S2 | S3 | 光电二极管类型 |
LOW | LOW | 红色的 |
LOW | HIGH | 蓝色的 |
HIGH | LOW | 清除(无过滤器) |
HIGH | HIGH | 绿色的 |
内部电流频率转换器将光电二极管的读数转换为方波,其频率与所选颜色的强度成正比。典型输出频率范围为2HZ~500KHZ。
该传感器还有两个控制引脚 S0 和 S1,用于缩放输出频率。频率可以缩放为 2%、20% 或 100% 三个不同的预设值。这种频率缩放功能允许传感器与各种微控制器和其他设备一起使用。
S0 | S1 | 输出频率缩放 |
LOW | LOW | 断电 |
LOW | HIGH | 2% |
HIGH | LOW | 20% |
HIGH | HIGH | 100% |
通过S0和S1的不同组合可以得到不同的缩放因子。对于 Arduino,大多数应用都使用 20% 的缩放比例。
TCS230 颜色传感器模块引脚分配
下图显示了常见 TCS230 模块的引脚排列。
接地是接地引脚。
OE是输出使能引脚。该引脚很少使用,并且在大多数模块上都是永久启用的。如果尚未启用,则将其拉低。
S0&S1引脚用于选择频率缩放。
S2&S3引脚用于选择颜色阵列。
OUT引脚为TTL电平方波
VCC引脚为模块供电。将其连接至2.7V至5.5V电源。
将 TCS230 颜色传感器连接到 Arduino UNO
将 TCS 230 连接到 Arduino 非常简单。除输出使能引脚外,每个引脚均被使用,并且该模块由 Arduino 的 5 伏输出安全供电。
以下是 TCS230 实验的连接:
Arduino 上使用的所有引脚都不是关键的,因为该模块不需要任何特定于引脚的功能,因此如果您想使用不同的引脚,您可以安全地这样做。请务必更改代码中的引脚编号以反映接线的任何更改。
一旦您的传感器连接到 Arduino,就可以编写一些代码了!
校准传感器
我们实际上将使用两个草图来处理 TCS230 颜色传感器
- 第一个草图(校准草图)将帮助我们从传感器获取原始数据。
- 第二个草图(Arduino 主草图)将使用之前接收到的原始数据来显示所感测颜色的 RGB 值。
请注意,两个草图将使用相同的硬件连接。
以下是校准草图。该草图逐个颜色地处理 TCS230 传感器并读取输出引脚的脉冲宽度。然后输出显示在串行监视器上。
将草图加载到 Arduino 并安装传感器,使其面向物体。首先找到白色和黑色的参考对象。这些参考物体将产生所有三种颜色的最大值和最小值的读数。
// Define color sensor pins
#define S0 4
#define S1 5
#define S2 6
#define S3 7
#define sensorOut 8
// Variables for Color Pulse Width Measurements
int redPW = 0;
int greenPW = 0;
int bluePW = 0;
void setup() {
// Set S0 - S3 as outputs
pinMode(S0, OUTPUT);
pinMode(S1, OUTPUT);
pinMode(S2, OUTPUT);
pinMode(S3, OUTPUT);
// Set Pulse Width scaling to 20%
digitalWrite(S0,HIGH);
digitalWrite(S1,LOW);
// Set Sensor output as input
pinMode(sensorOut, INPUT);
// Setup Serial Monitor
Serial.begin(9600);
}
void loop() {
// Read Red Pulse Width
redPW = getRedPW();
// Delay to stabilize sensor
delay(200);
// Read Green Pulse Width
greenPW = getGreenPW();
// Delay to stabilize sensor
delay(200);
// Read Blue Pulse Width
bluePW = getBluePW();
// Delay to stabilize sensor
delay(200);
// Print output to Serial Monitor
Serial.print("Red PW = ");
Serial.print(redPW);
Serial.print(" - Green PW = ");
Serial.print(greenPW);
Serial.print(" - Blue PW = ");
Serial.println(bluePW);
}
// Function to read Red Pulse Widths
int getRedPW() {
// Set sensor to read Red only
digitalWrite(S2,LOW);
digitalWrite(S3,LOW);
// Define integer to represent Pulse Width
int PW;
// Read the output Pulse Width
PW = pulseIn(sensorOut, LOW);
// Return the value
return PW;
}
// Function to read Green Pulse Widths
int getGreenPW() {
// Set sensor to read Green only
digitalWrite(S2,HIGH);
digitalWrite(S3,HIGH);
// Define integer to represent Pulse Width
int PW;
// Read the output Pulse Width
PW = pulseIn(sensorOut, LOW);
// Return the value
return PW;
}
// Function to read Blue Pulse Widths
int getBluePW() {
// Set sensor to read Blue only
digitalWrite(S2,LOW);
digitalWrite(S3,HIGH);
// Define integer to represent Pulse Width
int PW;
// Read the output Pulse Width
PW = pulseIn(sensorOut, LOW);
// Return the value
return PW;
}
上传草图后,您将获得此类读数。记录在两个极端处获得的读数。
代码说明:
该草图首先定义用于连接 TCS230 的引脚。还定义了一些变量来表示红色、绿色和蓝色阵列的脉冲宽度。
#define S0 4
#define S1 5
#define S2 6
#define S3 7
#define sensorOut 8
int redPW = 0;
int greenPW = 0;
int bluePW = 0;
在设置中,我们将 S0-S3 引脚定义为输出。这些引脚将用于选择频率缩放和我们希望处理的颜色。S0 和 S1 引脚用于将频率缩放设置为 20%,这是将此颜色传感器与 Arduino 结合使用时的常见值。接下来,传感器输出引脚被定义为 Arduino 的输入,这是我们接收方波的地方。最后,我们设置了串行监视器。
void setup() {
// Set S0 - S3 as outputs
pinMode(S0, OUTPUT);
pinMode(S1, OUTPUT);
pinMode(S2, OUTPUT);
pinMode(S3, OUTPUT);
// Set Pulse Width scaling to 20%
digitalWrite(S0,HIGH);
digitalWrite(S1,LOW);
// Set Sensor output as input
pinMode(sensorOut, INPUT);
// Setup Serial Monitor
Serial.begin(9600);
}
在循环部分,我们调用三个函数getRedPW()
、getGreenPW()
和getBluePW()
来获取脉冲宽度。让我们getRedPW()
举个例子来看看。
该getRedPW()
函数获取红色脉冲宽度。首先设置 S2 和 S3 引脚来选择红色滤光片。这是该函数与其绿色和蓝色对应函数不同的唯一步骤。
接下来,定义一个整数来存储脉冲宽度。然后使用 Arduino 函数确定脉冲宽度pulseIn()
。该函数测量脉冲宽度,请注意,我们已将其配置为测量脉冲低电平部分的宽度。结果是以毫秒为单位的时间。然后返回该值并且函数终止。
int getRedPW() {
// Set sensor to read Red only
digitalWrite(S2,LOW);
digitalWrite(S3,LOW);
// Define integer to represent Pulse Width
int PW;
// Read the output Pulse Width
PW = pulseIn(sensorOut, LOW);
// Return the value
return PW;
}
回到循环中,我们调用三个函数来读取颜色脉冲宽度,在它们之间添加 200ms 的延迟以使传感器稳定。然后我们在串行监视器上打印这些值并重复循环。
void loop() {
// Read Red Pulse Width
redPW = getRedPW();
// Delay to stabilize sensor
delay(200);
// Read Green Pulse Width
greenPW = getGreenPW();
// Delay to stabilize sensor
delay(200);
// Read Blue Pulse Width
bluePW = getBluePW();
// Delay to stabilize sensor
delay(200);
// Print output to Serial Monitor
Serial.print("Red PW = ");
Serial.print(redPW);
Serial.print(" - Green PW = ");
Serial.print(greenPW);
Serial.print(" - Blue PW = ");
Serial.println(bluePW);
}
Arduino 代码 – 从 TCS230 读取 RGB 值
读取读数后,您可以上传下一个草图,我们将从 TCS230 颜色传感器读取 RGB 值。
上传草图之前,请在草图顶部输入从校准草图获得的六个校准值。将“0”替换为您的实际值。
// Define color sensor pins
#define S0 4
#define S1 5
#define S2 6
#define S3 7
#define sensorOut 8
// Calibration Values
// *Get these from Calibration Sketch
int redMin = 0; // Red minimum value
int redMax = 0; // Red maximum value
int greenMin = 0; // Green minimum value
int greenMax = 0; // Green maximum value
int blueMin = 0; // Blue minimum value
int blueMax = 0; // Blue maximum value
// Variables for Color Pulse Width Measurements
int redPW = 0;
int greenPW = 0;
int bluePW = 0;
// Variables for final Color values
int redValue;
int greenValue;
int blueValue;
void setup() {
// Set S0 - S3 as outputs
pinMode(S0, OUTPUT);
pinMode(S1, OUTPUT);
pinMode(S2, OUTPUT);
pinMode(S3, OUTPUT);
// Set Sensor output as input
pinMode(sensorOut, INPUT);
// Set Frequency scaling to 20%
digitalWrite(S0,HIGH);
digitalWrite(S1,LOW);
// Setup Serial Monitor
Serial.begin(9600);
}
void loop() {
// Read Red value
redPW = getRedPW();
// Map to value from 0-255
redValue = map(redPW, redMin,redMax,255,0);
// Delay to stabilize sensor
delay(200);
// Read Green value
greenPW = getGreenPW();
// Map to value from 0-255
greenValue = map(greenPW, greenMin,greenMax,255,0);
// Delay to stabilize sensor
delay(200);
// Read Blue value
bluePW = getBluePW();
// Map to value from 0-255
blueValue = map(bluePW, blueMin,blueMax,255,0);
// Delay to stabilize sensor
delay(200);
// Print output to Serial Monitor
Serial.print("Red = ");
Serial.print(redValue);
Serial.print(" - Green = ");
Serial.print(greenValue);
Serial.print(" - Blue = ");
Serial.println(blueValue);
}
// Function to read Red Pulse Widths
int getRedPW() {
// Set sensor to read Red only
digitalWrite(S2,LOW);
digitalWrite(S3,LOW);
// Define integer to represent Pulse Width
int PW;
// Read the output Pulse Width
PW = pulseIn(sensorOut, LOW);
// Return the value
return PW;
}
// Function to read Green Pulse Widths
int getGreenPW() {
// Set sensor to read Green only
digitalWrite(S2,HIGH);
digitalWrite(S3,HIGH);
// Define integer to represent Pulse Width
int PW;
// Read the output Pulse Width
PW = pulseIn(sensorOut, LOW);
// Return the value
return PW;
}
// Function to read Blue Pulse Widths
int getBluePW() {
// Set sensor to read Blue only
digitalWrite(S2,LOW);
digitalWrite(S3,HIGH);
// Define integer to represent Pulse Width
int PW;
// Read the output Pulse Width
PW = pulseIn(sensorOut, LOW);
// Return the value
return PW;
}
加载草图并使用不同颜色的样本观察结果。如有必要,您可以对校准值进行微调。
代码说明
您会注意到,该草图的大部分内容与之前的草图完全相同,除了:
从校准草图获得的六个校准值将输入到草图的顶部。
// Calibration Values
int redMin = 0; // Red minimum value
int redMax = 0; // Red maximum value
int greenMin = 0; // Green minimum value
int greenMax = 0; // Green maximum value
int blueMin = 0; // Blue minimum value
int blueMax = 0; // Blue maximum value
为我们想要输出的 RGB 值定义了三个新变量。
int redValue;
int greenValue;
int blueValue;
在循环部分,我们使用上一个草图中使用的相同函数读取每个值。然后我们使用Arduinomap()
函数将这些值转换为RGB值,以我们的校准值作为参考。
请注意,我们已经反转了范围(最小值映射到 255,最大值映射到 0),因为我们的函数返回脉冲宽度,而不是频率。
// Read Red value
redPW = getRedPW();
// Map to value from 0-255
redValue = map(redPW, redMin,redMax,255,0);
// Delay to stabilize sensor
delay(200);
最后,我们在串行监视器上输出值。这些最终读数将对应于被扫描物品的 RGB 值。