GP2Y0A02YKOF是夏普的一款距离测量传感器模块。它由PSD(position sensitive detector)和IRED(infrared emitting diode)以及信号处理电路三部分组成。由于采用了三角测量方法,被测物体的材质、环境温度以及测量时间都不会影响传感器的测量精度。传感器输出电压值对应探测的距离。通过测量电压值就可以得出所探测物体的距离,所以这款传感器可以用于距离测量、避障等场合。
一、模块来源
采购链接:
GP2Y0A02YK0F 红外激光测距传感器 避障测距20-150cm
资料下载链接:
https://pan.baidu.com/s/11dDQHyYJfi0nNyC28vkpoA
资料提取码:qvpm
二、规格参数
工作电压:3.3-5V
工作电流:33MA
模块尺寸:37 x 21.6mm
输出方式: 模拟量输出
读取方式:ADC
管脚数量:3 Pin
以上信息见厂家资料文件
三、移植过程
我们的目标是将例程移植至开发板上【能够判断前方障碍物的功能】。首先要获取资料,查看数据手册应如何实现读取数据,再移植至我们的工程。
1、查看资料
红外测距传感器的输出是非线性的。每个型号的输出曲线都不同。所以,在实际使用前,最好能对所使用的传感器进行一下校正。对每个型号的传感器创建一张曲线图,以便在实际使用中获得真实有效的测量数据。下图是测距距离为20-150CM型号的输出曲线图。
从上图中,可以看到,当被探测物体的距离小于大约 15cm 的时候,输出电压急剧下降,也就是说从电压读数来看,物体的距离应该是越来越远了。但是实际上并不是这样的,想象一下,你的机器人本来正在慢慢的 靠近障碍物,突然发现障碍物消失了,一般来说,你的控制程序会让你的机器人以全速移动,结果是,"砰"的一声。当然了,解决这个方法也不是没有,这里有个小技巧。只需要改变一下传感器的安装位置,使它到机器人的外围的距离大于最小探测距离就可以了。
红外测距传感器的输出数据线是通过电压的变化来确定距离,我们可以使用ADC功能获取传感器的电压变化,将其转换为实际距离即可。电压距离转换公式见官方代码库链接:https://github.com/zoubworldArduino/ZSharpIR找到我们20-150CM型号的传感器,在下方有换算公式。
2、引脚选择
3、移植至工程
移植步骤中的导入.c和.h文件与传感器章节的【DHT11温湿度传感器】相同,只是将.c和.h文件更改为bsp_IRdistance.c与bsp_IRdistance.h。这里不再过多讲述,移植完成后面修改相关代码。
在文件bsp_IRdistance.c中,编写如下代码。
/*
* 立创开发板软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:https://oshwhub.com/forum
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
* Change Logs:
* Date Author Notes
* 2024-03-29 LCKFB-LP first version
*/
#include "bsp_IRdistance.h"
#include "board.h"
#include "stdio.h"
#include "math.h"
/**********************************************************
* 函 数 名 称:IRdistance_GPIO_Init
* 函 数 功 能:初始化ADC
* 传 入 参 数:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:LP
**********************************************************/
void IRdistance_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStruct;
RCC_APB2PeriphClockCmd (RCC_IRDISTANCE_GPIO, ENABLE);
RCC_APB2PeriphClockCmd(RCC_ADC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_IRDISTANCE_AO;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//模拟输入
GPIO_Init(PORT_IRDISTANCE, &GPIO_InitStructure);
ADC_DeInit(IRDISTANCE_ADC);//ADC复位
// ADC 模式配置
ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;// 只使用一个ADC,独立模式
ADC_InitStruct.ADC_ScanConvMode = DISABLE ;// 禁止扫描模式,单通道不需要扫描
ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;// 连续转换模式
ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;// 软件触发转换
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;// 数据右对齐
ADC_InitStruct.ADC_NbrOfChannel = 1;// 转换通道1个
// 初始化ADC
ADC_Init(IRDISTANCE_ADC, &ADC_InitStruct);
// 配置ADC时钟PCLK2的6分频,即12MHz
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
// 配置 ADC 通道转换顺序为1,第一个转换,采样时间为55.5个时钟周期
// 通道为5
ADC_RegularChannelConfig(IRDISTANCE_ADC, IRDISTANCE_ADC_CHANNEL, 1, ADC_SampleTime_55Cycles5);
//ADC使能
ADC_Cmd(IRDISTANCE_ADC, ENABLE);
// 初始化ADC 校准寄存器
ADC_ResetCalibration(IRDISTANCE_ADC);
// 等待校准寄存器初始化完成
while (ADC_GetResetCalibrationStatus(IRDISTANCE_ADC));
// ADC开始校准
ADC_StartCalibration(IRDISTANCE_ADC);
// 等待校准完成
while (ADC_GetCalibrationStatus(IRDISTANCE_ADC));
// 使用软件触发ADC转换
ADC_SoftwareStartConvCmd(IRDISTANCE_ADC, ENABLE);
}
/**********************************************************
* 函 数 名 称:Get_Adc_Value
* 函 数 功 能:获得某个通道的值
* 传 入 参 数:CHx:通道数字
* Count:采集次数
* 函 数 返 回:无
* 作 者:LC
* 备 注:LP
**********************************************************/
float Get_Adc_Value(uint8_t CHx, uint8_t Count)
{
uint32_t adcValue = 0;
double ret = 0;
ADC_RegularChannelConfig(IRDISTANCE_ADC, CHx, 1, ADC_SampleTime_55Cycles5 );
ADC_SoftwareStartConvCmd(IRDISTANCE_ADC, ENABLE);
// 因为采集 SAMPLES 次,故循环 SAMPLES 次
for(int i = 0; i < Count; i++)
{
adcValue += ADC_GetConversionValue(IRDISTANCE_ADC);
}
// 求平均值
ret = (double)adcValue / Count;
ret = (((double)ret / 4095) * 3.5);
return ret;
}
/******************************************************************
* 函 数 名 称:Get_illume_Percentage_value
* 函 数 说 明:计算红外测距的测量距离
* 函 数 形 参:无
* 函 数 返 回:返回测量距离
* 作 者:LC
* 备 注:无
******************************************************************/
double Get_IRdistance_Distance(void)
{
double adc_new = 0;
double Distance = 0;
adc_new = Get_Adc_Value(IRDISTANCE_ADC_CHANNEL, 30);
// 根据官方代码库链接:https://github.com/zoubworldArduino/ZSharpIR
// 得到距离换算公式:
// 【GP2Y0A02YK0F:Using MS Excel, we can calculate function (For distance > 15cm) :
// Distance = 60.374 X POW(Volt , -1.16)】
Distance = 60.374 * pow(adc_new,-1.16);
return Distance;
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
在文件bsp_IRdistance.h中,编写如下代码。
/*
* 立创开发板软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:https://oshwhub.com/forum
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
* Change Logs:
* Date Author Notes
* 2024-03-29 LCKFB-LP first version
*/
#ifndef _BSP_IRDISTANCE_H_
#define _BSP_IRDISTANCE_H_
#include "stm32f10x.h"
#define RCC_IRDISTANCE_GPIO RCC_APB2Periph_GPIOA
#define RCC_ADC RCC_APB2Periph_ADC1
#define IRDISTANCE_ADC ADC1
#define IRDISTANCE_ADC_CHANNEL ADC_Channel_5
#define PORT_IRDISTANCE GPIOA
#define GPIO_IRDISTANCE_AO GPIO_Pin_5
void IRdistance_GPIO_Init(void);
float Get_Adc_Value(uint8_t CHx, uint8_t Count);
double Get_IRdistance_Distance(void);
#endif2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
四、移植验证
在main.c中输入代码如下:
/*
* 立创开发板软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:https://oshwhub.com/forum
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
* Change Logs:
* Date Author Notes
* 2024-03-29 LCKFB-LP first version
*/
#include "stm32f10x.h"
#include "board.h"
#include "bsp_uart.h"
#include "stdio.h"
#include "bsp_IRdistance.h"
int main(void)
{
board_init();
uart1_init(115200);
IRdistance_GPIO_Init();
printf("ADC demo start\r\n");
while(1)
{
printf("Distance = %.2f\r\n", Get_IRdistance_Distance() );
delay_ms(1000);
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
上电效果:
移植成功案例代码下载链接: