开启左侧

颜色传感器 TCS3200

[复制链接]
发表于 2017-4-13 00:14:53 | 显示全部楼层 |阅读模式
本帖最后由 PPeach 于 2017-4-17 23:07 编辑

       这样的颜色传感器,其实在Arduino学习过程中使用的还是蛮多的,主要不是因为他的效果怎么怎么好,或者使用起来怎么怎么方便,而是因为推广的好,然后很多小白不懂就一个接一个用了下去。
       模块上手,讲实在的并不是很好用。这里注意,该模块不能用来检测动态的颜色变化,其次,这个环境光对这个模块的影响比较大,就算加了白色LED,也要尽量的保证被测颜色的物体足够接近传感器,识别的颜色才会较为准确(可能是因为我程序不会写吧)。
       如果想比较准确的使用这个模块,最好有一个支撑来保证模块到背侧物体的距离保持不变,并且,最好加入大数据分析。前面一个是硬件上的问题,用3D打印一个支座便可以了,后面一个,要么人工读取数据分析,要么使用机器学习。
       这篇文章的主要目的就是对模块进行一个介绍,然后贴一下测试程序,讲解一下程序的组成。最后会把程序和WS2812/2813进行整合,做一个灯带可以根据检测物体颜色而变化的小玩意(不过讲实在的,颜色还是不是很准确)。
       废话不多说,先上接线图。
298309.png
这里我们看一下各个IO的意思。
S2 S3是控制模块内一个可控的滤镜来选择透过光的颜色。这里贴一下图,主要就是讲一下原理,看不懂也无所谓,到时候看程序组成即可,我们只要会用,不用知道为什么。
298306.png
S0 S1是一个控制比率因子的IO,这个比率因子影响OUT输出的脉冲个数。举个例子,你现在假设检测红光,然后比率设成2%那么OUT就有可能输出2个,你要设置成100,OUT就输出100个。
298307.png

我们控制与检测的,主要也就是这五个IO,剩下的LED, VCC, GND就是供电上的问题,这里我推荐LED供电电压采用3.3V。
现在我们来贴一下程序,这里采用  宜昌城老张  的程序,非常感谢。
这里提供原博文:http://www.eefocus.com/zhang700309/blog/13-08/296390_6c438.html
  1. #include <TimerOne.h> //申明库文件
  2. //把TCS3200颜色传感器各控制引脚连到Arduino数字端口
  3. #define S0    6   //物体表面的反射光越强,TCS3002D内置振荡器产生的方波频率越高,
  4. #define S1    5  //S0和S1的组合决定输出信号频率比例因子,比例因子为2%
  5.                  //比率因子为TCS3200传感器OUT引脚输出信号频率与其内置振荡器频率之比
  6. #define S2     4   //S2和S3的组合决定让红、绿、蓝,哪种光线通过滤波器
  7. #define S3     3

  8. #define OUT    2  //TCS3200颜色传感器输出信号连接到Arduino中断0引脚,并引发脉冲信号中断
  9.                   //在中断函数中记录TCS3200输出信号的脉冲个数
  10. #define LED    7  //控制TCS3200颜色传感器是否点亮LED灯
  11. float g_SF[3];     //从TCS3200输出信号的脉冲数转换为RGB标准值的RGB比例因子
  12. int   g_count = 0;  // 计算与反射光强相对应TCS3200颜色传感器输出信号的脉冲数
  13. // 数组用于存储在1s内TCS3200输出信号的脉冲数,它乘以RGB比例因子就是RGB标准值
  14. int   g_array[3];  
  15. int   g_flag = 0;   // 滤波器模式选择顺序标志

  16. // 初始化TSC3200各控制引脚的输入输出模式
  17. //设置TCS3002D的内置振荡器方波频率与其输出信号频率的比例因子为2%
  18. void TSC_Init()
  19. {
  20.   pinMode(S0, OUTPUT);
  21.   pinMode(S1, OUTPUT);
  22.   pinMode(S2, OUTPUT);
  23.   pinMode(S3, OUTPUT);
  24.   pinMode(OUT, INPUT);
  25.   pinMode(LED, OUTPUT);
  26.   digitalWrite(S0, LOW);
  27.   digitalWrite(S1, HIGH);
  28. }

  29. //选择滤波器模式,决定让红、绿、蓝,哪种光线通过滤波器
  30. void TSC_FilterColor(int Level01, int Level02)
  31. {
  32.   if(Level01 != 0)
  33.     Level01 = HIGH;
  34.   if(Level02 != 0)
  35.     Level02 = HIGH;
  36.   digitalWrite(S2, Level01);
  37.   digitalWrite(S3, Level02);
  38. }

  39. //中断函数,计算TCS3200输出信号的脉冲数
  40. void TSC_Count()
  41. {
  42.   g_count ++ ;
  43. }

  44. //定时器中断函数,每1s中断后,把该时间内的红、绿、蓝三种光线通过滤波器时,
  45. //TCS3200输出信号脉冲个数分别存储到数组g_array[3]的相应元素变量中
  46. void TSC_Callback()
  47. {
  48.   switch(g_flag)
  49.   {
  50.     case 0:
  51.          Serial.println("->WB Start");
  52.          TSC_WB(LOW, LOW);   //选择让红色光线通过滤波器的模式
  53.          break;
  54.     case 1:
  55.          Serial.print("->Frequency R=");
  56.          Serial.println(g_count);   //打印1s内的红光通过滤波器时,TCS3200输出的脉冲个数
  57.          g_array[0] = g_count;    //存储1s内的红光通过滤波器时,TCS3200输出的脉冲个数
  58.          TSC_WB(HIGH, HIGH);  //选择让绿色光线通过滤波器的模式
  59.          break;
  60.     case 2:
  61.          Serial.print("->Frequency G=");
  62.          Serial.println(g_count);   //打印1s内的绿光通过滤波器时,TCS3200输出的脉冲个数
  63.          g_array[1] = g_count;    //存储1s内的绿光通过滤波器时,TCS3200输出的脉冲个数
  64.          TSC_WB(LOW, HIGH);  //选择让蓝色光线通过滤波器的模式
  65.          break;

  66.     case 3:
  67.          Serial.print("->Frequency B=");
  68.          Serial.println(g_count);   //打印1s内的蓝光通过滤波器时,TCS3200输出的脉冲个数
  69.          Serial.println("->WB End");
  70.          g_array[2] = g_count;     //存储1s内的蓝光通过滤波器时,TCS3200输出的脉冲个数
  71.          TSC_WB(HIGH, LOW);   //选择无滤波器的模式  
  72.          break;
  73.    default:
  74.          g_count = 0;     //计数值清零
  75.          break;
  76.   }
  77. }
  78. //设置反射光中红、绿、蓝三色光分别通过滤波器时如何处理数据的标志
  79. //该函数被TSC_Callback( )调用
  80. void TSC_WB(int Level0, int Level1)   
  81. {
  82.   g_count = 0;   //计数值清零
  83.   g_flag ++;     //输出信号计数标志
  84.   TSC_FilterColor(Level0, Level1); //滤波器模式
  85.   Timer1.setPeriod(1000000);     //设置输出信号脉冲计数时长1s
  86. }
  87. //初始化
  88. void setup()
  89. {
  90.   TSC_Init();
  91.   Serial.begin(9600); //启动串行通信
  92.   Timer1.initialize();   // defaulte is 1s
  93.   Timer1.attachInterrupt(TSC_Callback); //设置定时器1的中断,中断调用函数为TSC_Callback()
  94.   //设置TCS3200输出信号的上跳沿触发中断,中断调用函数为TSC_Count()
  95.   attachInterrupt(0, TSC_Count, RISING);
  96.   digitalWrite(LED, HIGH);//点亮LED灯
  97.   delay(4000); //延时4s,以等待被测物体红、绿、蓝三色在1s内的TCS3200输出信号脉冲计数
  98.   //通过白平衡测试,计算得到白色物体RGB值255与1s内三色光脉冲数的RGB比例因子
  99.   g_SF[0] = 255.0/ g_array[0];     //红色光比例因子
  100.   g_SF[1] = 255.0/ g_array[1] ;    //绿色光比例因子
  101.   g_SF[2] = 255.0/ g_array[2] ;    //蓝色光比例因子
  102.   //打印白平衡后的红、绿、蓝三色的RGB比例因子
  103.   Serial.println(g_SF[0],5);
  104.   Serial.println(g_SF[1],5);
  105.   Serial.println(g_SF[2],5);
  106.   //红、绿、蓝三色光分别对应的1s内TCS3200输出脉冲数乘以相应的比例因子就是RGB标准值
  107.   //打印被测物体的RGB值
  108.   for(int i=0; i<3; i++)
  109.     Serial.println(int(g_array[i] * g_SF[i]));   
  110. }
  111. //主程序
  112. void loop()
  113. {
  114.    g_flag = 0;
  115.    //每获得一次被测物体RGB颜色值需时4s
  116.    delay(4000);
  117.    //打印出被测物体RGB颜色值
  118.    for(int i=0; i<3; i++)
  119.       Serial.println(int(g_array[i] * g_SF[i]));
  120. }
复制代码

在这里,我对程序运行的流程进行一个简单的介绍:
程序中设定了一个定时器中断,一个外部中断,定时器中断是为了控制S3 S4进行滤光片选择,外部中断是为了对OUT的输出进行计数,这里涉及到一些物理知识。
红色透光镜只透的过红色,绿色透光镜只透的过绿色,蓝色透光镜只透的过蓝色。物理里面定义这三个颜色为三原色,由三原色可以混出任何颜色。所以我们只要检测三原色的脉冲值就好了。
这里我们先引入一个理念:如果红(R)绿(G)蓝(B)三色如果用0到255表示,那么0就是没这个颜色,255就是该颜色最亮。我们理论认为,当三个颜色都是255时候就是白色(实际的话颜色会和白色有一点点不一样)。程序运行后,先进行白平衡矫正,我们需要把颜色传感器放到一个白色的物体上,记录下在当前环境中,RGB的最大值,然后对应到255。这样就有了一个定量的判断,那么你以后该环境下的所有的颜色都是和这个白色进行参考(实际上就是一个标定的过程),这里注意,只要你的环境改变了,就需要重新进行校正。校正完成了后,我们就可以使用RGB三个值进行下一步操作。
这里注意,RGB三个值并不是保存在数组中,而是由两个数组相乘的到,R是g_array[0] * g_SF[0], G是g_array[1] * g_SF[1],B是g_array[2] * g_SF[2],前一项是OUT的脉冲数,后一项就是你标定产生的一个比例值。换句话说,你的标定其实是修改后面的g_SF。

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

精彩课程推荐

关于我们

帮助中心

商务合作

点击这里给我发消息

关注微信公众号

Copyright © 2016-2017 i创学院 - 上海享渔教育科技有限公司 Powered by Discuz!     ( 沪ICP备16033954号-1 )