TCS3200颜色识别模块

TCS3200颜色识别模块

TCS3200简介

  • 供电电源(2.7V to 5.5V)
  • 可配置颜色滤波器和输出信号频率
  • 高分辨率光强转换到频率(工作原理)

TCS3200工作原理

在这里插入图片描述
在这里插入图片描述

  • TCS3200是TAOS公司推出的可编程彩色光到频率的转换器,它把可配置的硅光电二极管与电流频率转换器集成在一个单一的CMOS电路上,同时集成了三种颜色(RGB)的滤光器;TCS3200能检测物体反射的光强,并生成不同频率的方波信号(50%占空比)

  • TCS3200有一个8*8的光电二极管矩阵,其中分别有三组16个光电二极管有RGB三种滤波器,一组16个光点二极管无滤波器,共64个光电二极管

  • 具有不同滤波器的光电二极管分别检测RGB的值

  • S2和S3用于配置光电二极管矩阵(选择上面四组光电二极管中的一组),S0和S1用于配置电流频率转换器(可以控制输出信号的频率范围)

TCS3200引脚定义

在这里插入图片描述

  • 注意: 对于常见TCS3200颜色识别模块 O E ‾ \overline {OE} OE引脚一般不引出,但会有LED引脚控制模块的LED灯亮灭(一般四个),用于在无光源环境下识别物体

TCS3200功能表

在这里插入图片描述

  • S2、S3用于选择滤波器 对应有 RGB 无滤波器

  • S0、S1用于选择输出波形的频率范围(可以理解为限制输出信号频率的最大值)

  • 下面对TCS3200的输出信号频率作一个简单讲解

在这里插入图片描述

根据网上资料: 该传感器的典型输出频率范围从2Hz-500KHz (但官方资料好像典型值应该到600KHz, 不重要)

S0=H, S1=H对应输出状态为100% 输出典型值为600KHz

S0=H, S1=L对应输出状态为20% 输出典型值为600*0.2 = 120KHz

S0=L, S1=H对应输出状态为2% 输出典型值为 600*0.02=12KHz

注意:该值应为输出频率的最大值, 接着往下看
在这里插入图片描述

这是TCS3200运行特征表的一部分,可以看到在100%输出的模式下, 不同颜色光照对应的输出信号频率范围

TCS3200工作流程

在这里插入图片描述

白平衡校准

白平衡就是告诉TCS3200什么是白色的,以此为参照才能计算其他颜色的RGB。理论上,白色是由等量的RGB混合而成(255、255、255)但实际中,由于光照条件人的感知能力有限等原因,我们看到的白色很有可能不是由均匀的RGB组成,并且TCS3200对三种颜色的敏感性也不相同(参考TCS3200运行特征表),因此进行白平衡给TCS3200一个标准(这个标准有时候不一定准确,会导致识别的结果出现一定的误差)

白平衡的方法: 在装置启动前,先将一个白色物体(不是白色就校验不准)置于传感器处,等待传感器检测,MCU计算出比例因子

题外话: 校验不准容易导致后续的检测中出现异常值,RGB的值超出255,这样在现有的RGB体系下我们无法找到对应的颜色;校验的越准,越不容易出现异常值

颜色识别

参考TCS230,大致有两种思路

在这里插入图片描述

这里采用第二种思路

程序设计

设计思路

设置一个定时器每隔1s进入一次中断服务,期间对TCS3200输出的信号进行采集和处理;设置另外一个定时器,捕获TCS3200的输出信号**(外部时钟源模式2,上升沿使计数器加一);第一次的检测用于白平衡,后续循环检测RGB**,每完成一组将RGB的值显示在OLED屏幕上

标准库下使用外部时钟源模式2

1. 通用定时器框图(部分)

在这里插入图片描述

回顾一下这个图,要想用外部时钟源模式2,信号的流向是这样子的。

可简单分为三个部分:

  • 外部时钟源模式2参数配置 (极性选择,边沿检测,预分频器,滤波器)
  • 从模式控制器配置(复位、使能、向上/下、计数)
  • 时基单元配置(TimeBase)

接下来根据信号的流向,讲解整个流程的配置

2. 配置外部时钟模式2

在这里插入图片描述

  • 首先从参考手册的描述中可知,设定该模式主要操作的是SMCR寄存器也就是所谓的从模式寄存器

  • 第二句话说明它的功能,即我们所需的功能

