基于TCS3200和ESP32-E的颜色识别显示与报警系统(Funpack2-3)
本文使用TCS3200颜色传感器和 ESP32-E主控板,开发了一款颜色识别、显示与报警系统。单色屏显示RGB色彩值,彩色屏浮现出被测物体颜色效果;当检测到不同色块时,会发出高低不同的报警音。
标签
Funpack活动
Funpack2-3
ESP32-E
TCS3200
颜色识别
chinaking
更新2023-01-03
654

内容介绍

基于TCS3200和ESP32-E的颜色识别显示与报警系统

  • 概述

    本文使用DFROBOT公司的TCS3200颜色传感器模块和FireBeetle ESP32-E主控板,开发了一款颜色识别、显示与报警系统。

    该系统使用TCS3200传感器采集颜色信息,将采集结果以频率信号形式发送到主控板;主控板外接了一块0.96寸OLED单色显示屏和2.4寸TFT彩色液晶屏,单色屏显示RGB色彩值及颜色判定结果,彩色屏浮现出检测到的色块颜色效果;系统还带有1个蜂鸣器,当检测到红、绿、蓝等不同色块时,会发出高低不同的报警音。

  • 硬件设计

系统原理图如图1所示。

FktdXdqZcHq9amkyEJH3-IHTGH3V

图1 系统原理图

系统使用的主要模块见表1.

1 主要模块信息

序号

名称

型号

制造商

备注

1

主控板

FireBeetle ESP32-E

DFROBOT

 

2

颜色传感器

TCS3200

DFROBOT

 

3

V-Meter模块

SSD1306驱动128*64

硬禾学堂

0.96寸OLED 屏I2C接口

4

TFT显示屏

ILI9341驱动240*320

 

2.4寸TFT屏 SPI接口

Fp1xXu9TpGlh79ZqjFhm1_sllf2M

2 具体接线对应表

Flpz0bw3Dsy0hRy5vj-0OpdTI6Vl

  • 软件设计

软件开发使用Arduino开发环境,目前使用的版本是1.8.13。

首先,设置附加开发板管理器网址。

FkkidTX1YefXWOAjv84fVRJtlAQn

然后,安装开发板对应的库文件。

FoIhAdnSwN_yvXWcXlWMN3-DXlFo

安装完成后,在工具菜单下,找到并选中开发板。

FoNEEJa-PVcOiM9YIRAb1hDQC15l

安装U8g2库文件,以支持OLED屏显示。

FuLgXzpgkhSIZi6Roj_M_x9FAs43

安装TFT_eSPI库文件,以支持TFT屏驱动。

FgM__l3wUjucAILNiZ6tZjRnvCvH

接下来,需要指定SPI屏的驱动及引脚信息。

进入C:\Users\Administrator\Documents\Arduino\libraries\TFT_eSPI文件夹下,编辑User_Setup.h文件。

主要是编辑以下几行代码。

#define ILI9341_DRIVER   //选择屏幕驱动芯片
#define TFT_CS   D10  // 指定Chip select control pin,
#define TFT_DC   D11  // 指定Data Command control pin
#define TFT_RST  -1  // 指定Reset引脚,若直接接开发板RST,此值设为-1

因使用的是开发板的硬件SPI接口,所有SPI引脚无需指定;若使用软件SPI,还需要指定SPI引脚。

主要程序代码如下:

#include <TFT_eSPI.h>        //TFT屏驱动
TFT_eSPI tft = TFT_eSPI();  

#include <U8g2lib.h>        //OLED屏驱动 
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

#define S0_PIN  D7  //颜色传感器与开发板连接引脚定义
#define S1_PIN  D6
#define S2_PIN  D5
#define S3_PIN  D3
#define OUT_PIN D2  //传感器的输出脚

//PWM参数
int freq = 2000;    // 频率
int channel = 0;    // 通道
int resolution = 8;   // 分辨率
#define Buzzer_PIN D12 //指定蜂鸣器的引脚,一定要是D脚,A脚不可以。

void setup() {
pinMode(S0_PIN,OUTPUT); //设定引脚输入输出模式
pinMode(S1_PIN,OUTPUT);
pinMode(S2_PIN,OUTPUT);
pinMode(S3_PIN,OUTPUT);
pinMode(OUT_PIN,INPUT);//控制器采集传感器信号

pinMode(Buzzer_PIN,OUTPUT);//控制器控制蜂鸣器信号

digitalWrite(S0_PIN,HIGH); //频率缩放20%  S0-HIGH,S1-LOW    
digitalWrite(S1_PIN,LOW);
Serial.begin(9600);

tft.init();
tft.setRotation(0);
tft.fillScreen(TFT_BLACK);

u8g2.begin();

ledcSetup(channel, freq, resolution);//PWM初始化函数
ledcAttachPin(Buzzer_PIN, channel);
}


