背景:
随着现代工业生产向高速化、自动化方向的发展,生产过程中长期以来由人眼起主导作用的颜色识别工作将越来越多地被相应的颜色传感器所替代。例如:图书馆使用颜色区分对文献进行分类,能够极大地提高排架管理和统计等工作;在包装行业,产生包装利用不同的颜色和装潢来表示其不同的性质或用途。目前的颜色传感器通常是在独立的光电二极管上覆盖经过修正的红、绿、蓝滤波片,然后对输出信号进行相应的处理,才能将颜色信号识别出来;有的将两者集合起来,但是输出模拟信号,需要一个A/D电路进行采集,对该信号进一步处理,才能进行识别,增加了电路的复杂性,并且存在较大的识别误差,影响了识别的效果。TAOS(TexasAdvancedOptoelectronicSolutions)公司最新推出的颜色传感器TCS3200,不仅能够实现颜色的识别与检测,与以前的颜色传感器相比,还具有许多优良的新特性。
最近在网上淘了一片TCS3200模块,从官方的介绍中看的出这片TCS3200功能好强大,闲来没事就做了一实验,想看看这个TCS3200的性能、检测能力到底怎样;
需要的器件和材料:
1.51最小系统(12T 时钟:11.0592MHz)
2.TCS3200颜色识别模块
3.各种颜色的物料
4.1602液晶屏
TCS3200接口定义:
S0、S1接VCC
EO接GND(或用IO口控制)
S2接P1.0
S3接P1.1
OUT接P3.5(必须)
(测试程序贴在后面,实物测试通过!)
(TCS3200颜色识别模块) (自己做的TCS3200模块转接板,方便连线,方便检测颜色)
(模块和转接板连接完成)
(最小系统)
(1602液晶屏)
(连接好1602液晶屏)
(为了方便检测小物料和白平衡检测,需要自己做一个小平台,俩饮料瓶盖子,一颗自攻螺丝即可搞定!)
(做好的平台,为了方便白平衡,需要在上面盖子上划俩口子,只要能卡住一张白纸即可!)
(最终效果)
(全家福)
(连接好TCS3200模块)
(白平衡测试,注意:上电前必须白平衡检测,不然后面检测的颜色都不会准确的;检测方法:白纸放在TCS3200模块前面1公分处,然后单片机上电,只要第一次读出的值为255,255,255即可,否则请重新进行白平衡!)
(白平衡的结果,现在就可以进行颜色识别了)
(识别到绿色娃娃的颜色,上位机上面的颜色为识别到的颜色,同时液晶上会显示RGB值)
(识别到黄色娃娃的颜色值)
(识别到粉红色娃娃的颜色值)
(上位机显示粉红色娃娃的颜色)
(上位机界面)
(这俩高尔夫球的识别,但是结果不准确,估计是这俩高尔夫球的反光能力太强烈了,只要表面不是很光滑的物体检测出来误差都是很小的,另外,有网友说要放在黑盒子里检测,我感觉没必要,只要白平衡做好了基本就没什么问题了,至于表面特别光滑的物体,只能去寻找其他方法去进行检测了!)
========================= 测 试 程 序 ======================== #include "reg52.h"
#define _data P2 //LCD1602数据接口
/******************************************************************
- 说明:端口定义
- 备注:无
******************************************************************/
sbit EN =P0^5; //读写使能,高电平有效,下降沿锁定数据。
sbit RW =P0^6; //读/写选择:高电平为读数据,低电平为写数据。
sbit RS =P0^7; //数据/指令选择:高电平为数据,低电平为指令。
sbit tcs230_s2=P1^0; //TCS3200 S2 P1.0
sbit tcs230_s3=P1^1; //TCS3200 S3 P1.1
//TCS3200 OUT 接P3.5
/******************************************************************
- 说明:变量定义
- 备注:无
******************************************************************/
unsigned int Ryz,Gyz,Byz; //分别定义红色因子 绿色因子 蓝色因子
unsigned int Rzhi,Gzhi,Bzhi; //RGB值
unsigned char code num[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
/******************************************************************
- 功能描述:延时子程序
- 入口参数:长整数型
- 参 数 值:0-65535
- 返回说明:无
- 备 注:无
******************************************************************/
void delay1ms(unsigned int ms)//延时1毫秒(不够精确的)
{
unsigned int i,j;
for(i=0;i<ms;i++)
for(j=0;j<100;j++);
}
void delay600ms(void)
{
unsigned char a,b,c;
for(c=89;c>0;c--)
for(b=230;b>0;b--)
for(a=12;a>0;a--);
}
/******************************************************************
- 功能描述:写数据子程序
- 入口参数:数据
- 参 数 值:字节型
- 返回说明:无
- 备 注:无
******************************************************************/
void wdat(unsigned char dat)
{
delay1ms(1);
RS=1;
RW=0;
EN=0;
_data=dat;
delay1ms(1);
EN=1;
delay1ms(1);
EN=0;
}
/******************************************************************
- 功能描述:写命令子程序
- 入口参数:数据
- 参 数 值:字节型
- 返回说明:无
- 备 注:无
******************************************************************/
void wcmd(unsigned char com)
{
delay1ms(1);
RS=0;
RW=0;
EN=0;
_data=com;
delay1ms(1);
EN=1;
delay1ms(1);
EN=0;
}
/******************************************************************
- 功能描述:初始化子程序
- 入口参数:无
- 参 数 值:无
- 返回说明:无
- 备 注:无
******************************************************************/
void init_1602(void)
{
delay1ms(15);
wcmd(0x38);delay1ms(5); //功能设置 8位总线 2行显示 5*7点阵
wcmd(0x06);delay1ms(5); //设置输入模式 光标右移 整体不移
wcmd(0x08);delay1ms(5); //设置显示方式 显示关
wcmd(0x01);delay1ms(5); //清除显示
wcmd(0x0c);delay1ms(5); //设置显示方式 显示开 无光标 光标不闪烁
}
/******************************************************************
- 功能描述:指定位置写字符函数
- 入口参数:行,列,字符
- 参 数 值:无
- 返回说明:无
- 备 注:无
******************************************************************/
void DisplayOneChar( unsigned char X, unsigned char Y, unsigned char in)
{
X &= 0x1; //限制X值为 0 和 1
Y &= 0xF; //限制Y值为 0 - 15
if (X)
{Y|=0x40;} //当要显示第二行时地址码+0x40;
Y |= 0x80; //得出列位置
wcmd(Y); //写地址
wdat(in); //写数据
}
/******************************************************************
- 功能描述:发送数据到上位机
- 入口参数:数据1,数据2,数据3
- 参 数 值:无
- 返回说明:无
- 备 注:无
******************************************************************/
void SendOneByte(unsigned char ina,unsigned char inb,unsigned char inc)
{
TMOD = 0x20;
SCON = 0x50;
TH1 = 0xFD;
TL1 = TH1;
PCON = 0x00;
EA = 1;
ES = 1;
TR1 = 1;
SBUF = ina;
while(!TI);
TI = 0;
SBUF = inb;
while(!TI);
TI = 0;
SBUF = inc;
while(!TI);
TI = 0;
}
/******************************************************************
- 功能描述:白平衡函数
- 入口参数:无
- 参 数 值:无
- 返回说明:无
- 备 注:无
******************************************************************/
void baipingheng(void)
{
TMOD=0x51; //设定T0以工作方式1定时10毫秒
TH0=(65536-10000)/256; //取红色因子
TL0=(65536-10000)%256;
TH1=0;
TL1=0;
tcs230_s2=0;
tcs230_s3=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;
Gyz=TH1*256+TL1; //其实这里的比例因子应该为255/(TH1*256+TL1)
}
/******************************************************************
- 功能描述:测量颜色值
- 入口参数:无
- 参 数 值:无
- 返回说明:无
- 备 注:无
******************************************************************/
void ceyanse(void)
{
TMOD=0x51; //设定T0以工作方式1定时10毫秒
TH0=(65536-10000)/256; //求R值
TL0=(65536-10000)%256;
TH1=0;
TL1=0;
tcs230_s2=0; //选择红色滤光器
tcs230_s3=0;
TR0=1; //10毫秒开始计时
TR1=1; //开始计数
while(TF0==0); //等待定时器溢出
TF0=0; //清除定时器0溢出标志
TR0=0; //关闭定时0
TR1=0;
Rzhi=(unsigned long)(TH1*256+TL1)*255/Ryz;
if(Rzhi>255)Rzhi=255; //判断RGB值是否合法
TH0=(65536-10000)/256; //求B值
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;
Bzhi=(unsigned long)(TH1*256+TL1)*255/Byz;
if(Bzhi>255)Bzhi=255; //判断RGB值是否合法
TH0=(65536-10000)/256; //求G值
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;
Gzhi=(unsigned long)(TH1*256+TL1)*255/Gyz;
if(Gzhi>255)Gzhi=255; //判断RGB值是否合法
}
void main(void)
{
init_1602();//LCD初始
baipingheng();//上电时先白平衡一次
while(1)
{
ceyanse(); //颜色测试
DisplayOneChar(0, 0,'R');//以十进制显示RGB中红色的分值
DisplayOneChar(0, 1, Rzhi/100+0x30); //显示百位数据
DisplayOneChar(0, 2, Rzhi/10%10+0x30);//显示十位数据
DisplayOneChar(0, 3, Rzhi%10+0x30);//显示个位数据
DisplayOneChar(0, 5,'G');//以十进制显示RGB中绿色的分值
DisplayOneChar(0, 6, Gzhi/100+0x30); //显示百位数据
DisplayOneChar(0, 7, Gzhi/10%10+0x30);
DisplayOneChar(0, 8, Gzhi%10+0x30);
DisplayOneChar(0, 10,'B');//以十进制显示RGB中蓝色的分值
DisplayOneChar(0, 11, Bzhi/100+0x30);
DisplayOneChar(0, 12, Bzhi/10%10+0x30);
DisplayOneChar(0, 13, Bzhi%10+0x30);
//*****在LCD1602的第二行以16进制显示RGB*******************
DisplayOneChar(1, 1, num[Rzhi/16]);
DisplayOneChar(1, 2, num[Rzhi%16]);
DisplayOneChar(1, 3, 'H');
DisplayOneChar(1, 6, num[Gzhi/16]);
DisplayOneChar(1, 7, num[Gzhi%16]);
DisplayOneChar(1, 8, 'H');
DisplayOneChar(1, 11,num[Bzhi/16]);
DisplayOneChar(1, 12,num[Bzhi%16]);
DisplayOneChar(1, 13,'H');
SendOneByte(Rzhi,Gzhi,Bzhi); //发送数据到上位机
delay600ms(); //每隔0.6秒测试一次颜色
}
}
=========================== 《 完 》 ==========================
薛 二 炜 于江苏·无锡
2015 年 05 月 19 日
smhacker@126.com 转载请注明出处