返回列表 发新帖我要提问本帖赏金: 100.00元(功能说明)

[国产单片机] 色彩识别与样本色彩显示器

[复制链接]
1895|4
 楼主| jinglixixi 发表于 2022-12-30 23:08 | 显示全部楼层 |阅读模式
本帖最后由 jinglixixi 于 2023-1-11 17:17 编辑

#申请原创#

要想识别色彩就离不开色彩传感器的使用,而色彩传感器的种类又有许多种,如早期的TCS230TCS3200到现在的TCS34725等。
对于TCS230这类的传感器,它是以脉冲计数的方式来获得检测值,并通过色彩通道的选择来获得RGB的值。此外,为了达到一个可供使用的标准值,还需进行白平衡等处理,使用起来相对比较麻烦。
1  TCS230

而现在推出的色彩传感器,如TCS34725则是数字化的,并采用I2C接口来传送数据,在使用时直接就可读取到色彩的RGB值,并可获得两种色彩模式的检测结果,即RGB模式和HSL模式因此在使用上,它要比以前的色彩传感器要方便许多,功能也丰富一些。
2  TCS34725


1. 整体结构
为此,在制作色彩识别与样本色彩显示器时是直接选取TCS34725来做检测器件,该设计的整体结构见图3所示。
3 整体结构

在整体结构中,是以复旦微的FM33LGxx开发板作为处理核心,由TCS34725检测色彩值,由彩色的LCD屏来承担显示任务,其实物构成如图4所示。
4 实物构成


2.色彩传感器及其使用

TCS34725是采用I2C方式工作,其遵循的通讯协议如下:

TCS34725与开发板的引脚连接关系为:
PE9 ---SCL
PD10---SDA
由于TCS34725使用I2C的方式工作,为此是以GPIO口来模拟I2C的方式来实现。
其中,对所用引脚的功能配置函数为:
  1. void TCS34725_I2C_Init()
  2. {
  3.     FL_GPIO_InitTypeDef GPIO_InitStruct = {0};
  4.     FL_GPIO_ResetOutputPin(GPIOD, FL_GPIO_PIN_10);
  5.     GPIO_InitStruct.pin = FL_GPIO_PIN_10;
  6.     GPIO_InitStruct.mode = FL_GPIO_MODE_OUTPUT;
  7.     GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
  8.     GPIO_InitStruct.pull = FL_DISABLE;
  9.     FL_GPIO_Init(GPIOD, &GPIO_InitStruct);
  10.         
  11.     FL_GPIO_ResetOutputPin(GPIOE, FL_GPIO_PIN_9);
  12.     GPIO_InitStruct.pin = FL_GPIO_PIN_9;
  13.     GPIO_InitStruct.mode = FL_GPIO_MODE_OUTPUT;
  14.     GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
  15.     GPIO_InitStruct.pull = FL_DISABLE;
  16.     FL_GPIO_Init(GPIOE, &GPIO_InitStruct);
  17. }

由于在TCS34725工作时,既有数据输入处理,又有数据输出处理,故为其配置的输入、输出模式设置函数为:
  1. void TCS_SDA_OUT()
  2. {
  3.     FL_GPIO_InitTypeDef GPIO_InitStruct = {0};
  4.     FL_GPIO_ResetOutputPin(GPIOD, FL_GPIO_PIN_10);
  5.     GPIO_InitStruct.pin = FL_GPIO_PIN_10;
  6.     GPIO_InitStruct.mode = FL_GPIO_MODE_OUTPUT;
  7.     GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
  8.     GPIO_InitStruct.pull = FL_DISABLE;
  9.     FL_GPIO_Init(GPIOD, &GPIO_InitStruct);
  10. }

  11. void TCS_SDA_IN()
  12. {
  13.     FL_GPIO_InitTypeDef GPIO_InitStruct = {0};
  14.     FL_GPIO_ResetOutputPin(GPIOD, FL_GPIO_PIN_10);
  15.     GPIO_InitStruct.pin = FL_GPIO_PIN_10;
  16.     GPIO_InitStruct.mode = FL_GPIO_MODE_INPUT;
  17.     GPIO_InitStruct.pull = FL_ENABLE;
  18.     FL_GPIO_Init(GPIOD, &GPIO_InitStruct);
  19. }

