单片机学习小组
直播中

李桂兰

7年用户 1432经验值
私信 关注

如何使用串口通信连接GY-33颜色传感器完成对颜色的识别?

如何使用串口通信连接GY-33颜色传感器完成对颜色的识别?

回帖(1)

凌云志

2022-1-25 14:29:43
所需:stm32单片机(这里使用的是正点原子stm32mini板),GY_33传感器,GY_33配套软件,串口助手,USB转TTL


  
  1.GY-33介绍及其接线

  GY-33是一款低成本颜色识别传感器模块。工作电压3-5v,功耗小,体积小,安装方便。其工作原理是,照明LED发光,照射到被测物体后,返回光经过滤镜检测RGB的比例值,根据RGB的比例值识别出颜色。此模块,有两种方式读取数据,即串口UART(TTL电平)或者IIC(2线)。串口的波特率有9600bps与115200bps,可配置,有连续,询问输出两种方式,其响应频率为10hz
                                                                                                                    先来看看GY-33的实物及其接线
  
  我们只需要焊接排针在这四位上,然后用杜邦线把这四位同stm32对应的引脚连接即可,由于我设置GY-33通过串口3同stm32通信 ,根据原理图DR应该连接PB10,CT应该连接PB11
   
  2.通信原理

  首先我们得先了解GY-33是怎么通过stm32和上位机完成通信的(这一步至关重要,如果连这个过程是怎样进行的都不知道,那就像无头苍蝇,永远完成不了这个功能)--------------
  思路是1. 上位机通过串口1发送指令到stm32                                                                 2.stm32再通过串口3把指令发到GY-33颜色传感器                                                          3.GY-33接受到指令后会自动输出其测量的颜色对应的数据(第四部分会讲数据类型及数据处理)回串口3                                                                                                                            4.串口3接受到数据后中断,我们可以在串口3中断函数里对数据进行处理,从而提取出RGB值并打印出对应的颜色和RGB值
  (文字看着腻歪,直接看下图通信思路及实现方法)
  3.代码

   先看看串口的通信协议
  程序应该按通信协议设置
话不多说,直接上代码(看串口3中断函数代码前可以先看第四部分)

