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

前言

不得不说,这颜色模块还挺有趣的,早上起床我就有想法想要把它实现了,之前一直把这模块压箱里了,本以为电赛要用到,结果材料清单无,所以就战略性放弃,现在才想起来有这个模块哈哈,就顺手拿来玩玩,其实对于TCS3200这个模块,还是比较不错的一款识别颜色,但是如果对颜色识别要求较高就不建议入手,这款识别模块抗干扰能力还是强的,是TCS230的升级版吧,具体下面再一一介绍。

另外就是发现关于这款模块的博文少,而且基于库函数的适用STM32f1的几乎没有,有的也是收费资源,因此就有了以下文章的问世哈哈

当然也有一篇基于HAL库的文章,同样在上面受益匪浅,推荐给大家:

基于STM32F103的TCS3200颜色传感器的使用_weixin_50950634的博客-CSDN博客

肝了一下午,学会TCS3200颜色识别——基于STM32,分享一波!_第1张图片 

一、TCS3200如何用?

这里老规矩,还是讲一下TCS3200颜色识别模块怎么使用,首先,了解一下它有几个接口

肝了一下午,学会TCS3200颜色识别——基于STM32,分享一波!_第2张图片肝了一下午,学会TCS3200颜色识别——基于STM32,分享一波!_第3张图片 

 上面两张图片已经很好地说明了,该模块含有8个引脚,即VCC、GND、S0、S1、S2、S3、LED(OE)、OUT,实际上在原理图上写了EO,但在实物图上并没有看到EO接口,只有LED接口,所以我就“自作主张”修改了一下,方便大家学习哈哈,这里是原理图,实物图会额外多出两个引脚(VCC、GND),那么这些引脚作用是什么呢?自问自答来了

S0、S1是一对情侣,S2、S3也是一对情侣,LED和OUT就两电灯泡

那么首先我们要如何定义这些端口呢,毋庸置疑,S0~S3全部推挽输出,LED推挽输出,OUT就下拉输入即可,怎么接比较好呢,除了OUT要设置在定时器的外部触发输入口(ETR),这里选用的是PA0(TIM2-ETR),其他接口无特别要求。测试时与被测物体保持在1cm时最佳。

先说明一下接线问题,因为我的博文主要还是以实际操作为主,理论部分较少,直接让你上手,理论后面再补哈哈

S0~S3分别接PA4~PA7,LED接PC5,OUT接PA0

那么认识认识它长怎么样吧?

肝了一下午,学会TCS3200颜色识别——基于STM32,分享一波!_第4张图片

是不是很酷炫哈哈

二、实现原理

那么这到底是如何实现的,接下来一探到底。

肝了一下午,学会TCS3200颜色识别——基于STM32,分享一波!_第5张图片

肝了一下午,学会TCS3200颜色识别——基于STM32,分享一波!_第6张图片

肝了一下午,学会TCS3200颜色识别——基于STM32,分享一波!_第7张图片

 以上奉行的是拿来主义哈哈,其实是淘宝商家给的。这里比较详细地介绍了它的主要工作原理,大家在学习过程中可以多次返回来学习,肯定会有用的。

下面是S0~S3分别在高低电平下代表的意义(L表示低电平,H表示高电平

肝了一下午,学会TCS3200颜色识别——基于STM32,分享一波!_第8张图片

 这里我们可以看到四种模式,在测试时,按红绿蓝清除的顺序进行

肝了一下午,学会TCS3200颜色识别——基于STM32,分享一波!_第9张图片

 这里可以看到四种情况,双L下不启动,其他按比例因子情况启动

后面我选择的是2%,参照另一位博主的,大家也可以自行更改。

当然在进行测试之前,一定要进行白平衡校准,即每次运行前拿一个白色物体放在模块前进行第一次识别,之后就可以识别其他颜色了,白平衡等到的R值G值B值均为255。之后就可以开始测试了。

肝了一下午,学会TCS3200颜色识别——基于STM32,分享一波!_第10张图片 

 

三、测试实现程序

TCS3200函数:

#include "tcs3200.h"
#include "delay.h"
#include "usart.h"
#include "lcd.h"

float RGB_Scale[3];         
int count=0;              
int cnt[3];             
int flag=0; 

//S0-----PA4,S1-----PA5,S2-----PA6,S3-----PA7,LED-----PC5,OUT-----PA0

void TCS_GPIO_Init(void)
{
 
 GPIO_InitTypeDef  GPIO_InitStructure;
 	
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC, ENABLE);	 
	
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;				 
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 
 GPIO_Init(GPIOA, &GPIO_InitStructure);					
 GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_4|GPIO_Pin_7);						 //PA.4567 Êä³ö¸ß
				
	
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;	    	
 GPIO_Init(GPIOC, &GPIO_InitStructure);	  				
 GPIO_SetBits(GPIOC,GPIO_Pin_5); 					
}

void filter(int s2,int 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 ++;   
  filter(s2, s3); 
}

定时器函数:

#include "timer.h"
#include "led.h"
#include "usart.h"
#include "tcs3200.h"
#include "lcd.h"

extern float RGB_Scale[3];                    
extern int cnt[3];             
extern int flag;
extern int count;