TCS34725发送和接收字节数据的函数分别为:
  1. void TCS34725_I2C_Send_Byte(u8 byte)
  2. {
  3.         u8 i;
  4.         TCS_SDA_OUT();
  5.         TCS_SCL_L;
  6.         for(i = 0; i < 8; i++)
  7.         {
  8.                 if(((byte&0x80)>>7)==1)  TCS_SDA_H;
  9.                 else
  10.                         TCS_SDA_L;
  11.                 byte <<= 1;
  12.                 FL_DelayUs(2);
  13.                 TCS_SCL_H;
  14.                 FL_DelayUs(2);
  15.                 TCS_SCL_L;
  16.                 FL_DelayUs(2);
  17.         }
  18. }

  19. u8 TCS34725_I2C_Read_Byte(u8 ack)
  20. {
  21.         u8 i,receive = 0;
  22.         TCS_SDA_IN();
  23.         for(i = 0; i < 8; i++)
  24.         {
  25.                 TCS_SCL_L;
  26.                 FL_DelayUs(2);
  27.                 TCS_SCL_H;
  28.                 receive <<= 1;
  29.                 if(TCS_SDA_READ) receive++;
  30.                 FL_DelayUs(1);
  31.         }
  32.         if (!ack) TCS34725_I2C_NACK();
  33.         else TCS34725_I2C_ACK();
  34.         return  receive;
  35. }

TCS34725的初始化函数为:
  1. u8 TCS34725_Init(void)
  2. {
  3.         u8 id=0;
  4.         TCS34725_I2C_Init();
  5.         TCS34725_Read(TCS34725_ID, &id, 1);
  6.         if(id==0x4D | id==0x44)
  7.         {
  8.                         TCS34725_SetIntegrationTime(TCS34725_INTEGRATIONTIME_50MS);
  9.                         TCS34725_SetGain(TCS34725_GAIN_1X);
  10.                         TCS34725_Enable();
  11.                         return 1;
  12.         }
  13.         return 0;
  14. }

获取输出值的函数为:
  1. u8 TCS34725_GetRawData(COLOR_RGBC *rgbc)
  2. {
  3.         u8 status = TCS34725_STATUS_AVALID;        
  4.         TCS34725_Read(TCS34725_STATUS, &status, 1);        
  5.         if(status & TCS34725_STATUS_AVALID)
  6.         {
  7.                 rgbc->c = TCS34725_GetChannelData(TCS34725_CDATAL);        
  8.                 rgbc->r = TCS34725_GetChannelData(TCS34725_RDATAL);        
  9.                 rgbc->g = TCS34725_GetChannelData(TCS34725_GDATAL);        
  10.                 rgbc->b = TCS34725_GetChannelData(TCS34725_BDATAL);
  11.                 return 1;
  12.         }
  13.         return 0;
  14. }

3.LCD屏显示驱动
在显示方面,所使用的显示器件为0.96寸的彩色LCD屏,其显示分辨率为160*80像素点。该显示屏采用SPI接口方式工作,为此它与开发板的引脚连接关系为:
SCL ---PD3
SDA ---PD5
RES ---PD4
DC ---PC5
CS ---PD2


LCD屏对引脚的功能配置函数为:
  1. void lcd_app(void)
  2. {
  3.     FL_GPIO_InitTypeDef GPIO_InitStruct = {0};
  4.     FL_GPIO_ResetOutputPin(GPIOD, FL_GPIO_PIN_2|FL_GPIO_PIN_3|FL_GPIO_PIN_4|FL_GPIO_PIN_5);
  5.     GPIO_InitStruct.pin = FL_GPIO_PIN_2|FL_GPIO_PIN_3|FL_GPIO_PIN_4|FL_GPIO_PIN_5;
  6.     GPIO_InitStruct.mode = FL_GPIO_MODE_OUTPUT;
  7.     GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
  8.     GPIO_InitStruct.pull = FL_DISABLE;
  9.     FL_GPIO_Init(GPIOD, &GPIO_InitStruct);
  10.         
  11.     FL_GPIO_ResetOutputPin(GPIOC, FL_GPIO_PIN_5);
  12.     GPIO_InitStruct.pin = FL_GPIO_PIN_5;
  13.     GPIO_InitStruct.mode = FL_GPIO_MODE_OUTPUT;
  14.     GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
  15.     GPIO_InitStruct.pull = FL_DISABLE;
  16.     FL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  17. }


GPIO口模拟SPI方式发送字节数据的函数为:
  1. void LCD_Writ_Bus(u8 dat)
  2. {
  3.     u8 i;
  4.     OLED_CS_Clr();
  5.     for(i=0;i<8;i++)
  6.     {
  7.         OLED_SCLK_Clr();
  8.         if(dat&0x80)
  9.            OLED_SDIN_Set();
  10.         else
  11.            OLED_SDIN_Clr();
  12.         OLED_SCLK_Set();
  13.         dat<<=1;
  14.     }
  15.     OLED_CS_Set();
  16. }