#include "stm32f10x.h"#include "stdio.h"//printf函数void USART1_Init(void){        GPIO_InitTypeDef GPIO_InitStructure;//定义GPIO结构体        USART_InitTypeDef USART_InitStructure;//定义串口结构体        NVIC_InitTypeDef NVIC_InitStructure;//定义优先级结构体        //使能时钟        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能GPIOA        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 ,ENABLE);//使能串口1        //发送TX        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//PA9        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;//根据GY-33响应频率10hz        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出        GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化GPIOA        //接收RX        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//PA10        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;//根据GY-33响应频率10hz        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空输入        GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化GPIOA        //串口        USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//不使用硬件        USART_InitStructure.USART_BaudRate=9600;//波特率        USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;//模式        USART_InitStructure.USART_StopBits=USART_StopBits_1;//一个停止位        USART_InitStructure.USART_Parity=USART_Parity_No;//奇偶校验关闭        USART_InitStructure.USART_WordLength=USART_WordLength_8b;//字长        USART_Init(USART1,&USART_InitStructure);//初始化串口1        //优先级配置        NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;//串口1中断        NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//使能串口1中断        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级        NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;//响应优先级        NVIC_Init(&NVIC_InitStructure);//初始化优先级        //使能        USART_Cmd(USART1,ENABLE);//使能串口1        USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//使能接收缓存非空寄存器}void USART3_Init(void){        GPIO_InitTypeDef GPIO_InitStructure;//定义GPIO结构体        USART_InitTypeDef USART_InitStructure;//定义串口结构体        NVIC_InitTypeDef NVIC_InitStructure;//定义优先级结构体        //使能时钟        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能GPIOB        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3 ,ENABLE);//使能串口3        //发送TX        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//PB10        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;//根据GY-33响应频率10hz        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出        GPIO_Init(GPIOB,&GPIO_InitStructure);//初始化GPIOB        //接收RX        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11;//PB11        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空输入        GPIO_Init(GPIOB,&GPIO_InitStructure);//初始化GPIOB        //串口        USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//不使用硬件        USART_InitStructure.USART_BaudRate=9600;//波特率        USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;//模式        USART_InitStructure.USART_StopBits=USART_StopBits_1;//一个停止位        USART_InitStructure.USART_Parity=USART_Parity_No;//奇偶校验关闭        USART_InitStructure.USART_WordLength=USART_WordLength_8b;//字长        USART_Init(USART3,&USART_InitStructure);//初始化串口3        //优先级配置        NVIC_InitStructure.NVIC_IRQChannel=USART3_IRQn;//串口3中断        NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//使能串口3中断        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//抢占        NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;//响应优先级        NVIC_Init(&NVIC_InitStructure);//初始化优先级        //使能        USART_Cmd(USART3,ENABLE);//使能串口3        USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);//使能接收缓存非空寄存器}void USART1_IRQHandler ()//串口1中断{                if(USART_GetITStatus(USART1,USART_IT_RXNE))//如果接收到数据        {   u8 data;                data=USART_ReceiveData(USART1);//保存指令                        USART_SendData(USART3,data);//串口3发送指令给传感器        }}void USART3_IRQHandler(){        if(USART_GetITStatus(USART3,USART_IT_RXNE))//如果接收到数据        {                u8 data;                static int result1,result2,result3;//静态保存                static int i=0,staus=0,j=0,staus2=0,temp1=0,temp2=0,temp3=0;                data=USART_ReceiveData(USART3);//赋值                        if(data==0x5A)                        staus2=1;                if(staus2)                {                        j++;                        if(j==1)temp1=data;                        if(j==2)temp2=data;                        if(j==3)                                {                                        temp3=data;j=0;                                        if(temp3==0x45&&temp2==0x5A&&temp1==0X5A)                                        {                                                staus2=0;                                                staus=1;                                        }                                }                }//如果连续收到0x5a,0x5a,0x45,staus置1,进入下面数据处理                if (staus)//将0x45看成第一位数据,保存第三,四,五位数据,分别对应红,绿,蓝的RGB值                {                        i++;                        if(i==3)                                result1=USART_ReceiveData(USART3);                        if(i==4)                                result2=USART_ReceiveData(USART3);                        if(i==5)                        {                                result3=USART_ReceiveData(USART3);                                if(result1==255&&result2==255&&result3==255)//三者RGB值都为255即打印白色                                        printf("R=%d G=%d B=%d 白色rn",result1,result2,result3);                                if(result1<50&&result2<50&&result3<50)//三者RGB值都比较小即为黑色                                        printf("R=%d G=%d B=%d 黑色rn",result1,result2,result3);                                else                                {                                if(result1>result2&&result1>result3)//不符合三者RGB都大或都小的情况下,红色RGB值最大即打印红色                                        printf("R=%d G=%d B=%d 红色rn",result1,result2,result3);                                if(result2>result1&&result2>result3)//不符合三者RGB都大或都小的情况下,绿色RGB值最大即打印绿色                                        printf("R=%d G=%d B=%d 绿色rn",result1,result2,result3);                                if(result3>result2&&result1SR&0X40)==0);//循环发送,直到发送完毕   USART1->DR = (u8) ch;      return ch;}#endif

  4.GY-33发送出来的数据及如何处理数据

  一共有三种不同的数据类型(0x15,0x25,0x45),每种数据都是以俩个0x5a开头(帧头
    GY-33发给串口3的数据由这三种不同的数据类型组成,例如5A 5A 15 08 01 78 01 92 00 4C 05 05 33  5A 5A 25 06 02 CC  0C 5D 00 02 18 5A 5A 45 03 FF F 4C 46 5A 5A 15 08 01 78 01 92 00 4C 05 05 33  5A 5A 25 06 02 CC  0C 5D 00 02 18 5A 5A 45 03 FF F 4C 46(不同数据类型用不同颜色)
  并且每一种类型的数据所含数字的个数不同(每串数据的第四位数表示这串数据的有效数据个数,同种数据类型数字个数相同),我们需要选择一种数据类型来处理,这里我们就选择最简单的第三种数据进行处理吧
  处理方法:首先得判断是第三种数据(依次接收到的数据是0x5a,0x5a,0x45)//若再判断下一位为0x03会更好,然后再把第三种数据的第五,六,七位取出来并打印(具体处理方法查看上面的代码)                                                                                                                            其他俩种数据类型根据上面表格也可处理,处理方法与第三种数据类型类似                                                                                                                                                                                                                      
  5.软件使用

   在使用GY-33颜色传感器前,得先对其进行颜色白校准(使用COLOR,USA转ttl)u***转ttl直接连传感器,通过COLOR软件直接配置GY-33
     
   白校准后打开xcom(注:16进制发送勾选上,波特率停止位等配置按如下)
   打开串口就可以接收到打印的数据了
完成此次任务,我发现对信息的筛选及整合能力很关键,最重要的应该是先搞明白原理。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分