STM32 HAL庫快速實戰【十】《顏色傳感器的使用》--基於黑龍江科技大學機電工業機器人實訓


系列目錄

點擊展開

模塊介紹

image

TCS34725是一款低成本,高性價比的RGB全彩顏色識別傳感器,傳感器通過光學感應來識別物體的表面顏色。支持紅、綠、藍(RGB)三基色,支持明光感應,可以輸出對應的具體數值,幫助您還原顏色本真。 為了提高精度,防止周邊環境干擾,我們特意在傳感器底部添加了一塊紅外遮光片,最大程度減小了入射光的紅外頻譜成份,讓顏色管理更加准確。板載自帶高亮LED,可以讓傳感器在低環境光的情況下依然能夠正常使用,實現“補光”的功能。模塊采用I2C通信。

接線

直接接到SD1,SA1接口上。

CubeMX配置

采用GPIO模擬I2C。PA0,PA1都配置成推挽輸出,高速模式,默認無輸出。

點擊查看具體配置

編寫代碼

該模塊采用IIC協議通訊,需要大量的地址讀寫操作,這里不一一贅述,這里直接使用從眾靈科技官方代碼移植的驅動代碼。
新建color.c和color.h,將一下驅動代碼復制進對應文件,添加進工程。

color.c
#include "color.h"

COLOR_RGBC rgb;
COLOR_HSL  hsl;