在这里插入图片描述

  • 框图: 对应第一部分

  • 调用的库函数
    在这里插入图片描述

TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x0);
  • 不分频,极性不翻转(高电平有效), 不滤波
3. 配置从模式
  • 在参考手册中,只对从模式中的四个做出详细的介绍

在这里插入图片描述

  • 但在手册对于定时器寄存器描述中,我们找到从模式控制寄存器(TIMx_SMCR)

在这里插入图片描述

  • 可以看到其实有八种模式可以配置,然后可以发现外部时钟模式1,刚好对应了我们框图中的信号流向,因此我们需要将从模式配置为外部时钟模式1,从模式的外部时钟模式1和时钟选择的外部时钟源模式1不同

  • 下面介绍需要使用和了解的库函数

    • 函数TIM_ITRxExternalClockConfig

在这里插入图片描述

    /**
      * @brief  Configures the TIMx Internal Trigger as External Clock
      * @param  TIMx: where x can be  1, 2, 3, 4, 5, 9, 12 or 15 to select the TIM peripheral.
      * @param  TIM_ITRSource: Trigger source.
      *   This parameter can be one of the following values:
      * @param  TIM_TS_ITR0: Internal Trigger 0
      * @param  TIM_TS_ITR1: Internal Trigger 1
      * @param  TIM_TS_ITR2: Internal Trigger 2
      * @param  TIM_TS_ITR3: Internal Trigger 3
      * @retval None
      */
    void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource)
    {
      /* Check the parameters */
      assert_param(IS_TIM_LIST6_PERIPH(TIMx));
      assert_param(IS_TIM_INTERNAL_TRIGGER_SELECTION(TIM_InputTriggerSource));
      /* Select the Internal Trigger */
      TIM_SelectInputTrigger(TIMx, TIM_InputTriggerSource);  // 选择输入触发的通道
      /* Select the External clock mode1 */
      TIMx->SMCR |= TIM_SlaveMode_External1;   // 内部使用了从模式的外部模式1
    }
  • 可以看到该函数无论是在库函数编程手册,还是在ST库的注释中,都只有4个参数可选择(但实际不是, 接着往下看)

  • 可以看到该函数内部调用了函数TIM_SelectInputTrigger

  • 函数TIM_SelectInputTrigger

在这里插入图片描述

 /**
   * @brief  Selects the Input Trigger source
   * @param  TIMx: where x can be  1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the TIM peripheral.
   * @param  TIM_InputTriggerSource: The Input Trigger source.
   *   This parameter can be one of the following values:
   *     @arg TIM_TS_ITR0: Internal Trigger 0
   *     @arg TIM_TS_ITR1: Internal Trigger 1
   *     @arg TIM_TS_ITR2: Internal Trigger 2
   *     @arg TIM_TS_ITR3: Internal Trigger 3
   *     @arg TIM_TS_TI1F_ED: TI1 Edge Detector
   *     @arg TIM_TS_TI1FP1: Filtered Timer Input 1
   *     @arg TIM_TS_TI2FP2: Filtered Timer Input 2
   *     @arg TIM_TS_ETRF: External Trigger input  // 我们要选的参数
   * @retval None
   */
 void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource)
 {
   uint16_t tmpsmcr = 0;
   /* Check the parameters */
   assert_param(IS_TIM_LIST6_PERIPH(TIMx));
   assert_param(IS_TIM_TRIGGER_SELECTION(TIM_InputTriggerSource));
   /* Get the TIMx SMCR register value */
   tmpsmcr = TIMx->SMCR;
   /* Reset the TS Bits */
   tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCR_TS));
   /* Set the Input Trigger source */
   tmpsmcr |= TIM_InputTriggerSource;
   /* Write to TIMx SMCR */
   TIMx->SMCR = tmpsmcr;
 }
  • 实际可调用参数有8个

  • 配置代码

TIM_ITRxExternalClockConfig(TIM2, TIM_TS_ETRF);
4. 配置时基单元(略)

至此,框图信号流动路线全部配置完毕,外部时钟源模式2即可使用

主要代码

TCS.h
#ifndef __TCS_H
#define __TCS_H
#include "stm32f10x.h"