void TIM3_Int_Init(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); 

	TIM_TimeBaseStructure.TIM_Period = arr; 
	TIM_TimeBaseStructure.TIM_Prescaler =psc;  
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; 
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); 
 
	TIM_ITConfig(  
		TIM3, //TIM2
		TIM_IT_Update  | TIM_IT_Trigger, 
		ENABLE  
		);
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; 
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);  

	TIM_Cmd(TIM3, ENABLE);  //ʹÄÜTIMxÍâÉè
							 
}


void TIM2_Cap_Init(void)                                        
{    
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
 
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);   
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  
    
    GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;             
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;         
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_ResetBits(GPIOA,GPIO_Pin_0);                 
    
	
    TIM_TimeBaseStructure.TIM_Period = 0xFFFF;          
    TIM_TimeBaseStructure.TIM_Prescaler =0;           
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; 
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);        
    TIM_ITRxExternalClockConfig(TIM2,TIM_TS_ETRF);         
    TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0);
    TIM_SetCounter(TIM2, 0);        
    
    TIM_Cmd(TIM2,ENABLE );                            
}

void TIM3_IRQHandler(void)   
{
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) 
		{
	      TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  
	      count=TIM_GetCounter(TIM2);  
			
         switch(flag){
         case 0:
            TSC_WB(0, 0);   
            break;
         case 1:
            cnt[0] = count;    
            TSC_WB(1, 1); 
            break;
         case 2:
            cnt[1] = count;    
            TSC_WB(0, 1);  
            break;
         case 3:
            cnt[2] = count;     
            TSC_WB(1, 0);    
            break;
         default:
            count = 0;     
            break;
      }
			
      TIM_SetCounter(TIM2,0);

		}
}

 最后主函数:

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "lcd.h"
#include "tcs3200.h"
#include "timer.h"

extern float RGB_Scale[3];       //外部声明             
extern int cnt[3];             
extern int flag;
extern int count;

 int main(void)
 {		
	delay_init();	    	   
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	uart_init(115200);	 	
	LED_Init();		  		
	LCD_Init();			 
	TCS_GPIO_Init();	
	TIM3_Int_Init(9999,719);//100ms
	TIM2_Cap_Init();
	
 	POINT_COLOR=RED;	
	 
	S0_L;//这里直接2%设置,LED永远亮着即可
    S1_H;    
    LED_ON;
	delay_ms(8000);
	 
    RGB_Scale[0] = 255.0/ cnt[0];    
    RGB_Scale[1] = 255.0/ cnt[1] ;   
    RGB_Scale[2] = 255.0/ cnt[2] ;  
	LCD_ShowString(10,10,210,16,16,"Init"); 
	LCD_ShowString(20,70,210,16,16,"R:");
	LCD_ShowString(20,90,210,16,16,"G:"); 
	LCD_ShowString(20,110,210,16,16,"B:"); 
	LCD_ShowNum(50, 10,(int)(cnt[0]*RGB_Scale[0]),3,16);
	LCD_ShowNum(50, 30,(int)(cnt[1]*RGB_Scale[1]),3,16);
	LCD_ShowNum(50, 50,(int)(cnt[2]*RGB_Scale[2]),3,16);

	 //白平衡结束
	POINT_COLOR=BLUE;	

	while(1)
	{
		flag=0;  
		count=0;   
    delay_ms(10000); 
	LCD_ShowNum(50, 70,(int)(cnt[0]*RGB_Scale[0]),3,16);
	LCD_ShowNum(50, 90,(int)(cnt[1]*RGB_Scale[1]),3,16);
	LCD_ShowNum(50, 110,(int)(cnt[2]*RGB_Scale[2]),3,16);
        
 } 


}

 

 四、结果展示

白平衡结束后,我选用了一个青绿色纸盒进行测试,得到RGB值

肝了一下午,学会TCS3200颜色识别——基于STM32,分享一波!_第11张图片

 RGB值如下:76、96、80

肝了一下午,学会TCS3200颜色识别——基于STM32,分享一波!_第12张图片

 在自带的画图软件上查询是否准确

肝了一下午,学会TCS3200颜色识别——基于STM32,分享一波!_第13张图片

 基本上误差不大,但是要说多么精准也没有哈哈,不过简单的识别还是可以做到的,不错,我又试了一个红色和粉色的,那个识别就比较准确。

五、总结

本来我想着直接拿来主义直接理解一波就行了,没想到网上资料少得可怜,拿来主义行不通,商家给的也只有51程序,所以没办法,只得自己手动敲代码了,刚开始那是毫无头绪,但是在看了其他优秀博文后,渐渐就有了思路,就开始上手了,其实不难,但是贵在坚持,肯定会有很多bug等着你,但是成功是给坚持到底的人的,遇到不懂及时查找资料解决,就算做不出来,也肯定会有收获。加油!

那么老规矩,觉得文章写的还可以的记得给点一下赞,收藏一下,说不定以后用得上呢哈哈

题外话:

挺喜欢彭于晏说的一句话:“我就是没有才华,所以才用命去拼!”

学习32之路固然辛苦,但要是坚持下来了,那不是很酷?哈哈哈

你可能感兴趣的:(STM32f1库函数版,stm32,单片机,经验分享,传感器,c语言)