/******************************************************************************/
void delay_s(uint32_t i)
{
	while(i--);
}
/******************************************************************************/
void TCS34725_I2C_Init()
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	GPIO_InitStruct.Pin = TCS_SDA_Pin|TCS_SCL_Pin;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
	HAL_GPIO_WritePin(GPIOA, TCS_SDA_Pin|TCS_SCL_Pin, GPIO_PIN_SET);
	
}
/*********************************************/
void TCS34725_I2C_Start()
{
	TCS_SDA_OUT();
	TCS_SDA_H;
	TCS_SCL_H;
	delay_s(40);//delay_us(4);
	TCS_SDA_L;
	delay_s(40);//delay_us(4);
	TCS_SCL_L;
}
/*********************************************/
void TCS34725_I2C_Stop()
{
	TCS_SDA_OUT();
	TCS_SCL_L;
	TCS_SDA_L;
	delay_s(40);//delay_us(4);
	TCS_SCL_H;
	TCS_SDA_H;
	delay_s(40);//delay_us(4);							   	
}
/*********************************************/
//返回值:1,接收應答失敗
//        0,接收應答成功
uint8_t TCS34725_I2C_Wait_ACK()
{
	uint32_t t=0;
	
	TCS_SDA_IN();//SDA設置為輸入  
	TCS_SDA_H; 
	delay_s(10);//delay_us(1);
	TCS_SCL_H; 
	delay_s(10);//delay_us(1);
	while(TCS_SDA_READ)
	{
		t++;
		if(t > 250)
		{
			TCS34725_I2C_Stop();
			return 1;
		}
	}
	TCS_SCL_L;
	return 0;	
}
/*********************************************/
//產生ACK應答
void TCS34725_I2C_ACK()
{
	TCS_SCL_L;
	TCS_SDA_OUT();//sda線輸出
	TCS_SDA_L;
	delay_s(20);//delay_us(2);
	TCS_SCL_H;
	delay_s(20);//delay_us(2);
	TCS_SCL_L;
}
/*********************************************/
//不產生ACK應答		    
void TCS34725_I2C_NACK()
{
	TCS_SCL_L;
	TCS_SDA_OUT();//sda線輸出
	TCS_SDA_H;
	delay_s(20);//delay_us(2);
	TCS_SCL_H;
	delay_s(20);//delay_us(2);
	TCS_SCL_L;
}
/*********************************************/
//I2C發送一個字節		  
void TCS34725_I2C_Send_Byte(uint8_t byte)
{
	uint8_t i;
	
	TCS_SDA_OUT();//sda線輸出
	TCS_SCL_L;//拉低時鍾開始數據傳輸
	for(i = 0; i < 8; i++)
	{
		if(((byte&0x80)>>7)==1)TCS_SDA_H;
		else
			TCS_SDA_L;
		byte <<= 1;
		
		delay_s(20);//delay_us(2);
		TCS_SCL_H;
		delay_s(20);//delay_us(2);
		TCS_SCL_L;
		delay_s(20);//delay_us(2);
	} 
}
/*********************************************/
//讀1個字節,ack=1時,發送ACK,ack=0,發送nACK   
uint8_t TCS34725_I2C_Read_Byte(uint8_t ack)
{
	uint8_t i,receive = 0;
	
	TCS_SDA_IN();
	for(i = 0; i < 8; i++)
	{
		TCS_SCL_L;
		delay_s(20);//delay_us(2);
		TCS_SCL_H;
		receive <<= 1;
		if(TCS_SDA_READ) receive++;
		delay_s(10);//delay_us(1);
	}
	if (!ack) TCS34725_I2C_NACK();//發送nACK
	else TCS34725_I2C_ACK(); //發送ACK 
	
	return receive;
}
/*********************************************/
/*******************************************************************************
 * @brief Writes data to a slave device.
 *
 * @param slaveAddress - Adress of the slave device.
 * @param dataBuffer - Pointer to a buffer storing the transmission data.
 * @param bytesNumber - Number of bytes to write.
 * @param stopBit - Stop condition control.
 *                  Example: 0 - A stop condition will not be sent;
 *                           1 - A stop condition will be sent.
*******************************************************************************/
void TCS34725_I2C_Write(uint8_t slaveAddress, uint8_t* dataBuffer,uint8_t bytesNumber, uint8_t stopBit)
{
	uint8_t i = 0;
	
	TCS34725_I2C_Start();
	TCS34725_I2C_Send_Byte((slaveAddress << 1) | 0x00);	   //發送從機地址寫命令
	TCS34725_I2C_Wait_ACK();
	for(i = 0; i < bytesNumber; i++)
	{
		TCS34725_I2C_Send_Byte(*(dataBuffer + i));
		TCS34725_I2C_Wait_ACK();
	}
	if(stopBit == 1) TCS34725_I2C_Stop();
}
/*******************************************************************************
 * @brief Reads data from a slave device.
 *
 * @param slaveAddress - Adress of the slave device.
 * @param dataBuffer - Pointer to a buffer that will store the received data.
 * @param bytesNumber - Number of bytes to read.
 * @param stopBit - Stop condition control.
 *                  Example: 0 - A stop condition will not be sent;
 *                           1 - A stop condition will be sent.
*******************************************************************************/
void TCS34725_I2C_Read(uint8_t slaveAddress, uint8_t* dataBuffer, uint8_t bytesNumber, uint8_t stopBit)
{
	uint8_t i = 0;
	
	TCS34725_I2C_Start();
	TCS34725_I2C_Send_Byte((slaveAddress << 1) | 0x01);	   //發送從機地址讀命令
	TCS34725_I2C_Wait_ACK();
	for(i = 0; i < bytesNumber; i++)
	{
		if(i == bytesNumber - 1)
		{
			*(dataBuffer + i) = TCS34725_I2C_Read_Byte(0);//讀取的最后一個字節發送NACK
		}
		else
		{
			*(dataBuffer + i) = TCS34725_I2C_Read_Byte(1);
		}
	}
	if(stopBit == 1) TCS34725_I2C_Stop();
}
/*******************************************************************************
 * @brief Writes data into TCS34725 registers, starting from the selected
 *        register address pointer.
 *
 * @param subAddr - The selected register address pointer.
 * @param dataBuffer - Pointer to a buffer storing the transmission data.
 * @param bytesNumber - Number of bytes that will be sent.
 *
 * @return None.
*******************************************************************************/
void TCS34725_Write(uint8_t subAddr, uint8_t* dataBuffer, uint8_t bytesNumber)
{
    uint8_t sendBuffer[10] = {0, };
    uint8_t byte = 0;
    
    sendBuffer[0] = subAddr | TCS34725_COMMAND_BIT;
    for(byte = 1; byte <= bytesNumber; byte++)
    {
        sendBuffer[byte] = dataBuffer[byte - 1];
    }
	TCS34725_I2C_Write(TCS34725_ADDRESS, sendBuffer, bytesNumber + 1, 1);
}
/*******************************************************************************
 * @brief Reads data from TCS34725 registers, starting from the selected
 *        register address pointer.
 *
 * @param subAddr - The selected register address pointer.
 * @param dataBuffer - Pointer to a buffer that will store the received data.
 * @param bytesNumber - Number of bytes that will be read.
 *
 * @return None.
*******************************************************************************/
void TCS34725_Read(uint8_t subAddr, uint8_t* dataBuffer, uint8_t bytesNumber)
{
	subAddr |= TCS34725_COMMAND_BIT;
	
	TCS34725_I2C_Write(TCS34725_ADDRESS, (uint8_t*)&subAddr, 1, 0);
	TCS34725_I2C_Read(TCS34725_ADDRESS, dataBuffer, bytesNumber, 1);
}
/*******************************************************************************
 * @brief TCS34725設置積分時間
 *
 * @return None
*******************************************************************************/
void TCS34725_SetIntegrationTime(uint8_t time)
{
	TCS34725_Write(TCS34725_ATIME, &time, 1);
}
/*******************************************************************************
 * @brief TCS34725設置增益
 *
 * @return None
*******************************************************************************/
void TCS34725_SetGain(uint8_t gain)
{
	TCS34725_Write(TCS34725_CONTROL, &gain, 1);
}
/*******************************************************************************
 * @brief TCS34725使能
 *
 * @return None
*******************************************************************************/
void TCS34725_Enable(void)
{
	uint8_t cmd = TCS34725_ENABLE_PON;
	
	TCS34725_Write(TCS34725_ENABLE, &cmd, 1);
	cmd = TCS34725_ENABLE_PON | TCS34725_ENABLE_AEN;
	TCS34725_Write(TCS34725_ENABLE, &cmd, 1);
	//delay_s(600000);//delay_ms(3);//延時應該放在設置AEN之后
}
/*******************************************************************************
 * @brief TCS34725失能
 *
 * @return None
*******************************************************************************/
void TCS34725_Disable(void)
{
	uint8_t cmd = 0;
	
	TCS34725_Read(TCS34725_ENABLE, &cmd, 1);
	cmd = cmd & ~(TCS34725_ENABLE_PON | TCS34725_ENABLE_AEN);
	TCS34725_Write(TCS34725_ENABLE, &cmd, 1);
}