void loop()
{
  int r_RGB, g_RGB, b_RGB;
  float k_R=7.6, k_G=6.8, k_B=7.3;
  int r_H, g_H, b_H;
  int r_L, g_L, b_L;
  int data_RGB_TFT16;
  digitalWrite(S2_PIN, LOW);//只采集红光
  digitalWrite(S3_PIN, LOW);
  r_L = pulseIn(OUT_PIN, LOW);
  r_H = pulseIn(OUT_PIN, HIGH);
  r_RGB=calcRGB(r_L,r_H,k_R);
  Serial.print("r_RGB = ");
  Serial.print(r_RGB);
  Serial.print(" ");
  delay(200);

  digitalWrite(S2_PIN, HIGH);//只采集绿光
  digitalWrite(S3_PIN, HIGH);
  g_L = pulseIn(OUT_PIN, LOW);
  g_H = pulseIn(OUT_PIN, HIGH);
  g_RGB=calcRGB(g_L,g_H,k_G);
  Serial.print("g_RGB = ");
  Serial.print(g_RGB);
  Serial.print(" ");
  delay(200);

  digitalWrite(S2_PIN, LOW);//只采集蓝光
  digitalWrite(S3_PIN, HIGH);
  b_L = pulseIn(OUT_PIN, LOW);
  b_H = pulseIn(OUT_PIN, HIGH);
  b_RGB=calcRGB(b_L,b_H,k_B);
  Serial.print("b_RGB = ");
  Serial.print(b_RGB);
  Serial.print(" ");
  Serial.println();
  delay(200);

  data_RGB_TFT16=r_RGB*31/255*2048+g_RGB*63/255*32+b_RGB*31/255;// 16位色  红0xF800     绿0x07E0   蓝0x001F   注意乘除的先后顺序
 // tft.fillScreen(data_RGB_TFT16);//写屏幕背景色
  tft.fillRect(70, 60, 100, 200, data_RGB_TFT16);   //屏幕240*320
  
 // u8g2.setFont(u8g2_font_ncenB10_tr);  //设置英文字体
  u8g2.enableUTF8Print();                //中文字体需要有此行,否则只能显示字母
  u8g2.setFont(u8g2_font_wqy16_t_gb2312);//设置中文字体
  u8g2.setFontDirection(0);
  u8g2.firstPage();
  do {
      
       u8g2.setCursor(30, 30);//设置X,Y起始坐标
         if ((r_RGB > g_RGB) && (r_RGB > b_RGB) && (r_RGB>80) )
        {
          Serial.println("Colour Red");
         // u8g2.print("RED");
            u8g2.print("红");
           ledcWrite(channel, 30);//控制蜂鸣器发声  255对应100%
           
        }
        else if ((g_RGB > r_RGB) && (g_RGB > b_RGB)&& (g_RGB>80))
        {
          Serial.println("Colour Green");
          // u8g2.print("GREEN");
           u8g2.print("绿");
           ledcWrite(channel, 15);
        }
        else if ((b_RGB > r_RGB) && ( b_RGB > g_RGB) && (b_RGB>80))
        {
          Serial.println("Blue");
          // u8g2.print("BLUE");
           u8g2.print("蓝");
           ledcWrite(channel, 5);
        }
         else
        {
          Serial.println("READY");
          //u8g2.print("READY");
          u8g2.print("就绪");
          ledcWrite(channel, 0);
        }

      //显示颜色RGB值
     u8g2.setCursor(80, 20);//设置X,Y起始坐标  
     u8g2.print("R=");
     u8g2.setCursor(100, 20);//设置X,Y起始坐标  
     u8g2.print(r_RGB);
     u8g2.setCursor(80, 40);//设置X,Y起始坐标  
     u8g2.print("G=");
     u8g2.setCursor(100, 40);//设置X,Y起始坐标  
     u8g2.print(g_RGB);
     u8g2.setCursor(80, 60);//设置X,Y起始坐标  
     u8g2.print("B=");
     u8g2.setCursor(100, 60);//设置X,Y起始坐标  
     u8g2.print(b_RGB);
  } while ( u8g2.nextPage() );
}


 int calcRGB(int time_L,int time_H,float k)
{
  int data1;
  byte data_Output;
  time_L = pulseIn(OUT_PIN, LOW); //检测低电平的时间长度 ms
  time_H = pulseIn(OUT_PIN, HIGH);//检测高电平的时间长度 ms
  data1=int(1000.0/(time_L+time_H)*k);
  if (data1<=255)
  {data_Output=data1;
  }
  else
  {data_Output=255;
  }
  return data_Output;
}
  • 演示效果

