Infrared Distance Sensor
The GP2Y0A02YKOF is a distance measurement sensor module from Sharp. It consists of three parts: a PSD (position sensitive detector), an IRED (infrared emitting diode), and a signal processing circuit. Because the triangulation method is used, the material of the measured object, the ambient temperature, and the measurement time will not affect the sensor's measurement accuracy. The sensor output voltage value corresponds to the detected distance. By measuring the voltage value, the distance of the detected object can be obtained, so this sensor can be used for distance measurement, obstacle avoidance, and other applications.
Module Source
Purchase link: https://item.taobao.com/item.htm?spm=a230r.1.14.16.7def2810sScrt7&id=580318855469&ns=1&abbucket=12 Materials download link: https://pan.baidu.com/s/11dDQHyYJfi0nNyC28vkpoA Materials extraction code: qvpm
Specifications
Operating voltage: 3.3-5V Operating current: 33mA Module dimensions: 37 x 21.6mm Output method: Analog output Read method: ADC Number of pins: 3 Pin
Principle Analysis
The output of the infrared distance sensor is non-linear. The output curve of each model is different. Therefore, before actual use, it is best to calibrate the sensor being used. Create a curve chart for each model of sensor so that real and effective measurement data can be obtained during actual use. The figure below is the output curve for the 20-150CM distance model.
From the figure above, it can be seen that when the distance of the detected object is less than about 15cm, the output voltage drops sharply, which means that from the voltage reading, the distance of the object should be getting farther and farther. But in fact this is not the case. Imagine that your robot is slowly approaching an obstacle and suddenly finds that the obstacle has disappeared. Generally, your control program will make your robot move at full speed, and the result is a "bang". Of course, there are solutions to this problem, and here is a small trick. Just change the installation position of the sensor so that its distance to the outer periphery of the robot is greater than the minimum detection distance.
The output data line of the infrared distance sensor determines the distance through voltage changes. We can use the ADC function to obtain the sensor's voltage changes and convert it into actual distance. For the voltage-distance conversion formula, see the official code repository link: https://github.com/zoubworldArduino/ZSharpIR Find our 20-150CM model sensor, and the conversion formula is listed below.
Porting Process
Pin Selection
Port to Project
Our goal is to port the example to the ESP32-S3 dev board. Complete driver code has been provided for you. Follow the steps below to complete the porting. For detailed instructions on creating folders and new .c and .h files, refer to section 1.4.2 in the [DHT11 Temperature and Humidity Sensor] chapter; we will not repeat it here. Just note that here we change the file names bsp_dht11.c and bsp_dht11.h to bsp_IRdistance.c and bsp_IRdistance.h, and the folder name to IRdistance.
Write Code
Write the following in the bsp_IRdistance.c file:
#include "bsp_IRdistance.h"
#include "stdio.h"
#include "math.h"
esp_adc_cal_characteristics_t *adc_chars;
void delay_ms(unsigned int ms)
{
vTaskDelay(ms / portTICK_PERIOD_MS);
}
void delay_us(unsigned int us)
{
ets_delay_us(us);
}
/******************************************************************
* Function Name: ADC_DMA_Init
* Function Description: Initialize ADC+DMA function
* Function Parameters: None
* Function Return: None
* Author: LC
* Notes: None
******************************************************************/
void ADC_IRdistance_Init(void)
{
adc1_config_width(width);// 12-bit resolution
//ADC_ATTEN_DB_0: indicates reference voltage is 1.1V
//ADC_ATTEN_DB_2_5: indicates reference voltage is 1.5V
//ADC_ATTEN_DB_6: indicates reference voltage is 2.2V
//ADC_ATTEN_DB_11: indicates reference voltage is 3.3V
//adc1_config_channel_atten( channel,atten);// Set channel 0 and 3.3V reference voltage
// Allocate memory
adc_chars = calloc(1, sizeof(esp_adc_cal_characteristics_t));
// Initialize ADC characteristics so that it can correctly calculate conversion results and compensation factors
esp_adc_cal_characterize(unit, atten, width, DEFAULT_VREF, adc_chars);
}
/******************************************************************
* Function Name: Get_Adc_Dma_Value
* Function Description: Calculate the average of the data saved by DMA and output the voltage value
* Function Parameters: CHx the number of the scanned data
* Function Return: The voltage value of the corresponding scan
* Author: LC
* Notes: Return value minimum 0, maximum 4095
******************************************************************/
float Get_Adc_Value(char CHx)
{
unsigned char i = 0;
unsigned int AdcValue = 0;
double ret = 0;
/* Because SAMPLES times are collected, loop SAMPLES times */
for(i=0; i< SAMPLES; i++)
{
/* Accumulate */
AdcValue += adc1_get_raw(channel);
}
/* Calculate average */
ret = (double)AdcValue / SAMPLES;
//Manually subtract the voltage error 0.64
ret = (((double)ret / 4095) * 3.3);
return ret;
}
/******************************************************************
* Function Name: Get_illume_Percentage_value
* Function Description: Calculate the measured distance of infrared distance measurement
* Function Parameters: None
* Function Return: Returns the measured distance
* Author: LC
* Notes: None
******************************************************************/
double Get_IRdistance_Distance(void)
{
double adc_new = 0;
double Distance = 0;
adc_new = Get_Adc_Value(channel);
// According to the official code repository link: https://github.com/zoubworldArduino/ZSharpIR
// The distance conversion formula is:
// [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) -4.8;
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
Write the following in the bsp_IRdistance.h file:
#ifndef _BSP_IRDISTANCE_H_
#define _BSP_IRDISTANCE_H_
#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_rom_sys.h"
#include "esp_timer.h"
#include "driver/uart.h"
#include "rom/ets_sys.h"
#include "esp_system.h"
#include "driver/gptimer.h"
#include "esp_log.h"
#include "freertos/queue.h"
#include "driver/spi_master.h"
#include "nvs_flash.h"
#include "esp_adc/adc_cali_scheme.h"
#include "esp_adc/adc_cali.h"
#include "driver/adc.h"
#include "esp_adc_cal.h"
#define DEFAULT_VREF 1100 //Default reference voltage, unit: mV
#define channel ADC_CHANNEL_0 // ADC measurement channel
#define width ADC_WIDTH_BIT_12 // ADC resolution
#define atten ADC_ATTEN_DB_11 // ADC attenuation
#define unit ADC_UNIT_1 // ADC1
#define GPIO_DATA 1
#define SAMPLES 20 // Number of acquisition cycles
void delay_ms(unsigned int ms);
void ADC_IRdistance_Init(void);
float Get_Adc_Value(char CHx);
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
33
34
35
36
37
38
39
40
41
42
At this point, the porting is complete. Please proceed to section 2.5 for porting verification.
Porting Verification
Enter the following code in main.c:
#include <stdio.h>
#include "bsp_IRdistance.h"
void app_main(void)
{
ADC_IRdistance_Init();
printf("IRdistance 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
Power-on effect:
Driver code:
File Download
📌 Materials Download Center (click to jump)
📌 In the Materials Download Center -> Module Porting Materials Download, inside the compressed package of this chapter.