/**
 * @breif TCS3200端口定义
 * 		  S0: PA4
 * 		  S1: PA5
 * 		  S2: PA6
 * 		  S3: PA7
 * 		  LED: PB0
 */
#define  S0_L 		GPIO_ResetBits(GPIOA, GPIO_Pin_4);
#define  S0_H       GPIO_SetBits(GPIOA, GPIO_Pin_4);

#define  S1_L       GPIO_ResetBits(GPIOA, GPIO_Pin_5);
#define  S1_H    	GPIO_SetBits(GPIOA, GPIO_Pin_5);

#define  S2_L       GPIO_ResetBits(GPIOA, GPIO_Pin_6);
#define  S2_H       GPIO_SetBits(GPIOA, GPIO_Pin_6);

#define  S3_L       GPIO_ResetBits(GPIOA, GPIO_Pin_7);
#define  S3_H       GPIO_SetBits(GPIOA, GPIO_Pin_7);

#define  LED_OFF    GPIO_ResetBits(GPIOB, GPIO_Pin_0);
#define  LED_ON     GPIO_SetBits(GPIOB, GPIO_Pin_0);

extern float RGB_Scale[3];  // R、G、B 比例因子
extern uint16_t count;  // 脉冲计数
extern uint16_t cnt[3]; // RGB 三种颜色的脉冲数

// 频率选择
typedef enum
{
	TCS_2Percentage = 0x01,
	TCS_20Percentage = 0x02,
	TCS_100Percentage = 0x03,
	TCS_Frequent_OFF = 0x04
}TCS_FrequentTypeDef;

// 滤波器
typedef enum
{
	TCS_Filter_Red = 0x01,
	TCS_Filter_Blue = 0x02,
	TCS_Filter_Green = 0x03,
	TCS_Filter_None = 0x04
} TCS_FilterTypeDef;

void TCS_Init(void);
void TCS_FrequentKeyer(TCS_FrequentTypeDef TCS_Frequent);

#endif

TCS.c
#include "stm32f10x.h"
#include "MyNVIC.h"
#include "TCS.h"

float RGB_Scale[3];  // R、G、B 比例因子
uint16_t count;  // 脉冲计数
uint16_t cnt[3]; // RGB 三种颜色的脉冲数
static TCS_FilterTypeDef flag = TCS_Filter_None;  // 滤波器选择模式标志

/**
 *  @brief 颜色识别端口初始化  PA 4 5 6 7;  PB 0 
 */
void TCS_PortInit(void)
{
	// RCC
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);	
	// GPIO  S0-S3(PA4-7) 用来控制TCS3200工作模式 配置为通用推挽输出
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	// LED(PB0) 用来控制TCS3200的LED的亮灭 配置为通用推挽输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
}	

/**
 * @brief TIM1 初始化 用于计时 定时时间为1s
 */
void TCS_TIM1_Init(void)
{
	// RCC
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
	
	// TimeBase
	TIM_TimeBaseInitTypeDef TimeBase_InitStructure;
	TimeBase_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TimeBase_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TimeBase_InitStructure.TIM_Period = 10000-1; // ARR
	TimeBase_InitStructure.TIM_Prescaler = 7200-1; // PSC
	TimeBase_InitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM1, &TimeBase_InitStructure);
	
	// NVIC
	MyNVIC_TIM1_Config();
	
	// 开启中断
	TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);
	
	TIM_Cmd(TIM1, ENABLE);
}

/**
 *  @brief TIM2 初始化 外部时钟模式 用于捕获TCS3200 OUT口的信号 PA0信号输入口 TIM_ETR
 */
void TCS_TIM2_Init(void)
{
	// RCC
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	// GPIO
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	GPIO_ResetBits(GPIOA, GPIO_Pin_0);  // 拉倒低电平
	
	// TimeBase
	TIM_TimeBaseInitTypeDef TimeBase_InitStructure;
	TimeBase_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TimeBase_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TimeBase_InitStructure.TIM_Period = 0xFFFF; // ARR  65535
	TimeBase_InitStructure.TIM_Prescaler = 0;  // PSC
	TimeBase_InitStructure.TIM_RepetitionCounter=0;
	TIM_TimeBaseInit(TIM2, &TimeBase_InitStructure);
	
	// Select the clock source  选择时钟源
	TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x0);
	TIM_ITRxExternalClockConfig(TIM2, TIM_TS_ETRF);
	TIM_SetCounter(TIM2, 0);  // 将CNT置零
	
	TIM_Cmd(TIM2, ENABLE);  // 开启定时器
}

/**
 *  @brief 频率调制	
 *
 *  @param TCS_FrequentTypeDef:  TCS_2Percentage TCS_20Percentage TCS_100Percentage TCS_Frequent_OFF
 */
void TCS_FrequentKeyer(TCS_FrequentTypeDef TCS_Frequent)
{
	switch(TCS_Frequent)
	{	
		case TCS_2Percentage:
			S0_L;
			S1_H;
			break;
		case TCS_20Percentage:
			S0_L;
			S1_H;
			break;
		case TCS_100Percentage:
			S0_H;
			S1_H;
			break;
		case TCS_Frequent_OFF:
			S0_L;
			S1_L;
			break;
		default:
			break;
	}
}

/**
 *  @brief 选择滤波器
 *  @param TCS_Filter: TCS_Filter_Red TCS_Filter_Blue TCS_Filter_Green TCS_Filter_None 
 */
void TCS_SelectFilter(TCS_FilterTypeDef TCS_Filter)
{
	flag = TCS_Filter;  // 更新标志位
	switch(TCS_Filter)
	{
		case TCS_Filter_Red:
			S2_L;
			S3_L;
			break;
		case TCS_Filter_Blue:
			S2_L;
			S3_H;
			break;
		case TCS_Filter_Green:
			S2_H;
			S3_H;
			break;
		case TCS_Filter_None:
			S2_H;
			S3_L;
			break;
		default:
			break;
	}
}

/**
 * @brief TCS3200初始化 初始化端口 和两个用到的定时器 
 */
void TCS_Init(void)
{
	TCS_PortInit();   // 控制端口
	TCS_TIM1_Init();  // 定时计时器
	TCS_TIM2_Init();  // 捕获脉冲数 包括输入端口初始化 
	TCS_FrequentKeyer(TCS_Frequent_OFF);  // 频率调制器断电
	TCS_SelectFilter(TCS_Filter_None);  // 关闭TCS滤波器
	LED_OFF;  // 关闭LED
}

/**
 * @brief TIM1更新中断
 */
void TIM1_UP_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM1, TIM_IT_Update))
	{
		count = TIM_GetCounter(TIM2);  // 读取脉冲数
		// 依次读取 RGB三种颜色的值
		switch(flag)
		{
			case TCS_Filter_None:
				count = 0;
				TCS_SelectFilter(TCS_Filter_Red);  // 选择红色滤波器
				break;
			case TCS_Filter_Red:
				cnt[0] = count;  
				TCS_SelectFilter(TCS_Filter_Green);  // 选择绿色滤波器
				break;
			case TCS_Filter_Green:
				cnt[1] = count;
				TCS_SelectFilter(TCS_Filter_Blue);  // 选择蓝色滤波器
				break;
			case TCS_Filter_Blue:
				cnt[2] = count;
				TCS_SelectFilter(TCS_Filter_None);  // 关闭滤波器
				break;
			default:
				break;
		}
		// 将TIM2的计数器清零
		TIM_SetCounter(TIM2, 0);
		
		// 清除标志位
		TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
	}
}

MyNVIC.h
#ifndef __MyNVIC_H
#define __MyNVIC_H

void MyNVIC_TIM1_Config(void);

#endif

MyNVIC.c
#include "stm32f10x.h"

/**
 * @brief TIM1 中断向量嵌套配置 
 */
