首页 > 其他分享 >GD32F470_GP2Y0A02YK0F 红外激光测距传感器 避障测距20-150cm模块移植

GD32F470_GP2Y0A02YK0F 红外激光测距传感器 避障测距20-150cm模块移植

时间:2024-04-10 12:33:07浏览次数:27  
标签:DMA 避障 20 150cm dma adc PORT CHANNEL ADC

2.4 红外测距传感器
GP2Y0A02YKOF是夏普的一款距离测量传感器模块。它由PSD(position sensitive detector)和IRED(infrared emitting diode)以及信号处理电路三部分组成。由于采用了三角测量方法,被测物体的材质、环境温度以及测量时间都不会影响传感器的测量精度。传感器输出电压值对应探测的距离。通过测量电压值就可以得出所探测物体的距离,所以这款传感器可以用于距离测量、避障等场合。
2.4.1 模块来源
采购链接:
GP2Y0A02YK0F 红外激光测距传感器 避障测距20-150cm
资料下载链接:
https://pan.baidu.com/s/11dDQHyYJfi0nNyC28vkpoA
资料提取码:qvpm

2.4.2 规格参数
工作电压:3.3-5V
工作电流:33MA
模块尺寸:37 x 21.6mm
输出方式: 模拟量输出
读取方式:ADC
管脚数量:3 Pin
工作电流:33MA
模块尺寸:37 x 21.6mm
输出方式: 模拟量输出
读取方式:ADC
管脚数量:3 Pin

2.4.3 移植过程
我们的目标是在梁山派GD32F470上能够判断前方障碍物的功能。首先要获取资料,查看数据手册应如何实现,再移植至我们的工程。
2.4.3.1 查看资料
红外测距传感器的输出是非线性的。每个型号的输出曲线都不同。所以,在实际使用前,最好能对所使用的传感器进行一下校正。对每个型号的传感器创建一张曲线图,以便在实际使用中获得真实有效的测量数据。下图是测距距离为20-150CM型号的输出曲线图。
在这里插入图片描述

从上图中,可以看到,当被探测物体的距离小于大约 15cm 的时候,输出电压急剧下降,也就是说从电压读数
来看,物体的距离应该是越来越远了。但是实际上并不是这样的,想象一下,你的机器人本来正在慢慢的
靠近障碍物,突然发现障碍物消失了,一般来说,你的控制程序会让你的机器人以全速移动,结果就是,"
砰"的一声。当然了,解决这个方法也不是没有,这里有个小技巧。只需要改变一下传感器的安装位置,使
它到机器人的外围的距离大于最小探测距离就可以了。

图2.2.3.1-2 可以避免免探测误差的安装

红外测距传感器的输出数据线是通过电压的变化来确定距离,我们可以使用ADC功能获取传感器的电压变化,将其转换为实际距离即可。电压距离转换公式见官方代码库链接:https://github.com/zoubworldArduino/ZSharpIR
找到我们20-150CM型号的传感器,在下方有换算公式。

在这里插入图片描述

2.4.3.2 引脚选择
想要使用ADC,需要确定使用的引脚是否有ADC外设功能。可以通过数据手册【GD32F450xx_Datasheet_Rev2.2.pdf】进行查看。文件下载见文件2.4.3.2-1 数据手册(GD32F450与GD32F470在功能与寄存器地址上没有区分)(梁山派开发板资料可在官网获取www.lckfb.com)
在这里插入图片描述

在数据手册的第28页结尾,是关于GD32F450Zx系列芯片引脚的功能定义示意图。
图2.4.3.2-2 引脚功能定义起始页
当前只有AO引脚需要使用到ADC接口,所以DO引脚可以使用开发板上其他的GPIO。这里选择使用PC2的附加ADC功能。使用ADC0的第12道输入通道。
图2.4.3.2-3 有ADC功能的引脚

红外测距立创·梁山派
VCC5V
GNDGND
DATAPC2

在这里插入图片描述
2.4.3.3 移植至工程
移植步骤中的导入.c和.h文件与上一节相同,只是将.c和.h文件更改为bsp_IRdistance.c与bsp_IRdistance.h。见2.2.3.3 移植至工程。这里不再过多讲述。移植完成后面修改相关代码。
在文件bsp_IRdistance.c中,编写如下代码。

/********************************************************************************
  * 文 件 名: bsp_IRdistance.c
  * 版 本 号: 初版
  * 修改作者: LC
  * 修改日期: 2023年04月06日
  * 功能介绍:          
  ******************************************************************************
  * 注意事项: 
*********************************************************************************/
#include "bsp_IRdistance.h"
#include "systick.h"
#include "stdio.h"
#include "math.h"
     

 //DMA缓冲区
uint16_t gt_adc_val[ SAMPLES ][ CHANNEL_NUM ]; 

/******************************************************************
 * 函 数 名 称:ADC_DMA_Init
 * 函 数 说 明:初始化ADC+DMA功能
 * 函 数 形 参:无
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
******************************************************************/
void ADC_DMA_Init(void)
{
   
    /* DMA初始化功能结构体定义 */
    dma_single_data_parameter_struct dma_single_data_parameter;
        
        /* 使能引脚时钟 */
    rcu_periph_clock_enable(RCU_IRDISTANCE_GPIO);                
        
        /* 使能ADC时钟 */
    rcu_periph_clock_enable(RCU_IRDISTANCE_ADC);                
  
        /* 使能DMA时钟 */
        rcu_periph_clock_enable(RCU_IRDISTANCE_DMA);
 
        /*        配置ADC时钟        */ 
    adc_clock_config(ADC_ADCCK_PCLK2_DIV4);        
        
        /*        配置PC2为浮空模拟输入模式        */
    gpio_mode_set(PORT_IRDISTANCE, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_IRDISTANCE); // PC2 : ADC012_IN12 
 
        /*        配置ADC为独立模式        */
    adc_sync_mode_config(ADC_SYNC_MODE_INDEPENDENT);
        
    /*        使能连续转换模式        */
    adc_special_function_config(PORT_ADC, ADC_CONTINUOUS_MODE, ENABLE);
         
    /*        使能扫描模式        */
    adc_special_function_config(PORT_ADC, ADC_SCAN_MODE, ENABLE);
   
        /*        数据右对齐        */        
    adc_data_alignment_config(PORT_ADC, ADC_DATAALIGN_RIGHT);
    
    /*        ADC0设置为规则组  一共使用 CHANNEL_NUM 个通道                */  
    adc_channel_length_config(PORT_ADC, ADC_REGULAR_CHANNEL, CHANNEL_NUM);
                
    /*        ADC规则通道配置:ADC0的通道11的扫描顺序为0;采样时间:15个周期                */  
        /*        DMA开启之后 gt_adc_val[x][0] = PC1的数据   */
    adc_regular_channel_config(PORT_ADC, 0, CHANNEL_ADC, ADC_SAMPLETIME_15);//PC2
 
        /*        ADC0设置为12位分辨率                */  
        adc_resolution_config(PORT_ADC, ADC_RESOLUTION_12B); 
        
        /*        ADC外部触发禁用, 即只能使用软件触发                */  
    adc_external_trigger_config(PORT_ADC, ADC_REGULAR_CHANNEL, EXTERNAL_TRIGGER_DISABLE);
    
    /*        使能规则组通道每转换完成一个就发送一次DMA请求                */  
    adc_dma_request_after_last_enable(PORT_ADC);  
    
        /*        使能DMA请求                */  
        adc_dma_mode_enable(PORT_ADC);
    
        /*        使能DMA                */          
        adc_enable(PORT_ADC);
    
        /*        等待ADC稳定                */  
        delay_1ms(1);
    
        /*        开启ADC自校准                */
    adc_calibration_enable(PORT_ADC); 
 
    /*        清除 DMA通道0 之前配置         */
    dma_deinit(PORT_DMA, CHANNEL_DMA);
   
        /*        DMA初始化配置         */
        dma_single_data_parameter.periph_addr = (uint32_t)(&ADC_RDATA(PORT_ADC));         //设置DMA传输的外设地址为ADC0基地址
        dma_single_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE;                         //关闭外设地址自增
        dma_single_data_parameter.memory0_addr = (uint32_t)(gt_adc_val);                         //设置DMA传输的内存地址为 gt_adc_val数组
        dma_single_data_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE;                         //开启内存地址自增(因为不止一个通道)
        dma_single_data_parameter.periph_memory_width = DMA_PERIPH_WIDTH_16BIT;             //传输的数据位 为 16位
        dma_single_data_parameter.direction = DMA_PERIPH_TO_MEMORY;                                         //DMA传输方向为 外设往内存
        dma_single_data_parameter.number = SAMPLES * CHANNEL_NUM;                                     //传输的数据长度为:每个通道采集30次 * 1个通道
        dma_single_data_parameter.priority = DMA_PRIORITY_HIGH;                                                 //设置高优先级
        dma_single_data_mode_init(PORT_DMA, CHANNEL_DMA, &dma_single_data_parameter);//将配置保存至DMA1的通道0
        
        /*        DMA通道外设选择                */
        /*        数据手册的195页根据PERIEN[2:0]值确定第三个参数,例是100 则为DMA_SUBPERI4          例是010 则为DMA_SUBPERI2         */
        /*        我们是ADC0功能,PERIEN[2:0]值为000,故为DMA_SUBPERI0                */
        dma_channel_subperipheral_select(PORT_DMA, CHANNEL_DMA, DMA_SUBPERI0);
 
        /*        使能DMA1通道0循环模式                */
        dma_circulation_enable(PORT_DMA, CHANNEL_DMA);
 
        /*        启动DMA1的通道0功能                */
        dma_channel_enable(PORT_DMA, CHANNEL_DMA); 
        
        /*        开启软件触发ADC转换                */
        adc_software_trigger_enable(PORT_ADC, ADC_REGULAR_CHANNEL); 
}
 

/******************************************************************
 * 函 数 名 称:Get_Adc_Dma_Value
 * 函 数 说 明:对DMA保存的数据进行平均值计算后输出电压值
 * 函 数 形 参:CHx 第几个扫描的数据
 * 函 数 返 回:对应扫描的电压值
 * 作       者:LC
 * 备       注:返回值最低0  最高4095
******************************************************************/
float Get_Adc_Dma_Value(char CHx)
{   
        unsigned char i = 0;
        unsigned int AdcValue = 0;
    double ret = 0;
    /* 因为采集 SAMPLES 次,故循环 SAMPLES 次 */
        for(i=0; i< SAMPLES; i++)
        {
        /*    累加    */
                AdcValue += gt_adc_val[i][CHx];
        }
    /* 求平均值 */
        ret = (double)AdcValue / SAMPLES;
    //手动减去电压误差 0.64
    ret = (((double)ret / 4095) * 3.3);
        return ret;
}

/******************************************************************
 * 函 数 名 称:Get_illume_Percentage_value
 * 函 数 说 明:计算红外测距的测量距离 
 * 函 数 形 参:无
 * 函 数 返 回:返回测量距离
 * 作       者:LC
 * 备       注:无
******************************************************************/
double Get_IRdistance_Distance(void)
{
    double adc_new = 0;
    double Distance = 0;
    adc_new = Get_Adc_Dma_Value(0);
    
//    根据官方代码库链接: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;
}

在文件bsp_encoder.h中,编写如下代码。

#ifndef _BSP_IRDISTANCE_H_
#define _BSP_IRDISTANCE_H_
 
#include "gd32f4xx.h"
 
 
#define RCU_IRDISTANCE_GPIO    RCU_GPIOC
#define RCU_IRDISTANCE_ADC     RCU_ADC0
#define RCU_IRDISTANCE_DMA     RCU_DMA1

#define PORT_DMA        DMA1
#define CHANNEL_DMA     DMA_CH0

#define PORT_ADC     ADC0
#define CHANNEL_ADC     ADC_CHANNEL_12

#define PORT_IRDISTANCE     GPIOC
#define GPIO_IRDISTANCE     GPIO_PIN_2


 //采样次数
#define SAMPLES         100
//采样通道数 
#define CHANNEL_NUM     1


extern uint16_t gt_adc_val[ SAMPLES ][ CHANNEL_NUM ];  //DMA缓冲区
 
void ADC_DMA_Init(void);
float Get_Adc_Dma_Value(char CHx);
double Get_IRdistance_Distance(void);

#endif

2.4.4 移植验证
在自己工程中的main主函数中,编写如下。

/********************************************************************************
  * 文 件 名: main.c
  * 版 本 号: 初版
  * 修改作者: LC
  * 修改日期: 2023年04月06日
  * 功能介绍:          
  ******************************************************************************
  * 注意事项:
*********************************************************************************/


#include "gd32f4xx.h"
#include "systick.h"
#include "bsp_usart.h"
#include "stdio.h"
#include "bsp_irdistance.h"

int main(void)
{
    nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);  // 优先级分组
        systick_config();                //滴答定时器初始化 1ms

    usart_gpio_config(115200U);
    ADC_DMA_Init();
    printf("ADC+DMA demo start\r\n");
    while(1)
    {
        printf("Distance = %.2f\r\n", Get_IRdistance_Distance() );
        
        delay_1ms(1000);
    }
}

移植现象:输出ADC值和换算后的实际距离。

在这里插入图片描述
移植成功示例,见文件2.4.4-1 。
文件2.4.4-1

标签:DMA,避障,20,150cm,dma,adc,PORT,CHANNEL,ADC
From: https://blog.csdn.net/weixin_46893326/article/details/137306724

相关文章

  • Inventor 2025安装教程
    下载链接:https://docs.qq.com/doc/DTEZIV2JEbEtHdGNC1.选中下载的安装包,右键选择解压到"Inventor2025"文件夹2.双击打开“Setup”文件夹3.选中“Setup.exe”右键以管理员身份运行4.软件正在初始化5.勾选“我同意...”,点击“下一步”6.选择安装位置,点击“......
  • 220V直降9V1A非隔离恒压WT5110
    220V直降9V1A非隔离恒压WT5110WT5110是一款高性能的原边控制器,主要适用于充电器和适配器的制造,其能够提供高精度的输出性能。该芯片具备多种工作模式,包括调幅控制和调频控制,这有助于提高系统的效率和可靠性。在恒流输出模式下,WT5110采用调频控制方式,并且集成了线电压和负载电......
  • 220V降5V1A非隔离降压应用WT5105
    220V降5V1A非隔离降压应用WT510520V降5V1A非隔离恒压芯片WT5105是一款集高效、安全、小巧于一身的电源管理解决方案,它的出现无疑为我们的日常生活带来了极大的便利。这个WT5105是个集成非隔离电源控制器,里面有650V的高雪崩能力的功率MOSFET。这玩意可以帮你简化外围器件,做出......
  • SQLSERVER 2019数据库(可疑) 数据修复案例
    2019数据库,在正常使用过程中,服务器突然断电,重新启动服务器后,数据库变为(可疑)。【数据恢复故障分析】由于数据库在正常读写操作过,服务器突然断电,导致数据库无法把所有缓冲中的数据写入到数据库文件中,所以会使数据内部索引及数据区损坏。【数据恢复过......
  • 小美的数组操作(美团2024届秋招笔试第二场编程真题)
    题面核心思想可以从示例中看出当sum/n能够整除时我们选择平均数作为众数即可不能整除时也就表示着不可能让所有数相同那么我们可以舍弃掉一个数a记剩下的数集合为b那么当b需要+1或-1后可能会剩下一些数那么我们可以选择让a去执行相反操作从而不影响b中剩......
  • P5327 [ZJOI2019]语言 解题报告
    oj:https://gxyzoj.com/d/gxyznoi/p/P35树上差分+线段树合并+树链剖分1.暴力从最基础的方法开始,暴力统计s-t上的点,然后用map直接统计,显然会T,20pts2.特殊性质测试点5,6保证了数据是一条链,将链上每一个节点编号为1-n对于每一次操作,可以记录其覆盖情况,设共有x个节点,有y个节......
  • Apifox 集成,Fast Request 2024.1.4 发布
    RestfulFastRequest是一个类似于Postman的IDEA插件。它是一个强大的restfulapi工具包插件,可以根据已有的方法帮助您快速、自动生成url和params。RestfulFastRequest=API调试工具+API管理工具+API搜索工具。它有一个漂亮的界面来完成请求、检查服务器响......
  • C++ - VS2019配置Qt开发环境
    下面正式介绍VS2019+Qt5.14.2开发环境的配置,其它版本类似,安装步骤如下:注意:首先自行安装好vs2019和qt5.14.2再执行以下步骤1、VisualStudio2019配置Qt环境(1)插件下载安装点击VS上方的菜单栏,选择“拓展—>管理拓展”进入管理拓展对话框,在右上方搜索qt,出现搜索结果后,选择......
  • 界面控件DevExtreme JS & ASP.NET Core 2024年度产品规划预览(二)
    在本文中我们将介绍今年即将发布的v24.1附带的主要特性,这些特性既适用于DevExtreme JavaScript(Angular、React、Vue、jQuery),也适用于基于DevExtreme的ASP.NETMVC/Core控件。注意:本文中列出的功能和特性说明官方当前/预计的发展计划,此信息仅供参考之用,其中列出的功能/产品可......
  • 20240410sql查询学习_1
    需求:查看合同信息表里面有多少合同编号是重复的SELECT合同编号,COUNT(*)FROM合同信息表GROUPBY合同编号HAVINGCOUNT(*)>1;结果:数量太多需求:列数太多,怎样看具体有多少个SELECTCOUNT(*)AStotalFROM(SELECT合同编号,COUNT(*)ASduplicate_count......