一个基于TCS230颜色传感器和51单片机为核心的颜色识别系统,能够将颜色转化成构成它的R、G、B三基色数值。
本次设计由TCS230颜色传感器做为颜色的采集识别装置、STC89C52单片机做为核心控制系统、1602液晶显示器和LED小灯做为信号数字显示装置。通过三基色原理[10],和TCS230颜色传感器在工作时可以自主的选用其内部相应的滤波器,透过并识别不同频段的光强,在单片机程序的控制作用下将不同频段的波段信号最终以数字信号的形式在液晶显示器上显现出来。 主要工作内容如下:系统通电后打开开关先进行白平衡,白平衡过后将需要识别的颜色卡片置于颜色传感器上,颜色传感器会将采集到的颜色进行采集识别,并且将识别出的信号以波段的形式输送至单片机,单片机通过程序识别颜色传感器所发出的信号,在通过程序控制LCD液晶显示模块和LED灯组模块,显示出颜色传感器所采集到的信号。具体的系统结构如图2-1所示。 图2-1 颜色检测系统硬件结构示意图
2.2 方案比较与选择 由于单片机、颜色传感器和液晶显示器的种类众多,该颜色识别系统可以选择不同的元件。以下为本次硬件设计的几个核心模块元件的比较分析和最终选择。 2.2.1 单片机主控模块的选择 硬件部分涉及到了单片机,在我们日常学习中,常用的单片机有STM32系列、Arduino、51系列。以下为这三种单片机的比较以及最终选择。 STM32系列单片机。该系列单片机拥有强劲的性能、可嵌套中断、低功耗、位带操作、高代码密度等众多优点,还拥有着丰富的片内资源和强大的库函数支持。但对于本设计来说32系列单片机的运用较为复杂,32系列功能完全溢出。 Arduino 单片机内部直接包含硬件和软件能够直接读取传感器的数字或模拟输入信号,可连接云端操作,不需要额外的编程下载器将代码下载到板子上,能够极大缩减软件开发时间。但对于本设计来说Arduino核心板的I/O 端口较少、主频较低不适用。 89C52单片机是最简洁基础的入门级单片机,同时也是应用最广泛的8位单片机之一。其能够通过下载器将Keil上面的程序直接下载进单片机进行仿真、调试。而且其还具有方便插入到用户板中、体积小、价格实惠等优点。在插入时将单片机紧贴用户板,不需用连接线缆,可以有效地降低运行中的干扰,同时也能避免仿真时出现的一些不确定故障,虽然功能不如32强,但完全适用于本设计。 2.2.2 颜色采集识别模块的选择 现存的颜色采集识别元件分为两种类型,第一类是带有滤波片的光电二极管、第二类则是颜色识别传感器。 带有滤波器的光电二极管是直接将红、绿、蓝滤波片分别放置于相对独立的光电二极管的表面,对光信号进行初步的处理,在经过A/D电路对信号进行采集,采集过后在进一步的对信号进行处理识别,这样做电路较为复杂,增大了系统体积和设计成本,且识别颜色的效果较差。 颜色识别传感器可以直接对接受到的颜色信号进行采集处理并识别,再通过以不同频率的波段信号的形式直接将信号传递给单片机控制系统。这样使得识别系统电路较为简单,减少了系统体积和设计成本,同时TCS230颜色识别传感器本身还具有体积较小、识别精度较高等特点,完全适合该设计所需条件。 2.2.3 显示模块的选择 显示模块只需要能够显示出构成待测颜色的R、G、B数值即可。OLED1286液晶具有显示反应速度快,像素点密集,有着128*64个点阵等优势,不过在实际使用时发现该液晶需要自主建立字体模型使用较为复杂,而且该设计的需求并不能完全的适配与该液晶,最终使用LCD1602液晶。该液晶可显示两行,每行显示16个字符[11],具有使用简便、价格实惠的优点。虽然反应速度和显示能力不如OLED12864液晶,但完全能够适用于本设计。 2.2.4 设计所需元件清单 下表为该设计所需要的元器件清单表 表2-1 元件清单表
2.3 主要器件介绍 以下主要对构成设计的STC89C52单片机、TCS230颜色传感器、LCD1062液晶显示器做一个全面系统的介绍。 2.3.1 STC89C52单片机(1)STC89C51系列引脚功能 STC89C51系列单片机拥有40根引脚,每根引脚有不同的功能。图2-2为STC89C52单片机的引脚图,其中2根主电源线引脚VCC(P40)和VDDGND/VSS(P20)分别表示可接+5V电源的电源接口和电路接地线。2根外界晶振引脚XTAL1(P19)、XTAL2(P18)分别表示片内振荡电路的输入端口和片内振荡电路的输出端口。4根控制引脚即RST/VPP(P9)复位引脚,当单片机复位时该引脚上会出现两个机器周期的高电平;ALE/PROG(P30)地址锁存允许信号;PSEN(P29)外部储存器读选信号;EA/VPP(P31)程序存储器的内外部选通,当接高电平时从内部程序储存器读指令,当接低电平时从外部程序存储器读指令。4组8位可编程I/O口,每个口有8根引脚一共32根可编程输入/输出引脚,分别位于P0、P1、P2、P3口。P0口(P39~P32):8位双向I/O口线,名称为P0.0~P0.7;P1口(P1~P8):8位准双向I/O口线,名称为P1.0~P1.7;P2口(P21~P28):8位准双向I/O口线,名称为P2.0~P2.7;P3口(P10~P17):8位准双向I/O口线,名称为P3.0~P3.7。 图2-2 STC89C52单片机引脚图
(2)STC89C52的工作原理 单片机就是按时钟周期,取出指命和数据,作出相关的硬件操作[12]。当系统需要做出一项指令时,能否找到该项指令,要对该项指令做出什么处理,就需要单片机软件程序判断,并且做出相应的数据存储器。在单片机寻找的过程中,可能会出现单片机的中断。当单片机完成该项指令后,若是没有新的指令下达则单片机开始进入休眠状态,—但系统有新的指令下达单片机便又开始工作。STC89C52的内部结构如图2-3。 图2-3 STC89C52内部结构图 2.3.2 TCS230颜色传感器(1)TCS230的结构及工作原理 TCS230在单一芯片上集成了64个光电二极管,这64个光电二极管分为4类,16个带有红色滤波器的光电二极管;16个带有绿色滤波器的光电二极管;16个带有蓝色滤波器的光电二极管和16个不带有任何滤波器的光电二极管,基本上可以透过全部的光信号。这些光电二极管在芯片中又是交叉排列的,能够最大限度的减少入射光辐射的不均匀性,同时颜色相同的16个光电二极管是并联的,均匀分布在二极管阵列中,可以消除颜色的位置误差极大的提高了识别精度。工作时可通过两个可编程的引脚来动态选择所需要的滤波器。其内部结构如图2-4所示。 图2-4 TCS230颜色传感器内部结构图 由图可知当光照射到TCS230颜色传感器上时,光电二极管能够控制引脚S2,S3进行不同的组合,从而选择不同的滤波器,在通过电流-频率转换器将滤过识别到的颜色信号转换成不同的方波段,不同的颜色对应不同频率的波段;还可以通过输出信号控制引脚SO,S1,选择不同的信号输出比例因子(100%,20%,2%),从而调节输出波段频率范围,来达到不同的识别要求。以下两表为内部引脚所对应的功能和不同引脚工作在高低电平时传感器所对应的工作选项。 表2-2 STC230内部引脚所对应的功能表
表2-3 不同组合下的工作状态表
TCS230颜色传感器能够识别颜色的方式基于三点即三基色原理、颜色识别原理、白平衡原理。 三基色原理:人眼能够看到东西是因为人眼能够接收到来自物体反射的光。当太阳光或其它光源照射到物体表面时,某些频率的可见光会被物体表面吸收,不能吸收的可见光则会被物体表面反射,当肉眼接收到这一部分反射光,就形成了我们看到的颜色。这也说明了太阳光是一种由各种频率的可见光混合而成的光束,其中包含着各种颜色的光。自然界中所有颜色都可以通过不同比例的三基色(红、绿、蓝)混合得到,这称为三基色原理。 颜色识别原理:由三基色原理可知,任何颜色都可以由三基色通过不同比例构成,当确定了某物体的三基色比例数值,就可以反过来确定该物体的颜色。TCS230颜色传感器能够识别颜色是因为它内部含有64个光电二极管构成的滤波器。进行颜色识别时它能够选择一种特定的滤波器工作,当该种滤波器工作时只能通过特定的颜色,阻止其它颜色通过。这样就能得到通过滤波器的颜色的光强,通过透过颜色的不同光强数值,就可以分析照射在TCS230颜色传感器上的光的颜色。当使用TCS230颜色识别传感器识别颜色时:依次选择三种颜色滤波器,再对TCS230的输出脉冲进行依次计数。当计数到255时停止计数,记录下每个通道到达的时间,在这段时间内所测得的脉冲数量就是该颜色所对应的R、G、B的值。 白平衡和颜色识别原理:在颜色识别系统软件上确定一个基底色,由于该基底色通常选为白色故而称为白平衡。通常情况下白色应是由红色、绿色、蓝色按照相同的比例混合而成的,因此在调节白平衡时系统液晶显示屏上R、G、B的数值应保持在(255、255、255)。但实际测试中白色中的三基色数值并不相同,这样会导致TCS230颜色传感器上R、G、B的输出数值不同,导致后面的颜色识别不准确[14]。故在测试颜色前需要调节白平衡,使TCS230颜色传感器上检测到白色中的三基色数值相同,保证后面颜色识别的准确性。 (3)TCS230颜色识别电路接口 图2-5 TCS230与单片机的连接方式图
如图2-5所示,将TCS230颜色传感器的输出引脚连接到单片机的定时\计数的输入端。设置单片机定时计数器的工作方式,初始化单片机定时器的值,在调整TCS230的输出比例因子。在测量时通过单片机计数器的值,就可以计算出TCS230的各种输出频率,从而确定待测颜色的R、G、B三基色的数值。 2.3.3 LCD1602液晶LCD1602液晶显示器是广泛使用的一种字符型液晶显示模块。它是由字符型液晶显示屏(LCD)、控制驱动主电路HD44780及其扩展驱动电路HD44100,以及少量电阻、电容元件和结构件等装配在PCB板上而组成,内部带了80个字节的显示RAM,用来储存发送的数据。其与单片机的连接方式如图2-6。 图2-6 LCD1062与单片机的连接方式
其一共有16个引脚,每个引脚功能如下表。 表2-4 LCD1602引脚功能表
LCD1602液晶是可以显示两行,每行16个字符的液晶。第一行的地址是 0x00H 到 0x27,第二行的地址从 0x40 到 0x67,其中第一行0x00 到 0x0F是与液晶上第一行 16 个字符显示位置相对应的,第二行 0x40 到 0x4F 是与第二行 16 个字符显示位置相对应的[15]。而每行都多出来一部分,是为了显示移动字幕设置。其工作状态如下表。 表2-5 LCD工作状态表
图2-7所示是在本设计中当LCD1602处于白平衡工作状态时,所显示出的R、G、B三基色数值。 图2-7 LCD在工作时显示数值
第3章 系统软件设计设计中TCS230颜色传感器是现成的,可直接通电使用,在软件中不需要对系统进行初始化也可以进行颜色的识别。开始先在程序中定义参数,在识别待测颜色过程中,程序先将信号进行线性处理,再调用白平衡函数进行白平衡调节,然后在调用颜色识别函数,其能够完成颜色的采集、对比、转化并输出R、G、B的值,然后进行三种颜色数值的比较以此来控制LED灯的亮灭,最后在通过调用显示函数,将R、G、B的数值显示在显示模块之中,这样便完成了一次颜色的识别。具体程序框图如图3-1所示,整体程序详见附录。 图3-1 主程序框图 其中参数定义部分程序说明了单片机与1602液晶、LED和颜色传感器之间对应的引脚连接方式,还说明了程序中引用的子函数的作用以及定义了函数中某些字符所代表的颜色、颜色因子等必要参数;线性处理部分程序是对颜色传感器识别的信号先做一个处理。CMOD=0x51设置16位定时计数工作模式,由于颜色传感器识别的信号是不同频率的波段,设置一个16位的定时计数模式,用10ms内识别到的脉冲数量来求取待测颜色数值;颜色对比部分程序是用来判断构成该颜色的三基色的最大值,来控制对应LED的点亮和熄灭。 颜色识别子函数:该程序设置了颜色传感器的引脚工作状态的高低电平,以此来选择其内部的滤波器类型,如设置(S2=0、S3=0)此时红色滤波器工作,可求得三基色中的红色数值。具体方法如下:定时器(TH0、TL0)定时工作10ms,在这10ms内计数器(TH1、TL1)会记录出输入的脉冲个数,当10ms过后关闭定时器、计数器。此时红色滤波器工作,那么R=((TH1*256+TL1)/红色因子)。同理,调整传感器S2、S3的工作状态分别使另外两个滤波器工作即可求出其它两基色的值,R、G、B三个数值即可确定颜色。 白平衡子程序:上述中颜色识别过程中最终得出的颜色数值为脉冲数量/颜色因子,白平衡的过程就是求取颜色因子。由白平衡原理可知此时R、G、B的值应为(255、255、255),在通过计数器计算出在10ms内的脉冲数即可求得颜色因子。此时颜色因子=((TH1*255+TL1)/255)。通过设置不同的滤波器工作可以求出不同颜色(R、G、B)的颜色因子。 显示部分程序:1602液晶可以每行显示16个字符,共可显示两行。先设置1602初始化函数,定义液晶引脚的工作电平以此来控制其工作状态(读写状态、读写指令),在显示时设置显示在第X(X不大于1)行第Y列(Y不大于15),由于第二行显示的地址是从0x40开始的,当显示在第二行时地址码需加0x40,算出指令码进行显示。
第4章 硬件电路设计及测试 4.1 硬件电路 由于该设计较为便捷,在了解了各个模块的功能与作用之后,只需要将第二章所述模块各自按照其与单片机的连接方式逐一搭建起来,然后在通过仿真模拟记录下显示模块的数据,并且与网络上的标准比色卡的数据进行对比,判断本设计是否能够实现其要求的颜色识别功能即可。 首先在Altium Designer 软件上面构建出颜色采集识别模块、单片机主控模块、液晶显示模块中各个引脚之间的硬件模拟图。由于在Altium Designer 软件上面没有TCS230和LCD1602这两款元件,则需要自己通过创建子电路的方式进行构建。如图4-1,4-2,4-3是该设计的总硬件电路图、PCB版图和3D模拟图。 图4-1 颜色识别系统硬件电路模拟图 图4-2 系统PCB版图
图4-3 系统3D效果图
由于在Altium Designer上构建出来的元器件不能实现该元器件应有的功能,所以本设计不能通过软件仿真测试,只能通过实物进行仿真测试,因此需要先进行本设计的实物搭建。按照上述硬件模拟电路图,将实物逐步焊接在电路板上,为了能够使得LCD液晶显示器模块有更好的显示效果,在电路的设计中添加了一个滑动变阻器,通过调节滑动变阻器的阻值来控制LCD液晶的显示数值的亮暗程度,更加便于肉眼观察。如图4-4是本设计的硬件实物图。 图4-4 颜色识别系统硬件电路实物图 4.2实物测试 在Keil软件上编写程序,利用串口下载器将程序下载进STC89C52单片机中,并且使用不同颜色的卡纸放置在TCS230颜色传感器上,记录出现在LCD液晶显示模块上面的R、G、B数值。R、G、B三基色的数值只会出现在0-255之间,当某一数值显示为0时表示该基色颜色不参与该待测颜色的构成,若是待测颜色为三基色本身那么其余的两个基色的数值应显示为0,待测三基色应显示为255.如:测试基色红色,则显示结果应该为(R:255、G:0、B:0)同理其它三基色也是如此。将记录下的R、G、B数值输入到三基色颜色配比表(网页版)中,将待测颜色与三基色颜色配比表中出现的颜色进行对比,判断本颜色识别系统是否能够准确的识别待测颜色。如图4-5是本颜色识别系统的实物进行白平衡时的工作状态图。 图4-5 颜色识别系统实物白平衡仿真图 由上图可以看出,当带有颜色的卡纸放置在TCS230颜色传感器上时,在LCD显示模块上面会显示出R、G、B各自占比的数值,上图为系统白平衡调试故显示的数值为(R255、G255、B255)。 4.3数据测试 由于颜色的多种多样性,故选取7种具有代表性的颜色进行颜色识别测试,并分别将液晶显示模块上的数值记录下来,并且将数据输入进颜色生成器中,看生成的颜色是否符合待测颜色。下表为测试结果以及颜色生成器生成的目标颜色。 表4-1 颜色识别装置测试结果表
以下两组图片为该颜色识别系统在两种颜色的卡纸识别时的工作状态,以及数据验证。 图4-6 红色卡纸识别工作状态 图4-7 红色卡纸数据验证
图4-8 绿色卡纸识别工作状态
图4-9 绿色卡纸数据验证
单片机源程序如下:
- #include <reg52.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define LCM_Data P0 //LCD1602数据接口
- #define Busy 0x80 //用于检测LCM状态字中的Busy标识
- sbit LCM_RW = P2^6; //读写控制输入端,LCD1602的第五脚
- sbit LCM_RS = P2^7; //寄存器选 择输入端,LCD1602的第四脚
- sbit LCM_E = P2^5; //使能信号输入端,LCD1602的第6脚
- sbit deng_r =P2^0;
- sbit deng_g =P2^1;
- sbit deng_b =P2^2;
- sbit tcs230_s2=P1^1;//TCS230 S2接单片机P2.0
- sbit tcs230_s3=P1^0;//TCS230 S3接单片机P2.1
- sbit tcs230_en=P3^0; //TCS230 EN(E0)接GND
- void WriteDataLCM (uchar WDLCM);//LCD模块写数据
- void WriteCommandLCM (uchar WCLCM,BuysC); //LCD模块写指令
- uchar ReadStatusLCM(void);//读LCD模块的忙标
- void DisplayOneChar(uchar X,uchar Y,uchar ASCII);//在第X+1行的第Y+1位置显示一个字符
- void LCMInit(void);//LCD初始
- void DelayMs(uint Ms);//1MS基准延时程序
- void baipingheng();//白平衡子程序
- void celiang();//实际颜色程序
- uint ryz,gyz,byz;//分别定义红色因子 绿色因子 蓝色因子
- uint rb,gb,bb;//RGB值
- uchar tab1[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
- main()
- {
- int i;
- unsigned char max=0;
- TMOD=0x51;//设定T0以工作方式1定时10毫秒
- LCMInit();//LCD初始
- for(i=0;i<5;i++)
- baipingheng();//上电时先白平衡一次
- while(1)
- {
- celiang();//颜色测试
- max=rb;
- if(gb>max)
- max=gb;
- else
- max=max;
- if(bb>max)
- max=bb;
- else
- max=max;
- if(max==rb)
- deng_r=1;
- else
- deng_r=0;
- if(max==gb)
- deng_g=1;
- else
- deng_g=0;
- if(max==bb)
- deng_b=1;
- else
- deng_b=0;
- DisplayOneChar(0, 0,'R');//以十进制显示RGB中红色的分值
- DisplayOneChar(0, 1, rb/100+0x30); //显示百位数据
- DisplayOneChar(0, 2, rb/10%10+0x30);//显示十位数据
- DisplayOneChar(0, 3, rb%10+0x30);//显示个位数据
- DisplayOneChar(0, 5,'G');//以十进制显示RGB中绿色的分值
- DisplayOneChar(0, 6, gb/100+0x30); //显示百位数据
- DisplayOneChar(0, 7, gb/10%10+0x30);
- DisplayOneChar(0, 8, gb%10+0x30);
- DisplayOneChar(0, 10,'B');//以十进制显示RGB中蓝色的分值
- DisplayOneChar(0, 11, bb/100+0x30);
- DisplayOneChar(0, 12, bb/10%10+0x30);
- DisplayOneChar(0, 13, bb%10+0x30);
- 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');
- DelayMs(250);//每隔0.25秒测试一次颜色
- }
- }
- void celiang()
- {
- 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=(unsigned long)(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=(unsigned long)(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=(unsigned long)(TH1*256+TL1)*255/gyz;
- if(gb>255)gb=255;//判断RGB值是否合法
- }
- void baipingheng()
- {
- 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;//选择绿色滤光器
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
以上内容的Word格式文档51黑附件下载:
基于单片机颜色识别系统的设计.docx
(3.64 MB, 下载次数: 152)
|