LCD屏的初始化函数为:
voidLcd_Init(void)
{
  OLED_RST_Clr();
  FL_DelayMs(200);
  OLED_RST_Set();
  FL_DelayMs(200);
  LCD_WR_REG(0x11);
  FL_DelayMs(100);
  LCD_WR_REG(0x21);
  LCD_WR_REG(0xB1);
  LCD_WR_DATA8(0x05);
  LCD_WR_DATA8(0x3A);
  LCD_WR_DATA8(0x3A);
  LCD_WR_REG(0xB2);
  LCD_WR_DATA8(0x05);
  LCD_WR_DATA8(0x3A);
  LCD_WR_DATA8(0x3A);
  LCD_WR_REG(0xB3);
  LCD_WR_DATA8(0x05);
  LCD_WR_DATA8(0x3A);
  LCD_WR_DATA8(0x3A);
  LCD_WR_DATA8(0x05);
  LCD_WR_DATA8(0x3A);
  LCD_WR_DATA8(0x3A);
  LCD_WR_REG(0xB4);
  LCD_WR_DATA8(0x03);
  LCD_WR_REG(0xC0);
  LCD_WR_DATA8(0x62);
  LCD_WR_DATA8(0x02);
  LCD_WR_DATA8(0x04);
  LCD_WR_REG(0xC1);
  LCD_WR_DATA8(0xC0);
  LCD_WR_REG(0xC2);
  LCD_WR_DATA8(0x0D);
  LCD_WR_DATA8(0x00);
  LCD_WR_REG(0xC3);
  LCD_WR_DATA8(0x8D);
  LCD_WR_DATA8(0x6A);
  LCD_WR_REG(0xC4);
  LCD_WR_DATA8(0x8D);
  LCD_WR_DATA8(0xEE);
  LCD_WR_REG(0xC5);
  LCD_WR_DATA8(0x0E);
  LCD_WR_REG(0xE0);
  LCD_WR_DATA8(0x10);
  LCD_WR_DATA8(0x0E);
  LCD_WR_DATA8(0x02);
  LCD_WR_DATA8(0x03);
  LCD_WR_DATA8(0x0E);
  LCD_WR_DATA8(0x07);
  LCD_WR_DATA8(0x02);
  LCD_WR_DATA8(0x07);
  LCD_WR_DATA8(0x0A);
  LCD_WR_DATA8(0x12);
  LCD_WR_DATA8(0x27);
  LCD_WR_DATA8(0x37);
  LCD_WR_DATA8(0x00);
  LCD_WR_DATA8(0x0D);
  LCD_WR_DATA8(0x0E);
  LCD_WR_DATA8(0x10);
  LCD_WR_REG(0xE1);
  LCD_WR_DATA8(0x10);
  LCD_WR_DATA8(0x0E);
  LCD_WR_DATA8(0x03);
  LCD_WR_DATA8(0x03);
  LCD_WR_DATA8(0x0F);
  LCD_WR_DATA8(0x06);
  LCD_WR_DATA8(0x02);
  LCD_WR_DATA8(0x08);
  LCD_WR_DATA8(0x0A);
  LCD_WR_DATA8(0x13);
  LCD_WR_DATA8(0x26);
  LCD_WR_DATA8(0x36);
  LCD_WR_DATA8(0x00);
  LCD_WR_DATA8(0x0D);
  LCD_WR_DATA8(0x0E);
  LCD_WR_DATA8(0x10);
  LCD_WR_REG(0x3A);
  LCD_WR_DATA8(0x05);
  LCD_WR_REG(0x36);
  LCD_WR_DATA8(0x78);
  LCD_WR_REG(0x29);
}



4. 功能实现
有了前面的准备工作,就可以开始其功能设计了。
其设计思想为:
1)进行色彩值的归一化处理
由于TCS34725传感器是按3基色的亮度来进行检测的,因此对其检测值需要进行归一化处理,其处理方法就是用RGB的色彩值*255/亮度值。
以红色为例,其进行归一化的语句为:
rv=rgb.r*255/rgb.c;
对于GB这两种色彩的归一化处理与之相仿。

2)实现样本色彩的标识处理
在获得了色彩的归一化结果后,其输出值是24位色,为了便于以16位色彩的形式进行显示,需进行色彩位数的变换处理,对于565的色彩表示方式,所进行的变换处理为:
fv=((rv>>3)<<8)+((gv>>2)<<5)+(bv>>3);
其中fv就是变换后的16位色彩值,而rvgvbv8位色彩值。

