基于HAL库的GY56 红外激光测距传感器学习(串口)

前言

本篇使用设备

1.stm32f103zet6

2.GY56红外传感器

本篇参考官方历程,这里分享一下官方资料包

链接:https://pan.baidu.com/s/13u2yHgVmw8YCtJAgqG405w 

提取码:sxld 

一、关于GY56

1.简述GY56的特点

                             

GY-56 是一款低成本数字红外测距传感器模块。 工作电压 3-5v,功耗小,体积小,安装方便。 其工作原理是,红外 LED 发光,照射到被测物体后,返回光经过 MCU 接收,MCU 计算出时间差,得到距离。直接输出距离值。此模块,有两种方式读取数据,即串口 UART(TTL 电平)+IIC(2 线)模式,串口的波特率有 9600bps 与 115200bps,可配置,有连续,询问输出两种方式,可掉电保存设置。GY-56 可以设置上下限距离报警值,开关量输出,在设定的区间内有被测物体挡住,直接输出高电平。IIC 模式下,如果需要,可以设置内部 IIC 地址不同,以便多个传感器直接接在同一个总线。

除此之外它还具有以下特点

  • 高性价比
  • 内置 MCU 计算距离
  • IIC、串口通信协议
  • 配有相应的上位机软件

2.参数

名称参数
测量范围0-2m
响应频率22ms(快速测量模式)
工作电压3-5V
工作电流15-35mA
工作温度-20℃-85℃
传感器芯片VL53L0X

3.关于引脚的配置(还有作用)

VCC接电源(3-5v)
GND接地
CT接串口 USART_TX
DR接串口USART_RX
SET手动设置探测阈值(0-3.3v)
OUT当位于上下限之间的时候高电平,反之低电平

串口连接方式:

二、通信协议(这里只讲串口的相关配置)

这里注意一下:在你没有修改设置的情况下,该模块默认使用串口通信

1)串口通信参数(默认波特率值 9600bps,可通过软件设定)
波特率:9600 bps 校验位:N 数据位:8 停止位:1
波特率:115200 bps 校验位:N 数据位:8 停止位:1

2)、模块输出格式,每帧包含 8-13 个字节(十六进制):
①.Byte0: 0x5A 帧头标志
②.Byte1: 0x5A 帧头标志
③.Byte2: 0x15 本帧数据类型
④.Byte3: 0x03 数据量
⑤.Byte4: 0x00~0xFF 数据前高 8 位
⑥.Byte5: 0x00~0xFF 数据前低 8 位
⑦.Byte6: 0x00~0xFF 模块测量模式
⑧.Byte7: 0x00~0xFF 模块温度
⑨.Byte8: 0x00~0xFF 校验和(前面数据累加和,仅留低 8 位)

ps.就算你不进行修改,它也会正常输出(有默认模式)

这里的Byte6对应的模式是自己修改的,它对应以下的几个模式(来自官方pdf)

那我们该怎么处理数据呢?

官方给出的数据计算方法(距离长度计算方法):

Distance= (Byte4<<8) | Byte5 单位 cm
Mode= Byte6
Temp= Byte7(MCU 温度)

例:一帧数据
< 5A-5A-15-04-00-0A-02-1A-F3>
Distance =(0x00<<8)|0x0A =10cm
Mode=2 (高精度模式)
Temp=0x1A=26℃

(3)命令字节,由外部控制器发送至 GY-56 模块(十六进制)
串口命令指令:
命令格式:0xA5+功能指令+指令值+sum

下面给出详细的命令列表:

例 1:设置串口连续输出数据,(如需掉电保存,请发送掉电保存指令)
连续输出指令=0xA5+0x65+0x01+0x0B

例 2:设置在 10cm-50cm 的区间范围内 OUT 引脚输出高电平
(如需掉电保存,请发送掉电保存指令)
设置上限阀值 50CM=0xA5+0x98+0x32+0x6F
设置下限阀值 10CM=0xA5+0xA9+0x0A+0x58

例 3: 掉电保存指令 = 0xA5+0x87+0x01+0x2D

三、模块的使用方法(这部分引用官方)

        该模块为串口和 IIC 输出模块,模块默认为串口模式。模块接入电源后,检测距离不在上限阀值内,LED 会闪亮 1 秒,检测距离在上限阀值内,LED 指示灯会长亮,如果指示灯一直闪烁,说明模块初始化失败,模块不能使用。

        这里只需要知道该模块的默认配置即可——波特率9600、高精度测量、连续输出模式

1.关于SET、OUT引脚的具体使用