void TCS34725_LedON(uint8_t enable) {
	uint8_t cmd = 0;
	TCS34725_Read(TCS34725_ENABLE, &cmd, 1);
	if(enable) {
		cmd |= TCS34725_ENABLE_AIEN;
	} else {
		cmd &= ~TCS34725_ENABLE_AIEN;
	}
	TCS34725_Write(TCS34725_ENABLE, &cmd, 1);
}

/*******************************************************************************
 * @brief TCS34725初始化
 *
 * @return ID - ID寄存器中的值
*******************************************************************************/
uint8_t TCS34725_Init(uint8_t time,uint8_t gain)
{
	uint8_t id=0;
	uint8_t cmd_return[100];
	TCS34725_I2C_Init(); 
	TCS34725_Read(TCS34725_ID, &id, 1);  //TCS34725 的 ID 是 0x44 可以根據這個來判斷是否成功連接
	sprintf((char *)cmd_return, "{id=%x\r\n}", id);
	usart_send_str(&huart3,cmd_return);
	if(id==0x44)
		{
			TCS34725_SetIntegrationTime(time);
			TCS34725_SetGain(gain);
			TCS34725_Enable();
			return 1;
		}
	return 0;
}
/*******************************************************************************
 * @brief TCS34725獲取單個通道數據
 *
 * @return data - 該通道的轉換值
*******************************************************************************/
uint16_t TCS34725_GetChannelData(uint8_t reg)
{
	uint8_t tmp[2] = {0,0};
	uint16_t data;
	
	TCS34725_Read(reg, tmp, 2);
	data = (tmp[1] << 8) | tmp[0];
	
	return data;
}
/*******************************************************************************
 * @brief TCS34725獲取各個通道數據
 *
 * @return 1 - 轉換完成,數據可用
 *   	   0 - 轉換未完成,數據不可用
*******************************************************************************/
uint8_t TCS34725_GetRawData(COLOR_RGBC *rgbc)
{
	uint8_t status = TCS34725_STATUS_AVALID;
	
	TCS34725_Read(TCS34725_STATUS, &status, 1);
	
	if(status & TCS34725_STATUS_AVALID)
	{
		rgbc->c = TCS34725_GetChannelData(TCS34725_CDATAL);	
		rgbc->r = TCS34725_GetChannelData(TCS34725_RDATAL);	
		rgbc->g = TCS34725_GetChannelData(TCS34725_GDATAL);	
		rgbc->b = TCS34725_GetChannelData(TCS34725_BDATAL);
		return 1;
	}
	return 0;
}