系统上电后,OLED屏会显示“就绪”,此时TFT屏背景为黑色。

FgTfFif35mkTqJySSr6HqLjaNDGr

当放置不同颜色色块时,TFT屏上会浮现出相应色块的颜色。同时,OLED屏会判断大致颜色,并用汉字显示。

当检测到不同的颜色时,蜂鸣器会发出报警声,红色报警声最高,绿色居中,蓝色报警声最低。

FrI-DPHo9nRnojKdeRd69AId03IT

  • 总结

     试验过程中遇到了以下问题:

  1. 颜色传感器校准及数据处理。

如需精确测量RGB数值,需要对传感器进行校准。校准方法是,将标准白色物体放在传感器上方1cm左右,通过调节RGB各通道的系数,使显示值为255,255,255。然后才能进行测量。

本文是使用pulseIn函数获取脉冲的低电平时间和高电平时间,相加后得到信号周期(因传感器输出频率信号占空比为50%,也可用低电平时间的2倍)。然后换算出频率,进而乘上系数,再和255进行对应。

  1. U8G2库的中文显示。

U8G2库支持中文“文泉驿字体”,这样就避免了手动创建汉字字模。具体使用时,需要先调用u8g2.enableUTF8Print(),启用UTF-8支持,否则会显示空白。

  1. ESP32的PWM输出。

普通Arduino开发板,PWM输出往往使用模拟量端口(A口),使用analogWrite函数。而ESP32-E不支持该函数,需要通过数字量端口(D口)使用ledcSetup(), ledcAttachPin(), ledcWrite()等3个函数来实现PWM输出。

  1. RGB24位色和屏幕16位色彩的转换。

打开C:\Users\Administrator\Documents\Arduino\libraries\TFT_eSPI\TFT_Drivers目录下,在ILI9341_Defines.h中可发现。TFT屏幕的颜色是用16位数据表示的。

#define ILI9341_BLACK       0x0000      /*   0,   0,   0 */

#define ILI9341_NAVY        0x000F      /*   0,   0, 128 */

#define ILI9341_DARKGREEN   0x03E0      /*   0, 128,   0 */

#define ILI9341_DARKCYAN    0x03EF      /*   0, 128, 128 */

#define ILI9341_MAROON      0x7800      /* 128,   0,   0 */

#define ILI9341_PURPLE      0x780F      /* 128,   0, 128 */

#define ILI9341_OLIVE       0x7BE0      /* 128, 128,   0 */

#define ILI9341_LIGHTGREY   0xC618      /* 192, 192, 192 */

#define ILI9341_DARKGREY    0x7BEF      /* 128, 128, 128 */

#define ILI9341_BLUE        0x001F      /*   0,   0, 255 */

#define ILI9341_GREEN       0x07E0      /*   0, 255,   0 */

#define ILI9341_CYAN        0x07FF      /*   0, 255, 255 */

#define ILI9341_RED         0xF800      /* 255,   0,   0 */

#define ILI9341_MAGENTA     0xF81F      /* 255,   0, 255 */

#define ILI9341_YELLOW      0xFFE0      /* 255, 255,   0 */

#define ILI9341_WHITE       0xFFFF      /* 255, 255, 255 */

#define ILI9341_ORANGE      0xFD20      /* 255, 165,   0 */

#define ILI9341_GREENYELLOW 0xAFE5      /* 173, 255,  47 */

#define ILI9341_PINK        0xF81F

而传感器计算出的标准RGB色255,255,255组合起来是24位,因此需要将传感器数据,压缩成16位,才能发送给屏幕显示。

也就是将24位111111111111111111111111转换成16位的1111111111111111,注意16位数据红、绿、蓝分别占5位、6位、5位。

本文使用的是下面的公式,来进行数据转换。data_RGB_TFT16=r_RGB*31/255*2048+g_RGB*63/255*32+b_RGB*31/255。;

 

附件下载

ESP32E_Colour_OLED.rar

团队介绍

老胡,电子爱好者,自动化工程师。

评论

0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号