基于STM32F103的TCS3200颜色传感器的使用

团队布置的任务内容是2019年中国机器人大赛的题目,小车运行过程中需要对不同物料进行颜色上的识别。因此我最近就学了TCS3200颜色传感器的基本原理和代码的具体实现。网上对该模块的使用基本是基于Arduino的,对于基于STM32的介绍较少。鉴于此,补一篇代码可以跑STM32的笔记是有必要的(实际上为了凑一篇笔记赶紧交作业)

一、TCS3200芯片介绍

TCS3200是TAOS公司推出的可编程彩色光到频率的转换器,它把可配置的硅光电二极管与电流频率转换器集成在一个单一的CMOS电路上,同时集成了三种颜色(RGB)的滤光器,是业界第一个具有数字兼容接口的RGB彩色传感器。

工作时,通过两个可编程的引脚来动态选择所需要的滤光器,该传感器的典型输出频率范围从2Hz~500kHz,用户还可以通过两个可编程引脚来选择100%、20%、2%的输出比例因子,或是电源关断模式。选择不同的输出比例因子,可以对输出频率范围进行调整,适应不同的测量范围。

TCS3200适合于色度计测量应用领域。比如彩色打印、医疗诊断、计算机彩色监视器校准以及油漆、纺织品、化妆品和印刷材料的过程控制。
下图是其电路原理图(不看也行)

二、颜色识别原理

(一)三原色原理

通常所看到的物体颜色,实际上是物体表面吸收了照射到它上面的白光中的一部分有色成分,而反射出的另一部分有色光在人眼中的反应。白色是由各种频率的可见光混合在一起构成的,也就是说白光中包含着各种颜色的色光(如红R、黄Y、绿G、青V、蓝B、紫P)。根据德国物理学家赫姆霍兹的三原色理论可知,各种颜色是由不同比例的三原色(红、绿、蓝)混合而成的。每一种颜色都一个标准值。由上面的三原色感应原理可知,特定颜色的值就是红绿蓝三种颜色标准值的线性组合。

(二)TCS3200的识别原理

对于TCS3200来说,当选定一个颜色滤波器时,它只允许某种特定的原色通过,阻止其它原色的通过。例如:当选择红色滤波器时,入射光中只有红色可以通过,蓝色和绿色都被阻止,这样就可以得到红色光的光强;同理,选择其它的滤波器,就可以得到蓝色光和绿色光的光强。通过这三个光强值,就可以分析出反射到TCS3200D传感器上的光的颜色。TCS3200传感器有红绿蓝和清除4种滤光器,可以通过其引脚 S2S3 的高低电平来选择滤波器模式,如下图。

L表示低电平,H表示高电平

当被测物体反射光的红、绿、蓝三色光线分别透过相应滤波器到达TAOS TCS3200RGB感应芯片时,其内置的振荡器会输出方波,方波频率与所感应的光强成比例关系,光线越强,内置的振荡器方波频率越高。TCS3200传感器有一个OUT引脚,它输出信号的频率与内置振荡器的频率也成比例关系,它们的比率因子可以靠其引脚S0和S1的高低电平来选择,如下图。

现在我们对光强值做了处理,令其转换成了波,又在它的基础上乘上了一个因子来转换成OUT引脚输出给主控板的信号频率。现在就差要得到对应颜色的RGB标准值,这需要我们就需要做 白平衡校正

(三)白平衡校准

白平衡就是告诉传感器什么是“白色”的。以白色为参照颜色,才能计算其他颜色的RGB标准值。从理论上讲,白色是由等量的红色、蓝色、绿色混合而成的。

Window画图功能中编辑颜色界面