uint16_t TCS34725_GetR(void) {
//	COLOR_RGBC rgbc;
	uint8_t status = TCS34725_STATUS_AVALID;
	
	TCS34725_Read(TCS34725_STATUS, &status, 1);
	
	if(status & TCS34725_STATUS_AVALID){
		return TCS34725_GetChannelData(TCS34725_RDATAL);	
	}
	return 0;
}

uint16_t TCS34725_GetG(void) {
//	COLOR_RGBC rgbc;
	uint8_t status = TCS34725_STATUS_AVALID;
	
	TCS34725_Read(TCS34725_STATUS, &status, 1);
	
	if(status & TCS34725_STATUS_AVALID){
		return TCS34725_GetChannelData(TCS34725_GDATAL);	
	}
	return 0;
}

uint16_t TCS34725_GetB(void) {
//	COLOR_RGBC rgbc;
	uint8_t status = TCS34725_STATUS_AVALID;
	
	TCS34725_Read(TCS34725_STATUS, &status, 1);
	
	if(status & TCS34725_STATUS_AVALID){
		return TCS34725_GetChannelData(TCS34725_BDATAL);
	}
	return 0;
}

uint16_t TCS34725_GetC(void) {
//	COLOR_RGBC rgbc;
	uint8_t status = TCS34725_STATUS_AVALID;
	
	TCS34725_Read(TCS34725_STATUS, &status, 1);
	
	if(status & TCS34725_STATUS_AVALID){
		return TCS34725_GetChannelData(TCS34725_CDATAL);	
	}
	return 0;
}


/******************************************************************************/
//RGB轉HSL
void RGBtoHSL(COLOR_RGBC *Rgb, COLOR_HSL *Hsl)
{
	uint8_t maxVal,minVal,difVal;
	uint8_t r = Rgb->r*100/Rgb->c;   //[0-100]
	uint8_t g = Rgb->g*100/Rgb->c;
	uint8_t b = Rgb->b*100/Rgb->c;
	
	maxVal = max3v(r,g,b);
	minVal = min3v(r,g,b);
	difVal = maxVal-minVal;
	
	//計算亮度
	Hsl->l = (maxVal+minVal)/2;
	
	if(maxVal == minVal)//若r=g=b,灰度
	{
		Hsl->h = 0; 
		Hsl->s = 0;
	}
	else
	{
		//計算色調
		if(maxVal==r)
		{
			if(g>=b)
				Hsl->h = 60*(g-b)/difVal;
			else
				Hsl->h = 60*(g-b)/difVal+360;
		}
		else
			{
				if(maxVal==g)Hsl->h = 60*(b-r)/difVal+120;
				else
					if(maxVal==b)Hsl->h = 60*(r-g)/difVal+240;
			}
		
		//計算飽和度
		if(Hsl->l<=50)Hsl->s=difVal*100/(maxVal+minVal);  //[0-100]
		else
			Hsl->s=difVal*100/(200-(maxVal+minVal));
	}
}

color.h
#ifndef __Z_COLOR_H__
#define __Z_COLOR_H__
#include "stdint.h"
#include "gpio.h"
#include "motor.h"
/******************************************************************************/
#define TCS_SCL_PIN 		GPIO_PIN_1
#define TCS_SDA_PIN 		GPIO_PIN_0
#define TCS_SDA_GPIO		GPIOA
#define TCS_SCL_GPIO		GPIOA
#define TCS_GPIO			GPIOA



#define TCS34725_ADDRESS          (0x29)
 
#define TCS34725_COMMAND_BIT      (0x80)
 