void MyNVIC_TIM1_Config(void)
{
	NVIC_SetPriorityGrouping(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
	
	NVIC_Init(&NVIC_InitStructure);

}

main.c
#include "stm32f10x.h" 
#include "delay.h"  // 江科大对应的驱动
#include "OLED.h"  // 江科大对应的驱动
#include "TCS.h"
int main(void)
{
	OLED_Init();
	TCS_Init();  // 初始化TCS3200
	
	TCS_FrequentKeyer(TCS_2Percentage);  // 选择输出频率
	// 这里选2% 因为计数器最多到65535 
	// 若选20%最高输出120kHz 120000 当检测时长为1s时会超出计数器的范围
	// 但输出频率越高,结果越精确
	// 感兴趣的可以尝试两个定时器级联 扩大计数范围
	LED_ON;  // LED 开
	
	// 第一次获得的参数 进行白平衡 
	Delay_ms(8000);  // 延时8s,两轮检测确保白平衡的进行
	RGB_Scale[0] = 255.0/cnt[0];  // Get Red Scale
	RGB_Scale[1] = 255.0/cnt[1];  // Get Green Scale
	RGB_Scale[2] = 255.0/cnt[2];  // Get Blue Scale
	
	while(1)
	{
		Delay_ms(4000);
		OLED_ShowString(1, 1, "R:");
		OLED_ShowNum(1, 3, cnt[0]*RGB_Scale[0], 3);
		OLED_ShowString(2, 1, "G:");
		OLED_ShowNum(2, 3, cnt[1]*RGB_Scale[1], 3);
		OLED_ShowString(3, 1, "B:");
		OLED_ShowNum(3, 3, cnt[2]*RGB_Scale[2], 3);
	}
}

效果展示

【TCS3200颜色识别模块】

参考资料

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

肝了一下午,学会TCS3200颜色识别——基于STM32,分享一波

高分辨颜色传感器TCS230的原理与应用

TCS3200.pdf (DataSheet)

STM32F10xxx参考手册(中文).pdf

  • 3
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
TCS3200颜色传感器概述: TCS3200颜色传感器是一款全彩的颜色检测器,包括了一块TAOS TCS3200RGB感应芯片和4个白光LED灯,TCS3200能在一定的范围内检测和测量几乎所有的可见光。它适合于色度计测量应用领域。比如彩色打印、医疗诊断、计算机彩色监视器校准以及油漆、纺织品、化妆品和印刷材料的过程控制。 通常所看到的物体颜色,实际上是物体表面吸收了照射到它上面的白光(日光)中的一部分有色成分,而反射出的另一部分有色光在人眼中的反应。白色是由各种频率的可见光混合在一起构成的,也就是说白光中包含着各种颜色的色光(如红R、黄Y、绿G、青V、蓝B、紫P)。根据德国物理学家赫姆霍兹(Helinholtz)的三原色理论可知,各种颜色是由不同比例的三原色(红、绿、蓝)混合而成的。 由上面的三原色感应原理可知,如果知道构成各种颜色的三原色的值,就能够知道所测试物体的颜色。对于TCS3200D 来说,当选定一个颜色滤波器时,它只允许某种特定的原色通过,阻止其它原色的通过。例如:当选择红色滤波器时,入射光中只有红色可以通过,蓝色和绿色都被阻止,这样就可以得到红色光的光强;同理,选择其它的滤波器,就可以得到蓝色光和绿色光的光强。通过这三个光强值,就可以分析出反射到TCS3200D传感器上的光的颜色。 TCS3200颜色传感器实物展示: TCS3200颜色传感器描述: 感应芯片:TCS3200(全彩颜色检测器) 静态识别物体颜色,不同颜色输出不同频率方波 支持LED灯补光控制 TCS3200颜色传感器参数: 工作电压:2.7V ~ 5.5V 推荐检测距离:10mm 尺寸:36.0mm * 20.6mm 固定孔尺寸:2.0mm TCS3200颜色传感器主要用途: 颜色排序、感应与校准环境光、测试条阅读和颜色匹配等。 接口说明:(以接入MCU为例) VCC:接2.7V ~ 5.5V GND:接电源地 LED:接MCU.IO (控制四个白色LED灯的状态) OUT:接MCU.IO (RGB三原色对应的输出频率) S0/S1:接MCU.IO (选择不同的输出比例因子) S2/S3:接MCU.IO (选择不同色光的滤波器) 操作说明: S0/S1选择输出频率的比例因子,S2/S3依次选择三原色的滤波器类型,此时OUT端口输出的就是相应三原色的频率,与RGB颜色对照表比对即可得到所测物体的颜色。 注意: 颜色识别时要避免外界光线的干扰 首次使用该模块模块重启或更换光源时,需进行白平衡调整 相关技术资料: 如何进行TCS3200各控制引脚与Arduino控制器的硬件连线问题,详见链接:https://www.eefocus.com/zhang700309/blog/13-08/2963... 用TCS3200D做颜色识别时,如何将测得的脉冲数转换为RGB的值?链接:https://wenda.so.com/q/1367943564064205 实物购买链接:https://www.waveshare.net/shop/Color-Sensor.htm
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值