而然实际上白色中的RGB并不是完全相等,并且TCS3200光传感器对三种颜色的敏感性并不相同,导致RGB输出并不相同。因此必须要做白平衡校正,使得TCS3200检测的`“白色”``输出的RGB值一样。

白平衡的方法:把一个白色物体放置在TCS3200颜色传感器之下,两者相距10mm左右,点亮传感器上的4个白光LED灯,然后选通三原色的滤波器,让被测物体反射光中红、绿、蓝三色光分别通过滤波器,得到OUT引脚输出信号的脉冲数。在用白色的RGB标准值分别处以对应颜色就得到了三种颜色的比例因子。有了白平衡校正得到的RGB比例因子,就可以讲测得其他颜色的信号脉冲换算成RGB标准值了。

S=255N0(1)S={255\over N_0}\tag{1}S=N0​255​(1)
E=S∗N0(1)E=S*N_0\tag{1}E=S∗N0​(1)

N0是白平衡是测得的脉冲数,S是RGB比例因子,E是当前检测颜色的RGB值。

三、颜色识别的思路、方法以及代码实现

(一)方法及思路

根据上文的介绍,对颜色信号的采集基本上是以下步骤

我们的检测思路是:开一个定时器,间隔1s进入一次中断服务,在中断服务函数中采集信号并进行计算处理。1s检测RGB中的一种颜色。另外再开一个定时器,用来统计OUT引脚输出的脉冲数。第一次的检测做白平衡检测,用255除以脉冲数得到RGB比例因子,就可以用于之后的识别。所以白平衡进行一次,之后的检测都写在while函数里即可。开启串口通信,用printf函数把RGB值每隔4s打印一次,检查TCS3200传感器的识别结果。

(一)代码实现

我使用STM32CubeMax进行STM32开发,开发方式使用HAL库。用的板子型号是正点原子MINI板,芯片型号为STM32F103RCT6。

巨量的初始化函数自动生成,函数直接集成不同功能,谁用谁爽~~

这是我使用的GPIO口:

GPIO输出模式

PA4 —————— S0

PA5 —————— S1

PA6 —————— S2

PA7 —————— S3

PC4 —————— LED

定时器2外部时钟模式
PA0 —————— OUT

然后开了串口1 定时器1

定时器1采用内部时钟模式,经过倍频后APB2总线上的频率为72kHz,设置预分频系数和计数值分别为(7200-1)和(10000-1),这样定时间隔即为1s

定时器2采用外部时钟模式,统计OUT引脚输出的脉冲个数,计数方式为向上计数,65535溢出

打开串口1,采用异步传输方式,波特率为115200,8位字节的数据长度。没有奇偶校验位,数据发送停止位有1位。

下图是对时钟树的配置,在这里不多说

下面上代码:

我把有用的代码都写在了主函数文件里面,那些初始化函数啥的就不放出来,直接看有用的部分吧。另外声明,这些代码参考了http://www.eefocus.com/zhang700309/blog/13-08/296390_6c438.html,我改成了能在STM32板子上跑的代码。

  #include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
#include "stdio.h"    //使用printf函数需要调用这个库#define S0_L HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);  #define S0_H HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);#define S1_L HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);  #define S1_H HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);#define S2_L HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET);  #define S2_H HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET);#define S3_L HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_RESET);  #define S3_H HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET);#define LED_OFF HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_RESET);  #define LED_ON HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_SET);float RGB_Scale[3];          //数组存储3个RGB比例因子
int count=0;               //统计脉冲数
int cnt[3];              //数组存储RGB三种颜色的脉冲值
int flag=0;               //滤波器选择模式标志void SystemClock_Config(void);void filter(int s2,int s3)  //滤波器模式选择函数,根据S2和S3的电位来选择红、绿、蓝、三种颜色的滤波器
{if(s2==0&&s3==0){S2_L;S3_L;}if(s2==0&&s3==1){S2_L;S3_H;}if(s2==1&&s3==0){S2_H;S3_L;}if(s2==1&&s3==1){S2_H;S3_H;}
}void TSC_WB(int s2, int s3)  //结束上一种颜色识别,开始下一种颜色的识别
{count = 0;   //统计脉冲值清零flag ++;     //输出信号计数标志+1,进行下一个颜色的脉冲统计filter(s2, s3); //选择滤波器模式}int fputc(int c, FILE *stream)    //重定义printf函数,在川口打印数据
{HAL_UART_Transmit(&huart1, (unsigned char *)&c, 1, 1000);   return 1;
}int main(void)
{HAL_Init();        //初始化函数SystemClock_Config();MX_GPIO_Init();MX_TIM1_Init();MX_USART1_UART_Init();  MX_TIM2_Init();HAL_TIM_Base_Start_IT(&htim1); //使能TIM1HAL_TIM_Base_Start_IT(&htim2);  //使能TIM2S0_L;S1_H;    //选择2%的输出比例因子LED_ON;   //打开白光LED进行白平衡HAL_Delay(4000);  //延时四秒等待识别//通过白平衡测试,计算得到白色物体RGB值255与1s内三色光脉冲数的RGB比例因子RGB_Scale[0] = 255.0/ cnt[0];     //红色光比例因子RGB_Scale[1] = 255.0/ cnt[1] ;    //绿色光比例因子RGB_Scale[2] = 255.0/ cnt[2] ;    //蓝色光比例因子//打印白平衡后的红、绿、蓝三色的RGB比例因子printf("%5lf\r\n",RGB_Scale[0]);printf("%5lf\r\n",RGB_Scale[1]);printf("%5lf\r\n",RGB_Scale[2]);//红、绿、蓝三色光分别对应的1s内TCS3200输出脉冲数乘以相应的比例因子就是RGB标准值//打印被测物体的RGB值for(int i=0; i<3; i++)printf("%d\r\n",(int)(cnt[i]*RGB_Scale[i])); printf("白平衡调试结束\r\n");//白平衡结束后,就可以检测其他的颜色了,为了让它不断检测,我们让他循环起来while (1){flag=0;  //标志位清0 开始下一轮的识别count=0;   //脉冲数置为0,开始统计下一个脉冲数HAL_Delay(4000);  //延时4s 等待识别结果for(int i=0; i<3; i++)printf("%d\r\n",(int)(cnt[i] * RGB_Scale[i])); }void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK){Error_Handler();}
}//定时器1的中断服务函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){if(htim->Instance==htim1.Instance){count=__HAL_TIM_GET_COUNTER(&htim2);//将TIM2统计的脉冲数存入变量countswitch(flag){case 0:printf("->WB Start\r\n");TSC_WB(0, 0);   //选择让红色光线通过滤波器的模式break;case 1:printf("->Frequency R=");printf("%d\r\n",count);   //打印1s内的红光通过滤波器时,TCS3200输出的脉冲个数cnt[0] = count;    //存储1s内的红光通过滤波器时,TCS3200输出的脉冲个数TSC_WB(1, 1);  //选择让绿色光线通过滤波器的模式break;case 2:printf("->Frequency G=");printf("%d\r\n",count);   //打印1s内的绿光通过滤波器时,TCS3200输出的脉冲个数cnt[1] = count;    //存储1s内的绿光通过滤波器时,TCS3200输出的脉冲个数TSC_WB(0, 1);  //选择让蓝色光线通过滤波器的模式break;case 3:printf("->Frequency B=");printf("%d\r\n",count);   //打印1s内的蓝光通过滤波器时,TCS3200输出的脉冲个数printf("->WB End\r\n");cnt[2] = count;     //存储1s内的蓝光通过滤波器时,TCS3200输出的脉冲个数TSC_WB(1, 0);   //选择无滤波器的模式  break;default:count = 0;     //计数值清零break;}}
}void Error_Handler(void)
{}void assert_failed(uint8_t *file, uint32_t line)
{}
#endif

下面是实物接线,emmm,不太会拍,具体怎么接线参考其他文章吧。

现在我们来测试一下,打开串口助手。

可以看到我们接收到了来自传感器的信号,然后根据传来的数值做进一步处理。比如在这个比赛里,可以利用传来数据控制舵机呀,电机这些的下一步动作。不过这个测试还是有一些问题的,白平衡阶段和识别颜色阶段获得的脉冲数有异常的变动。我认为可能是硬件方面的问题,需要做进一步排查。欢迎大家积极讨论,发现问题。





分割线一下

发文两天后,经过一个大佬的指点,发现了我代码中的错误。为什么做完白平衡之后,我统计的脉冲数会暴增呢?原因就在于上面代码块的第144行中的_HAL_TIM_GET_COUNTER();我进了他函数内部看了一下,发现这根本不是一个函数,而是一个宏定义。


        所以这个语句他只会读取当前TIM2统计的脉冲数,而并不会每次读完之后都清除掉统计脉冲值,所以TIM2上的脉冲数一直是在累加的,这就是为什么我之前做的时候脉冲数异常暴增。解决方法很简单,就是在每次读完脉冲数之后手动清除CNT寄存器中的值TIM2->CNT=0;这样就可以啦。另外就是白平衡时和检测颜色时要保证外部的光照条件基本一样,所以全程要点亮白光LED,消除外界光源影响。
        我们再来做一遍测试。我测的红色。看一下传感器返回给上位机的结果。


返回的RGB标准值分别是159 66 56,我们在Windows画图里检验一下结果的准确性。

哈哈哈哈哈哈,我只能说识别结果还行。
        那么到这里,对这款传感器的讲解就到这里啦。

基于STM32F103的TCS3200颜色传感器的使用相关推荐

  1. TCS3200颜色传感器测试实验

    TCS3200颜色传感器测试实验 2013-08-02 17:18:24 分享: 标签:  Arduino  TCS3200  传感器 TCS3200颜色传感器是一款全彩的颜色检测器,包括了一块TAO ...

  2. 使用TCS3200颜色传感器的自制Arduino色选机

    顾名思义,颜色分类只是根据颜色对事物进行排序.它可以通过查看来轻松完成,但是当有太多东西需要分类并且是重复性任务时,自动颜色分选机非常有用.这些机器使用颜色传感器来感应任何物体的颜色,并在检测到颜色伺 ...

  3. 【TCS3200 颜色传感器与 Arduino 实现颜色识别】

    TCS3200 颜色传感器与 Arduino 实现颜色识别 前言 TCS3200 颜色传感器引脚 颜色传感器模块如何工作? TCS3200 颜色传感器模块组成 关于颜色传感器 TCS3200 的常见问 ...

  4. Ardunio开发实例-TCS3200颜色传感器

    颜色传感器 TCS3200颜色传感器可以根据其波长检测多种颜色. 该传感器对颜色识别项目特别有用,例如颜色匹配,颜色分类,试纸条读取等等. TCS3200颜色传感器(如下图所示)使用TAOS TCS3 ...

  5. TCS3200颜色传感器测试实验:

    收藏自用,转自:http://www.eefocus.com/zhang700309/blog/13-08/296390_6c438.html TCS3200颜色传感器是一款全彩的颜色检测器,包括了一 ...

  6. arduino下不用定时器的TCS3200颜色传感器

    参考dfrobot官方示例:http://wiki.dfrobot.com.cn/index.php?title=(SKU:SEN0101)TCS3200%E9%A2%9C%E8%89%B2%E4%B ...

  7. 基于STM32的VEML6040颜色传感器应用

    *以下文章资源均来自互联网,文章内容仅供参考,如果侵犯了您的权益,请留言或通过邮箱与我联系. The following article resources are all from the Inte ...

  8. 51单片机驱动TCS3200颜色识别传感器

    51单片机驱动TCS3200颜色识别传感器 TCS3200 简介 输出频率与滤光器选择说明 实验说明 接线 驱动 驱动说明 主要代码 主函数 实验现象 验证: 实验注意事项: TCS3200 简介 T ...

  9. TCS3200颜色识别传感器

    颜色传感器使用 文章目录 颜色传感器使用 前言 一.原理 二.代码实现 现象 前言 TCS3200颜色传感器是一款全彩的颜色检测器,包括了一块TAOS TCS3200RGB感应芯片和4个白光LED灯, ...

最新文章

  1. JVM基础面试题及原理讲解
  2. 李飞飞AI100报告提出14大AI机遇与挑战(附pdf)
  3. java 常量pi_JAVA的常量
  4. html认识数字游戏大全,认识数字小游戏,就是这么简单!为孩子收藏
  5. bootstrap与zookeeper区别
  6. [转载]C#异步委托的用法 .
  7. linux龙芯自动挂载u盘,Windows Subsystem for Linux (WSL)挂载移动硬盘U盘
  8. windows10双系统安装ubuntu18.04
  9. 【Unity开源项目精选】UniRx:Unity中的响应式编程
  10. python123平台作业答案循环结构棋盘放米_python练习集100题(1-20)
  11. linux系统怎么关闭445端口,如何关闭window 系统的445端口等方法 预防勒索病毒
  12. ARM 汇编详解 -- 体系结构与编程
  13. cacti mysql 压缩 备份_CactiEZ备份和恢复
  14. 全球十大农业大数据经典案例
  15. php 加密解密函数 sha,使用sha1()函数进行加密-php加密技术
  16. 知名大企业的愿景和使命
  17. algorithm negotiation fail错误
  18. 聊一聊进程、线程和协程以及线程的那些“锁“事
  19. 用python实现弹跳球游戏_使用Pygame模块制作一个跳跃的小球游戏
  20. s3c2440存储控制器详解

热门文章

  1. [病毒分析]WannaCry病毒分析(永恒之蓝)
  2. 十问十答,快速了解科力锐勒索拦截系统!
  3. JavaScript实现shift键连续多选
  4. 卷积码matlab图,【卷积码的MATLAB仿真设计】 卷积码仿真
  5. 产品经理-交流中所涉及的术语
  6. 安装win7到移动硬盘(亲自试过了)
  7. 爱上你是一种流泪的幸福
  8. 格林公式的原理理解(考研数学)
  9. tcp 错误代码 10061: 由于目标计算机积极拒绝,无法连接.,错误号10061:无法建立连接,因为目标计算机主动拒绝它(客户端-服务器)...
  10. squeezenet代码_2.1 SqueezeNet V1思考