我们假设有S,S1,S2,S3,S4

S 表示模块与被测物体之间的距离;
S1 表示设定的最大警界阀值(上限阀值);
S2 表示设定的最小警界阀值(下限阀值);
S3 表示解除最大警界状态值;S3 和 S1 的关系,S3+3≤S1。例如 S1=100,则 S3≤97;
S4 表示解除最小警界状态值;S4 和 S2 的关系,S4-3≥S2。例如 S2=50,则 S3≥53;

OUT 引脚的状态为高电平和低电平两种。高电平表示 S2<S<S1;低电平表示 S>S1 或 S<S2。

(1)OUT 由高电平变低电平。当模块 S>S1 或 S<S2 时,OUT 引脚变成低电平,模块 LED灯将由亮变灭。
(2)OUT 由低电平变高电平。当 S>S1,让 S≤S3 时(即当实际距离低于最大警界阀值 3cm时),OUT 引脚由低电平变高电平,模块 LED 灯将由灭变亮。当 S<S2,让 S≥S4 时(即当实际距离大于最小警界阀值 3cm 时),OUT 引脚由低电平变高电平,模块 LED 灯将由灭变亮。

2. 设置最大警界阀值:可通过发送指令外,也可通过 SET 引脚手动来设置。

(1)模块连续输出模式下,例如设置最大警界阀值 S1 为 100cm,则将模块放置在据被测物体 97cm 的位置进行 SET 引脚设置,或者发送指令:(A5 98 64 A1)0x64 是十进制的 100。
(2)手动 SET 引脚接入 3.3V 高电平,大约 3 秒,待模块 LED 指示灯闪速 2 下,此时断开 SET 引脚 3.3V 连接,断开后大约 5 秒,待 LED 闪烁 3 下,则设置成功。如果 LED 闪烁 4下,表示设置失败。失败原因有两种,一种是,接入高电平时间不够,另一种是设置的距离值小于最小警界阀值。

3. 设置最小警界阀值:可通过发送指令外,也可通过 SET 引脚来设置。

(1)模块连续输出模式下,例如设置最小警界阀值 S2 为 50cm,则将模块放置在据被测物体 53cm 的位置,进行 SET 引脚设置, 或者发送指令:(A5 A9 32 B2)0x32 是十进制的 50。
(2)手动 SET 引脚接入 GND,大约 3 秒,待模块 LED 指示灯闪速 2 下,此时断开 SET 引脚 GND 连接,断开后大约 5 秒,待 LED 闪烁 3 下,则设置成功。如果 LED 闪烁 4 下,表示设置失败。失败原因有两种,一种是,接入低电平时间不够,另一种是设置的距离值大于最大警界阀值。

4. 串口下 GY56 模块校准说明:

该模块由测距传感器和一个 MCU 组成。
(1)SPADs 修正: 当测距传感器上方被透明材质物体覆盖,模块需进行一次该修正,
并上电后加载 SPADs 修正参数。默认情况下,模块在每次上电后会进行一次 SPADs 修正操作,如用户手动执行一次 SPADs 修正后,设置了上电加载 SPADs 修正参数则模块不进行上电后 SPADs 修正操作,这样可以缩短模块初始化时间;通过上位机发送十六进制 A5 0A 01 B0 给模块,模块 LED 亮起,待熄灭校准完成。
(2)温度修正: 当模块工作环境温度变化超过 8 摄氏度,测距传感器灵敏度会发生改变,需进行一次温度修正;默认情况下,模块在每次上电后会进行一次温度修正操作,如模块工作环境温度恒定,可进手动进行一次温度修正后,设置模块上电后加载温度修正参数,这样可以缩短模块初始化时间;如用户开启了自动温度修正,则模块根据 MCU 温度超过 8度后,自行进行一次温度修正;通过上位机发送十六进制 A5 10 01 B6 给模块,模块 LED亮起,待熄灭校准完成。
(3)偏差校准: 当模块测距值与实际值之间存在一个固有的偏差时,可执行此操作。
偏差校准的指令=0xA5+0x21+指令值+sum,指令值为实际距离值。例如:模块测距值为
13CM,而实际值为 10CM,则指令中的指令值为十进制的 10;如需重新上电后加载该补偿值,需设置上电后加载偏差校准参数。通过上位机发送十六进制指令给模块,模块 LED 亮起,待熄灭校准完成。
(4)窗口校准: 当测距传感器上方被透明材质物体覆盖,模块在全量程测距的值不是线性的情况下,执行该操作。如下图所示:

X 轴为实际值,Y 轴为测量值。绿色虚线说明该材质对测距无影响或是传感器表面
无任务材质覆盖,蓝色线表明为轻度影响,红线为中度影响,绿色实线为重度影响。
窗口校准的指令=0xA5+0x32+指令值+sum;

指令值的选取:使用 17%灰色的反射率目标,则设模块与被测目标的距离为 S。对于
轻度影响的情况下,参见下图左侧蓝线,只要 S 在 AB 之间即可。指令值为实际距离值。中度影响的选取右测红线 AB 之间区域。如需重新上电后加载该补偿值,需设置上电后加载窗口校准参数。通过上位机发送十六进制指令给模块,模块 LED 亮起,待熄灭校准完成。

四、驱动代码及其配置(cubemx配置)

1.串口初始化

这里开了两个串口,串口1、2,分别用来给上位机传递数据以及获取数据

USART1:

USART2:

ps.连接GY56的串口初始波特率注意一下

2.发送指令

//串口打印函数
void UsartPrintf(UART_HandleTypeDef USARTx, char *fmt,...)
{
	unsigned char UsartPrintfBuf[296];
	va_list ap;
	unsigned char *pStr = UsartPrintfBuf;
	
	va_start(ap, fmt);
	vsnprintf((char *)UsartPrintfBuf, sizeof(UsartPrintfBuf), fmt, ap);							//格式化
	va_end(ap);
	
	while(*pStr != NULL)
	{
      HAL_UART_Transmit (&USARTx ,(uint8_t *)pStr++,1,HAL_MAX_DELAY );		
	}
 
}

//建立串口发送函数
void Usart_SendString(UART_HandleTypeDef USARTx, unsigned char *str, unsigned short len)//串口号,字符,长度
{
	unsigned short count = 0;
	
	for(; count < len; count++)
	{
		HAL_UART_Transmit (&USARTx ,(uint8_t *)str++,1,HAL_MAX_DELAY);									//发送数据
	}
}

//发送命令(这里地址内嵌好了)
void Uart_Send_com(uint8_t function,uint8_t value)
{
	uint8_t byte[4]={0};
	byte[0]=0xa5;
	byte[1]=function; //往该地址输出命令
	byte[2]=value; //指令值
	Usart_SendString(huart2,byte,4);
}

3.接收中断

#include "usart/bsp_usart.h"
#include "usart.h"
#include "stdio.h"
#include <stdarg.h>
#include "string.h"
unsigned char rx_p,rx_buff[40];
unsigned short rx_n,rx_pre;
_Bool gy56_receive=0;
static uint8_t gy56_buf[40],rebuf[40],rx_56;

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	rx_buff[rx_n++]=rx_p; //这个是用来接收其他字符串的,不用在意
	
	//GY_56接收
	rebuf[rx_56++]=rx_p;
	if(rebuf[0]!=0x5a)rx_56=0;
	if((rx_56==2)&&(rebuf[1]!=0x5a))rx_56=0;//帧头不对
	
	if(rx_56>3)
	{
		if(rx_56!=(rebuf[3]+5))
		{
			HAL_UART_Receive_IT(&huart2, (uint8_t *)&rx_p, 1);   //再开启接收中断
			return;
		}
		switch(rebuf[2])//接收完毕后处理
			{
				case 0x15:
					if(gy56_receive==0)//当数据处理完成后才接收新的数据
					{
						memcpy(gy56_buf,rebuf,9);//拷贝接收到的数据
						gy56_receive=1;//接收完成标志
					}
					break;
			
			}
			rx_56=0;//缓存清0
	}
	
	
	HAL_UART_Receive_IT(&huart2, (uint8_t *)&rx_p, 1);   //再开启接收中断
}

4.数据处理

void Gy56_Clear()
{
	rebuf[0]='\0';
	rx_56=0;
}

void Gy56_Init()
{
	Uart_Send_com(0x54,0x02); //开始测量
	Uart_Send_com(0x65,0x01); //连续输出
	Uart_Send_com(0x98,100); //设置上限阈值
	Uart_Send_com(0x87,1); //保存当前设置
}

void Uart_Proc()
{
	int i=0,sum=0,distance;
	if(gy56_receive) //接收完成
	{
		for(i=0;i<(gy56_buf[3]+4);i++)
		sum+=gy56_buf[i];
		
		if(sum==gy56_buf[i])
		{
			distance=gy56_buf[4]<<8|gy56_buf[5];
			UsartPrintf(huart1,"distance:%d\r\n",distance);
		}
		gy56_receive=0;
		Gy56_Clear();
	}
}

实验效果图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值