此外,还要做的2件事为:一是绘制样本色彩框,以标识样本色彩的区域,另一个则是标识样本色彩,即填充一个样本色彩块。
实现样本色彩框的绘制函数为:
  1. void LCD_box(u16 x1,u16 y1,u16 x2,u16 y2)
  2. {
  3.       int i,l;
  4.       LCD_Address_Set(x1,y1,x2,y1);
  5.       l=x2-x1;
  6.       for(i=0;i<l;i++)
  7.       {
  8.             LCD_WR_DATA8(0xff);
  9.             LCD_WR_DATA8(0xff);
  10.       }
  11.       LCD_Address_Set(x1,y2,x2,y2);
  12.       for(i=0;i<l;i++)
  13.       {
  14.             LCD_WR_DATA8(0xff);
  15.             LCD_WR_DATA8(0xff);
  16.       }
  17.       l=y2-y1;
  18.       for(i=0;i<l;i++)
  19.       {
  20.           LCD_DrawPoint(x1,y1+i,WHITE);
  21.       }
  22.       for(i=0;i<l;i++)
  23.       {
  24.           LCD_DrawPoint(x2,y1+i,WHITE);
  25.       }
  26. }


实现样本色彩标识的函数为:
  1. void LCD_color(u16 Color)
  2. {
  3.     u16 i,j;
  4.     LCD_Address_Set(110,30,129,49);
  5.     for(i=0;i<20;i++)
  6.     {
  7.        for (j=0;j<20;j++)
  8.        {
  9.           LCD_WR_DATA(Color);
  10.        }
  11.     }
  12. }


功能处理的主程序:
  1. int main(void)
  2. {
  3.     u16 rv,gv,bv,fv;
  4.     MF_Clock_Init();
  5.     MF_SystemClock_Config();
  6.     FL_Init();
  7.     MF_Config_Init();
  8.     UserInit();
  9.     led_int();
  10.     lcd_app();
  11.     Lcd_Init();
  12.     LCD_Clear(BLACK);
  13.     BACK_COLOR=BLACK;
  14.     FL_DelayMs(2000);
  15.     LCD_ShowString(20,30,"R:  G:  B:",YELLOW);
  16.     LCD_color(RED);
  17.     LCD_box(109,29,130,50);
  18.     TCS34725_Init();
  19.     TCS34725_GetRawData(&rgb);
  20.     while(1)
  21.     {
  22.                TCS34725_GetRawData(&rgb);
  23.                rv=rgb.r*255/rgb.c;
  24.                gv=rgb.g*255/rgb.c;
  25.                bv=rgb.b*255/rgb.c;
  26.                LCD_ShowNum(0,50,rv,4,YELLOW);
  27.                LCD_ShowNum(32,50,gv,4,YELLOW);
  28.                LCD_ShowNum(64,50,bv,4,YELLOW);
  29.                fv=((rv>>3)<<8)+((gv>>2)<<5)+(bv>>3);
  30.                LCD_color(fv);
  31.                FL_DelayMs(1000);
  32.                LED0_TOG();
  33.      }
  34. }


5. 验证测试
经程序的编译与下载,其检测的效果如图5至图7所示,其中用于彩色检测的材料为彩色的泡沫塑料板。
从测试效果看,其结果还是可信的,能在一定应用场合使用。
此外,由于传感器上所配的LED灯有些偏黄,会对反射光的检测有一定的影响。

5 检测粉色

6 检测绿色

7 检测蓝色


TCS34725相关代码及主程序:




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×

打赏榜单

21小跑堂 打赏了 100.00 元 2023-01-11
理由:恭喜通过原创审核!期待您更多的原创作品~

评论

使用色彩传感器捕获颜色并在屏幕上显示RGB值和色块,整体完成度较好,文章结构较为合理。若使用RGB灯将颜色显示,效果可能更佳。如果可以,作者是否可以上传源码,方便其他人下载学习。  发表于 2023-1-11 16:29
forgot 发表于 2022-12-31 22:12 | 显示全部楼层
 楼主| jinglixixi 发表于 2022-12-31 22:54 | 显示全部楼层
 楼主| jinglixixi 发表于 2023-1-11 17:18 | 显示全部楼层
TCS34725相关代码及主程序见附件
您需要登录后才可以回帖 登录 | 注册

本版积分规则

521

主题

2949

帖子

39

粉丝
快速回复 在线客服 返回列表 返回顶部