基于TCS230D和C52C51的颜色识别系统.docx
- 文档编号:10656592
- 上传时间:2023-05-27
- 格式:DOCX
- 页数:18
- 大小:987.64KB
基于TCS230D和C52C51的颜色识别系统.docx
《基于TCS230D和C52C51的颜色识别系统.docx》由会员分享,可在线阅读,更多相关《基于TCS230D和C52C51的颜色识别系统.docx(18页珍藏版)》请在冰点文库上搜索。
基于TCS230D和C52C51的颜色识别系统
一.课设概要:
1.利用TCS230D颜色传感器进行颜色检测
2.利用单片机(STC52)进行控制
3.利用1602液晶显示出RGB值(10进制和16进制)
二.课设原理:
1.TCS230D
(1)参数:
1)电源范围2.7V~5.5V
2)出错率0.2%每50KHz
3)采用soic封装(用DXP进行PCB设计时用到)
(2)颜色检测的原理:
基本原理:
不同的颜色经白光照射后,反射回的光中,RGB的值是不同的。
由三原色感应原理可知,如果知道构成各种颜色的三原色的值,就能够知道所测试物体的颜色。
对于TCS230来说,当选定一个颜色滤波器时,它只允许某种特定的原色通过,阻止其他原色的通过。
例如:
当选择红色滤波器时,入射光中只有红色可以通过,蓝色和绿色都被阻止,这样就可以得到红色光的光强;同理,选择其他的滤波器,就可以得到蓝色光和绿色光的光强。
通过这三个值,就可以分析投射到TCS230传感器上的光的颜色。
TCS230的输出信号是数字量,可以驱动标准的TTL或CMOS逻辑输入,因此可直接与微处理器或其他逻辑电路相连接。
TCS230采用8引脚的SOIC表面贴装式封装,在单一芯片上集成有64个光电二极管。
这些二极管共分为四种类型。
其中16个光电二极管带有红色滤波器;16个光电二极管带有绿色滤波器;16个光电二极管带有蓝色滤波器;其余16个不带有任何滤波器,可以透过全部的光信息。
这些光电二极管在芯片内是交叉排列的,能够最大限度地减少入射光辐射的不均匀性,从而增加颜色识别的精确度;另一方面,相同颜色的16个光电二极管是并联连接的,均匀分布在二极管阵列中,可以消除颜色的位置误差。
工作时,通过两个可编程的引脚来动态选择所需要的滤波器。
该传感器的典型输出频率范围从2Hz~500kHz,用户还可以通过两个可编程引脚来选择100%、20%或2%的输出比例因子,或电源关断模式。
输出比例因子使传感器的输出能够适应不同的测量范围,提高了它的适应能力。
(3)白平衡原理:
白平衡就是告诉系统什么是白色。
从理论上讲,白色是由等量的红色、绿色和蓝色混合而成的;但实际上,白色中的三原色并不完全相等,并且对于TCS230的光传感器来说,它对这三种基本色的敏感性是不相同的,导致TCS230的RGB输出并不相等,因此在测试前必须进行白平衡调整,使得TCS230对所检测的白色!
中的三原色是相等的。
进行白平衡调整是为后续的颜色识别作准备。
在本装置中,白平衡调整的具体步骤和方法如下:
将空的试管放置在传感器的上方,试管的上方放置一个白色的光源,使入射光能够穿过试管照射到TCS230上;根据前面所介绍的方法,依次选通红色、绿色和蓝色滤波器,分别测得红色、绿色和蓝色的值,然后就可计算出需要的3个调整参数。
(4)工作模式:
2.LCD的选取与使用:
(1)参数:
显示容量:
16×2个字符
芯片工作电压:
4.5—5.5V
工作电流:
2.0mA(5.0V)
模块最佳工作电压:
5.0V
字符尺寸:
2.95×4.35(W×H)mm
(2)选取原因:
1602可以显示2行*16个字符,完全可以显示RGB的值。
而且价格便宜,易于控制。
可以直接插到单片机上,非常便利。
(3)使用时的注意项目:
1)使用之前要有一个初始化的子函数。
2)显示值的时候,要有两个子程序,一个子程序用于确定显示字符的位置,一个子程序用于确定显示什么(即段码)
3)显示的时候要注意单片机的时钟,如果单片机的时钟过快,会导致显示的内容一闪而过,这个时候要在程序中加适当的延迟。
4)1602可以显示字母和数字,至于中文只能显示部分简单的。
而且显示中文的时候要先定义库,否则会出现乱码的问题。
三.课设内容:
1.c语言程序:
#include
#defineucharunsignedchar
#defineuintunsignedint
sbitrs=P2^4;//单片机位置3.5
sbitrw=P2^3;//3.6
sbite=P2^2;//3.4
sbittcs230_s2=P2^0;//TCS230S2接单片机P2.0
sbittcs230_s3=P2^1;//TCS230S3接单片机P2.1
sbittcs230_en=P3^0;//TCS230EN(E0)接GND
voidWriteDataLCM(ucharWDLCM);//子函数定义
voidWriteCommandLCM(ucharWCLCM,BuysC);
voidDisplayOneChar(ucharX,ucharY,ucharASCII);
voidLCMInit(void);
voidbaipingheng();
voidceliang();
//变量定义
ucharbusyc,line;
uintryz,gyz,byz;//分别定义红色因子绿色因子蓝色因子
uintrb,gb,bb;//RGB值
uchartab1[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
voiddelay(ucharn)//延迟程序
{
ucharx,y;
for(x=n;x>0;x--)
for(y=110;y>0;y--);
}
//**************************************************LCD子程序
voidbusy(ucharbusyc)//检测忙程序
{
rs=0;
rw=1;
e=1;
delay
(1);
busyc=P0;
e=0;
}
voidLCMInit(void)//lcd初始化程序
{
P0=0;
WriteCommandLCM(0x38,0);//三次显示模式设置,不检测忙信号
delay(5);
WriteCommandLCM(0x38,0);
delay(5);
WriteCommandLCM(0x38,0);
delay(5);
WriteCommandLCM(0x38,1);//显示模式设置,开始要求每次检测忙信号
WriteCommandLCM(0x08,1);//关闭显示
WriteCommandLCM(0x01,1);//显示清屏
WriteCommandLCM(0x06,1);//显示光标移动设置
WriteCommandLCM(0x0C,1);//显示开及光标设置
delay(10);
}
voidWriteDataLCM(ucharWDLCM)//显示字符
{
while(busyc);
rs=1;
rw=0;
e=1;
P0=WDLCM;
delay(10);
e=0;
}
voidWriteCommandLCM(ucharWCLCM,BuysC)//字符的位置确定
{
rs=0;
rw=0;
e=1;
P0=WCLCM;
delay(10);e=0;
}
voidDisplayOneChar(ucharX,ucharY,ucharASCII)//在第几行第几列显示什么
{
X&=0x1;
Y&=0xF;//限制Y不能大于15,X不能大于1
if(X)Y|=0x40;//当要显示第二行时地址码+0x40;
Y|=0x80;//算出指令码
WriteCommandLCM(Y,0);//这里不检测忙信号,发送地址码
WriteDataLCM(ASCII);
}
//*************************************************************************
//*********************************************************************检测子程序
voidceliang()//测量
{
//*********求红值****************************************
TH0=(65536-10000)/256;
TL0=(65536-10000)%256;
TH1=0;
TL1=0;
tcs230_s2=0;
tcs230_s3=0;//选择红色滤光器
tcs230_en=0;
TR0=1;//10毫秒开始计时
TR1=1;//开始计数
while(TF0==0);//等待定时器溢出
TF0=0;//清楚定时器0溢出标志
TR0=0;//关闭定时0
TR1=0;
rb=(unsignedlong)(TH1*256+TL1)*255/ryz;
if(rb>255)rb=255;//判断RGB值是否合法
//***********求蓝色值**************************************
TH0=(65536-10000)/256;
TL0=(65536-10000)%256;
TH1=0;
TL1=0;
tcs230_s2=0;
tcs230_s3=1;//选择蓝色滤光器
TR0=1;//10毫秒开始计时
TR1=1;//开始计数
while(TF0==0);//等待定时器溢出
TF0=0;//清楚定时器0溢出标志
TR0=0;//关闭定时0
TR1=0;
bb=(unsignedlong)(TH1*256+TL1)*255/byz;
if(bb>255)bb=255;//判断RGB值是否合法
//***********求绿色值**************************************
TH0=(65536-10000)/256;
TL0=(65536-10000)%256;
TH1=0;
TL1=0;
tcs230_s2=1;
tcs230_s3=1;//选择绿色滤光器
TR0=1;//10毫秒开始计时
TR1=1;//开始计数
while(TF0==0);//等待定时器溢出
TF0=0;//清楚定时器0溢出标志
TR0=0;//关闭定时0
TR1=0;
tcs230_en=1;
gb=(unsignedlong)(TH1*256+TL1)*255/gyz;
if(gb>255)gb=255;//判断RGB值是否在0-255的区间
}
//***************
voidbaipingheng()//白平衡子程序*
//***************
{
//**************求取红色因子***********************
TH0=(65536-10000)/256;
TL0=(65536-10000)%256;
TH1=0;
TL1=0;
tcs230_s2=0;
tcs230_s3=0;//选择红色滤光器
tcs230_en=0;
TR0=1;//10毫秒开始计时
TR1=1;//开始计数
while(TF0==0);//等待定时器溢出
TF0=0;//清楚定时器0溢出标志
TR0=0;//关闭定时0
TR1=0;
ryz=TH1*256+TL1;//其实这里的比例因子应该为255/(TH1*256+TL1)
//**************求取蓝色因子***********************
TH0=(65536-10000)/256;
TL0=(65536-10000)%256;
TH1=0;
TL1=0;
tcs230_s2=0;
tcs230_s3=1;//选择蓝色滤光器
TR0=1;//10毫秒开始计时
TR1=1;//开始计数
while(TF0==0);//等待定时器溢出
TF0=0;//清楚定时器0溢出标志
TR0=0;//关闭定时0
TR1=0;
byz=TH1*256+TL1;//其实这里的比例因子应该为255/(TH1*256+TL1)
//**************求绿红色因子***********************
TH0=(65536-10000)/256;
TL0=(65536-10000)%256;
TH1=0;
TL1=0;
tcs230_s2=1;
tcs230_s3=1;//选择绿色滤光器
TR0=1;//10毫秒开始计时
TR1=1;//开始计数
while(TF0==0);//等待定时器溢出
TF0=0;//清楚定时器0溢出标志
TR0=0;//关闭定时0
TR1=0;
tcs230_en=1;
gyz=TH1*256+TL1;//其实这里的比例因子应该为255/(TH1*256+TL1)
}
voidmain(void)
{
TMOD=0x51;//设定T0以工作方式1定时10毫秒
LCMInit();//初始化LCD
delay(20);//显示的延迟,用于LCD的显示问题
baipingheng();//上电时先白平衡一次
while
(1)
{
celiang();//颜色测试
DisplayOneChar(0,0,'R');//红色分量
DisplayOneChar(0,1,rb/100+0x30);//百
DisplayOneChar(0,2,rb/10%10+0x30);//十
DisplayOneChar(0,3,rb%10+0x30);//个
DisplayOneChar(0,5,'G');//绿色分量
DisplayOneChar(0,6,gb/100+0x30);//百
DisplayOneChar(0,7,gb/10%10+0x30);//十
DisplayOneChar(0,8,gb%10+0x30);//个
DisplayOneChar(0,10,'B');//蓝色分量
DisplayOneChar(0,11,bb/100+0x30);//百
DisplayOneChar(0,12,bb/10%10+0x30);//十
DisplayOneChar(0,13,bb%10+0x30);//个
//LCD的第二行显示,显示的内容为16进制的RGB值
DisplayOneChar(1,1,tab1[rb/16]);
DisplayOneChar(1,2,tab1[rb%16]);
DisplayOneChar(1,3,'H');
DisplayOneChar(1,6,tab1[gb/16]);
DisplayOneChar(1,7,tab1[rb%16]);
DisplayOneChar(1,8,'H');
DisplayOneChar(1,11,tab1[bb/16]);
DisplayOneChar(1,12,tab1[bb%16]);
DisplayOneChar(1,13,'H');
delay(250);//设置检测的间隔
}
while
(1);
}
2.程序详解:
程序主要由三个部分构成,主程序,模块检测程序,LCD显示程序。
(1)LCD显示程序:
我采用的是一次性显示一个字符,而不是直接显示一行字符,程序中:
首先是两三个与显示有关的子函数,voidDisplayOneChar(ucharX,ucharY,ucharASCII),voidWriteCommandLCM(ucharWCLCM,BuysC)和voidWriteDataLCM(ucharWDLCM)。
WriteCommandLCM的作用是确定显示字符的位置,WriteDataLCM的作用是确定显示什么,DisplayOneChar的作用是吧前两个子函数结合起来,确定在第几行第几列显示什么。
(2)模块检测程序:
该模块中主要就有两个子程序,白平衡和测量程序。
白平衡主要用于TCS的初始化,原因是每次使用TCS的时候环境几乎都不同(主要是周围的亮度和被检测物质的材质),这样的做法可以提高测量的精度。
白平衡程序确定了RGB的初始值,为测量程序服务。
测量程序主要是确定被测量的RGB值,并与初始值做比,则可以得到被测量的RGB值。
(3)主程序:
主程序主要的作用是把子程序连接起来,实现颜色识别并显示的功能。
3.传感器部分:
(1)用DXP进行板的设计:
1)设计TCS230D
由于DXP库中的原件很少,所以大部分都要自行设计
首先根据芯片手册中的长宽高的值,设计出TCS230D的封装,如下图所示:
手册中的尺寸图:
自行设计的TCS230D模块封装图
2)原理图:
3)布线及PCB版图:
如图所示:
P1为TCS230D的位置。
D1,D2,D3,D4为四个LED灯
S为一个开关,R?
为一个滑动变阻器
R1,R2,R3,R4为四个保护电阻
C1,C2,C3,C4为四个电容
4)传感器成品图:
(2)LCD部分:
如下图所示为PROTEUS的仿真图(仅限LCD部分)
四.成品:
五.课设结果:
如图所示:
测量的结果为R255G182B191
真实的结果为R255G180B190
测量的结果为R139G183B147
真实的结果为R135G190B130
测量的结果为R81G91B92
真实的结果为R85G85B85
从上面的数据来看,测量结果并不是很理想,除了第一个误差比较小之外,其余的都存在很大的误差。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 TCS230D C52C51 颜色 识别 系统