#define TCS34725_ENABLE           (0x00)
#define TCS34725_ENABLE_AIEN      (0x10)    /* RGBC Interrupt Enable */
#define TCS34725_ENABLE_WEN       (0x08)    /* Wait enable - Writing 1 activates the wait timer */
#define TCS34725_ENABLE_AEN       (0x02)    /* RGBC Enable - Writing 1 actives the ADC, 0 disables it */
#define TCS34725_ENABLE_PON       (0x01)    /* Power on - Writing 1 activates the internal oscillator, 0 disables it */
#define TCS34725_ATIME            (0x01)    /* Integration time */
#define TCS34725_WTIME            (0x03)    /* Wait time (if TCS34725_ENABLE_WEN is asserted) */
#define TCS34725_WTIME_2_4MS      (0xFF)    /* WLONG0 = 2.4ms   WLONG1 = 0.029s */
#define TCS34725_WTIME_204MS      (0xAB)    /* WLONG0 = 204ms   WLONG1 = 2.45s  */
#define TCS34725_WTIME_614MS      (0x00)    /* WLONG0 = 614ms   WLONG1 = 7.4s   */
#define TCS34725_AILTL            (0x04)    /* Clear channel lower interrupt threshold */
#define TCS34725_AILTH            (0x05)
#define TCS34725_AIHTL            (0x06)    /* Clear channel upper interrupt threshold */
#define TCS34725_AIHTH            (0x07)
#define TCS34725_PERS             (0x0C)    /* Persistence register - basic SW filtering mechanism for interrupts */
#define TCS34725_PERS_NONE        (0b0000)  /* Every RGBC cycle generates an interrupt                                */
#define TCS34725_PERS_1_CYCLE     (0b0001)  /* 1 clean channel value outside threshold range generates an interrupt   */
#define TCS34725_PERS_2_CYCLE     (0b0010)  /* 2 clean channel values outside threshold range generates an interrupt  */
#define TCS34725_PERS_3_CYCLE     (0b0011)  /* 3 clean channel values outside threshold range generates an interrupt  */
#define TCS34725_PERS_5_CYCLE     (0b0100)  /* 5 clean channel values outside threshold range generates an interrupt  */
#define TCS34725_PERS_10_CYCLE    (0b0101)  /* 10 clean channel values outside threshold range generates an interrupt */
#define TCS34725_PERS_15_CYCLE    (0b0110)  /* 15 clean channel values outside threshold range generates an interrupt */
#define TCS34725_PERS_20_CYCLE    (0b0111)  /* 20 clean channel values outside threshold range generates an interrupt */
#define TCS34725_PERS_25_CYCLE    (0b1000)  /* 25 clean channel values outside threshold range generates an interrupt */
#define TCS34725_PERS_30_CYCLE    (0b1001)  /* 30 clean channel values outside threshold range generates an interrupt */
#define TCS34725_PERS_35_CYCLE    (0b1010)  /* 35 clean channel values outside threshold range generates an interrupt */
#define TCS34725_PERS_40_CYCLE    (0b1011)  /* 40 clean channel values outside threshold range generates an interrupt */
#define TCS34725_PERS_45_CYCLE    (0b1100)  /* 45 clean channel values outside threshold range generates an interrupt */
#define TCS34725_PERS_50_CYCLE    (0b1101)  /* 50 clean channel values outside threshold range generates an interrupt */
#define TCS34725_PERS_55_CYCLE    (0b1110)  /* 55 clean channel values outside threshold range generates an interrupt */
#define TCS34725_PERS_60_CYCLE    (0b1111)  /* 60 clean channel values outside threshold range generates an interrupt */
#define TCS34725_CONFIG           (0x0D)
#define TCS34725_CONFIG_WLONG     (0x02)    /* Choose between short and long (12x) wait times via TCS34725_WTIME */
#define TCS34725_CONTROL          (0x0F)    /* Set the gain level for the sensor */
#define TCS34725_ID               (0x12)    /* 0x44 = TCS34721/TCS34725, 0x4D = TCS34723/TCS34727 */
#define TCS34725_STATUS           (0x13)
#define TCS34725_STATUS_AINT      (0x10)    /* RGBC Clean channel interrupt */
#define TCS34725_STATUS_AVALID    (0x01)    /* Indicates that the RGBC channels have completed an integration cycle */
#define TCS34725_CDATAL           (0x14)    /* Clear channel data */
#define TCS34725_CDATAH           (0x15)
#define TCS34725_RDATAL           (0x16)    /* Red channel data */
#define TCS34725_RDATAH           (0x17)
#define TCS34725_GDATAL           (0x18)    /* Green channel data */
#define TCS34725_GDATAH           (0x19)
#define TCS34725_BDATAL           (0x1A)    /* Blue channel data */
#define TCS34725_BDATAH           (0x1B)
 
