开启左侧

TCS3200与WS2812

[复制链接]
发表于 2017-6-5 17:42:38 | 显示全部楼层 |阅读模式
     这一章我们主要讲述一下WS2812与TCS3200的结合使用,再开始这章教程之前,我们需要先贴出TCS3200与WS2812的教程,我的建议是请将这两份教程单独调试通过以后再进行本章内容。(文字已经做了超链接,点击即可直达:Arduino与WS2812Arduino与TCS3200。)     注意本章教程是基于链接两个教程的,请务必看完再来学习!请务必看完再来学习!请务必看完再来学习!
     其实制作起来很简单,我们主要先分析一下WS2812的程序,找一下对我们有用的数据是什么。
  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. }
复制代码
    仔细阅读程序后我们发现,真正有用的数据是RGB三色标定后的值,也就是对应的 R是g_array[0] * g_SF[0], G是g_array[1] * g_SF[1],B是g_array[2] * g_SF[2]。
     然后我们查看一下WS2812的函数库,发现WS2812的函数中正好可以有配置RGB三个颜色的值。
  1. pixels.Color(a, b, c);
复制代码
    所以我们需要做的事情很简单,只要将RGB三色对应的值传递给该函数,然后控制WS2812进行show操作即可。
     现在我来贴一下程序。

  1. #include <TimerOne.h> //申明库文件
  2. #include <Adafruit_NeoPixel.h>

  3. // 配置WS2812
  4. #define PIN            6
  5. #define NUMPIXELS      16
  6. Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

  7. // 把TCS3200颜色传感器各控制引脚连到Arduino数字端口
  8. #define S0    6     // 物体表面的反射光越强,TCS3002D内置振荡器产生的方波频率越高,
  9. #define S1    5     // S0和S1的组合决定输出信号频率比例因子,比例因子为2%
  10. // 比率因子为TCS3200传感器OUT引脚输出信号频率与其内置振荡器频率之比
  11. #define S2     4    // S2和S3的组合决定让红、绿、蓝,哪种光线通过滤波器
  12. #define S3     3

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

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

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

  44. // 中断函数,计算TCS3200输出信号的脉冲数
  45. void TSC_Count()
  46. {
  47.   g_count ++ ;
  48. }

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

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

  126.   // 将RGB三色值传递给 pixels.Color()函数,然后全部传递完成后执行show函数
  127.   for (int i = 0; i < NUMPIXELS; i++)
  128.     pixels.setPixelColor(i, pixels.Color(g_array[0] * g_SF[0], g_array[1] * g_SF[1], g_array[2] * g_SF[2]));
  129.   pixels.show();
  130. }
复制代码
    程序部分我都做了注释,其实只需要在TCS3200的程序进行小小的修改即可。连线请参考文章开头贴的两篇帖子!
回复

使用道具 举报

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

本版积分规则

精彩课程推荐

关于我们

帮助中心

商务合作

点击这里给我发消息

关注微信公众号

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