#define TCS34725_INTEGRATIONTIME_2_4MS   0xFF   /**<  2.4ms - 1 cycle    - Max Count: 1024  */
#define TCS34725_INTEGRATIONTIME_24MS    0xF6   /**<  24ms  - 10 cycles  - Max Count: 10240 */
#define TCS34725_INTEGRATIONTIME_50MS    0xEB   /**<  50ms  - 20 cycles  - Max Count: 20480 */
#define TCS34725_INTEGRATIONTIME_101MS   0xD5   /**<  101ms - 42 cycles  - Max Count: 43008 */
#define TCS34725_INTEGRATIONTIME_154MS   0xC0   /**<  154ms - 64 cycles  - Max Count: 65535 */
#define TCS34725_INTEGRATIONTIME_240MS   0x9C   /**<  240ms - 100 cycles - Max Count: 65535 */
#define TCS34725_INTEGRATIONTIME_700MS   0x00   /**<  700ms - 256 cycles - Max Count: 65535 */
 
#define TCS34725_GAIN_1X                 0x00   /**<  No gain  */
#define TCS34725_GAIN_4X                 0x01   /**<  4x gain  */
#define TCS34725_GAIN_16X                0x02   /**<  16x gain */
#define TCS34725_GAIN_60X                0x03   /**<  60x gain */
/******************************************************************************/
#define TCS_SDA_IN()  {TCS_SDA_GPIO->CRL&=0xFFFFFFF0;TCS_SDA_GPIO->CRL|=8;}
#define TCS_SDA_OUT() {TCS_SDA_GPIO->CRL&=0xFFFFFFF0;TCS_SDA_GPIO->CRL|=3;}

#define TCS_SDA_READ   TCS_GPIO->IDR&(TCS_SDA_PIN)
 
#define TCS_SCL_H     HAL_GPIO_WritePin(TCS_GPIO,TCS_SCL_PIN,(GPIO_PinState)1)
#define TCS_SCL_L     HAL_GPIO_WritePin(TCS_GPIO,TCS_SCL_PIN,(GPIO_PinState)0)
#define TCS_SDA_H     HAL_GPIO_WritePin(TCS_GPIO,TCS_SDA_PIN,(GPIO_PinState)1)
#define TCS_SDA_L     HAL_GPIO_WritePin(TCS_GPIO,TCS_SDA_PIN,(GPIO_PinState)0)
/******************************************************************************/
#define max3v(v1, v2, v3)   ((v1)<(v2)? ((v2)<(v3)?(v3):(v2)):((v1)<(v3)?(v3):(v1)))
#define min3v(v1, v2, v3)   ((v1)>(v2)? ((v2)>(v3)?(v3):(v2)):((v1)>(v3)?(v3):(v1)))
 
typedef struct{
	unsigned short  c;      //[0-65536]
	unsigned short  r;
	unsigned short  g;
	unsigned short  b;
}COLOR_RGBC;//RGBC
 
typedef struct{
	unsigned short h;       //[0,360]
	unsigned char  s;       //[0,100]
	unsigned char  l;       //[0,100]
}COLOR_HSL;//HSL
 

uint8_t TCS34725_Init(uint8_t time,uint8_t gain);
uint8_t TCS34725_GetRawData(COLOR_RGBC *rgbc);
void TCS34725_LedON(uint8_t enable);


void RGBtoHSL(COLOR_RGBC *Rgb, COLOR_HSL *Hsl);
uint16_t TCS34725_GetR(void);
uint16_t TCS34725_GetG(void);
uint16_t TCS34725_GetB(void);
uint16_t TCS34725_GetC(void);

#endif

然后通過調用TCS34725_GetRawData(&color_rgbc);,即可獲取采集的rgb值。通過對比不同通道的大小,可以粗略的判斷識別的RGB三原色。
打開sensor.c,定義get_color(),編寫相關代碼。

代碼如下
	/**
 * @brief  : 識別木塊顏色,紅綠藍
 * @param  :無
 * @retval   識別的顏色,R G B
**/  
COLOR_RGBC color_rgbc;
uint8_t get_color() {
	TCS34725_GetRawData(&color_rgbc);//獲取RGB
	if(color_rgbc.c>400){return 0;}
      if (color_rgbc.r > color_rgbc.g && color_rgbc.r  > color_rgbc.b ) {
		//usart_send_str(&huart3,(uint8_t *)"May RED\r\n");
		  return 'R';
      } else if (color_rgbc.g > color_rgbc.r && color_rgbc.g  > color_rgbc.b) {
		  //usart_send_str(&huart3,(uint8_t *)"May GREEN\r\n");
		  return 'G';
      } else if (color_rgbc.b > color_rgbc.g && color_rgbc.b  > color_rgbc.r) {
		  //usart_send_str(&huart3,(uint8_t *)"May BULE\r\n");
		  return 'B';
      }
	return 0;
}

由於單次識別置信度較低,我們可以參考超聲波一節,采集多個數值返回中間值以減少誤差。定義get_adc_color_middle(),編寫對應函數。

get_adc_color_middle
/**
 * @brief  :處理顏色模塊采集到的數據,取采集到的中間值
 * @param  :數組地址,元素個數
 * @retval 處理后的顏色值  
**/  
char get_adc_color_middle() {
	YSSB_LED(1);
	uint8_t i;
	static int ad_value[5] = {0}, myvalue;// ad_value_bak[5] = {0}, 
	for(i=0;i<5;i++){ad_value[i] = get_color();HAL_Delay(200);};
	selection_sort(ad_value, 5);
	myvalue = ad_value[2];
	YSSB_LED(0);
	return myvalue;  
}

這里的YSSB_LED是宏定義的TCS34725_LedON(x)函數。用於開啟顏色傳感器的補光燈。打開color.h,加入該宏定義#define YSSB_LED(x) TCS34725_LedON(x)
現在我們獲取到了顏色傳感器傳來的顏色,根據不同顏色,我們可以執行不同動作。
在sensor.c中定義color_task函數。參考超聲波的task,這里先只打印出來,更多的功能后續添加。

color_task
/**
 * @brief  :顏色傳感器對應任務
 * @param  :無
 * @retval 無
**/ 
void color_task(){
	static uint32_t systick_ms_yanse = 0;
	int millis=HAL_GetTick();//獲取系統時間
	uint8_t cmd_return[128];
	char color_value;
	if (millis - systick_ms_yanse > 20) {
		systick_ms_yanse = HAL_GetTick();
		color_value = get_adc_color_middle();//獲取a0的ad值,計算出距離
		if(color_value!=0)
		{
			sprintf((char *)cmd_return, "Color = [%c]\r\n", color_value);
			usart_send_str(&huart3,cmd_return);
		}else
		{usart_send_str(&huart3,(uint8_t *)"no wood block \r\n");
		}	  
	}
}

在sensor.h中聲明定義的函數

sensor.h

#include "stdint.h"
#include "color.h"
#define sound_vol HAL_GPIO_ReadPin(sound_GPIO_Port,sound_Pin)
#define Trig(x) HAL_GPIO_WritePin(Trig_GPIO_Port,Trig_Pin,(GPIO_PinState)x)
#define Echo() HAL_GPIO_ReadPin(Echo_GPIO_Port,Echo_Pin)
#define YSSB_LED(x) TCS34725_LedON(x); //顏色識別的LED燈

void sound_task(void);
void hcsr_task(void);
void color_task(void);
uint16_t get_csb_value(void);
uint8_t get_color(void);
然后在main里添加相關選項 `case 'I':color_task();break;` 需要注意的是,顏色傳感器需要初始化。
/* USER CODE BEGIN 2 */
//motor_init();
//arm_init();
TCS34725_Init(TCS34725_INTEGRATIONTIME_700MS,TCS34725_GAIN_1X);

並且由於顏色識別傳感器過遠,因此上電后需要等待下在初始化顏色傳感器,不然第一次會無法使用。
在主函數大概108行位置加入

  /* USER CODE BEGIN SysInit */
	HAL_Delay(1000);
  /* USER CODE END SysInit */

工程源碼

國內用戶請使用gitee克隆或是使用代理訪問Github
https://github.com/USTHzhanglu/stm32-hal/tree/main/color


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM