查看: 765|回复: 1

【瑞萨RA4系列开发板体验】超声波测距模块在RA4M2上的应用

[复制链接]

116

主题

134

帖子

3778

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
3778
发表于 2023-2-8 15:56:37 | 显示全部楼层 |阅读模式
【瑞萨RA4系列开发板体验】超声波测距模块在RA4M2上的应用
作者:hehung

前言
本来之前申请试用的时候,打算做一个室内可燃气体检测设备的,但是我的可燃气体传感器居然坏掉了,采集不到ADC数值了,遂只能修改项目,完整了这个测距仪小作品,算是对本次试用的一个作品总结。
手头有一个超声波测距模块,遂使用超声波模块来编写一个举例测试器,本文使用超声波模块US-100是实现了超声波测距的功能。本文实现了一下功能:
  • 本文基于KEIL开发环境;
  • 本文使用的除超声波功能之外的功能都是以及之前的发帖内容进一步开发,有需要请参考之前的文章;
  • 本文实现了超声波模块测距并通过OLED显示距离。


硬件资料
US-100介绍

通过搜索US-100超声波测距模块的资料,了解到该模块可以通过两种方式进行驱动。
方式一:使用普通GPIO进行驱动Trig触发,然后通过接收echo的反馈波形长度就可以知道超声波测量物体的距离了,该方式需要结合定时器使用,并且自行计算返回距离,使用起来较复杂;
方式二:使用串口,给US-100的TX发送0x55,等待反馈数据,反馈数据为两个单字节数据,第一个字节为距离高位,第二个数据为距离低位,反馈距离为Data0<<8 | Data1, 单位是mm,详细资料见下图。


使用串口模式还可以获取超声波模块的温度,这个温度是用来补偿超声波数据,用来进行校准的,我们也可以通过发送0x50获取内部温度数据,温度数据为单字节,获取的数值-45就是真实的温度。

为了设计的便捷性,本文使用了串口的模式,使用串口模式需要将US-100后边的跳线帽连接上。


单片机硬件
确定使用UART连接之后,查看一下数据手册,看看还有没有串口可以供我们使用。我们可以使用SCI0的TXD0以及RXD0.


RASC配置
打开RASC,过程不在赘述。
在Pins页面配置SCI0,如下图:


在Stacks页面下配置串口,方式同我之前发布的帖子。
不再赘述,详见配置页面。




代码设计
配置完成之后点击生成配置代码,然后开始代码设计。
过程比较简单,与我之前的文章类似,我新建了app_us100.c自己app_us100.h,逻辑详见代码。

app_us100.c
在该文件中实现了如下功能函数:
  • US100相关引脚初始化(及UART初始化);
  • 开始测距函数;
  • 获取测的距离函数;
  • 开始获取温度函数;
  • 获取温度值函数;

  1. /*
  2. @hehung
  3. 2022-12-10
  4. */
  5. #include "hal_data.h"
  6. #include "app_dac.h"
  7. #include <stdio.h>

  8. static volatile uint8_t uart0_send_mode = 0;
  9. static volatile bool uart0_send_complete_flag = false;
  10. static volatile bool uart0_recv_complete_flag = false;
  11. static volatile uint32_t uart0_recv_char = '\0';
  12. static volatile uint8_t uart0_recv_cnt = 0U;

  13. // callback function for uart0
  14. void uart0_notification(uart_callback_args_t * p_args)
  15. {
  16.         if (p_args->event == UART_EVENT_TX_COMPLETE)
  17.         {
  18.                 uart0_send_complete_flag = true;
  19.         }
  20.         else if (p_args->event == UART_EVENT_RX_CHAR)
  21.         {
  22.                 if (uart0_send_mode == 0U)       
  23.                 {
  24.                         ++uart0_recv_cnt;
  25.                         if (uart0_recv_cnt == 2U)
  26.                         {
  27.                                 uart0_recv_cnt = 0U;
  28.                                 uart0_recv_char = (uart0_recv_char << 8U) | p_args->data;
  29.                                 uart0_recv_complete_flag = true;
  30.                         }
  31.                         else
  32.                         {
  33.                                 uart0_recv_char = p_args->data;
  34.                         }                       
  35.                 }
  36.                 else
  37.                 {
  38.                         uart0_recv_char = p_args->data;
  39.                         uart0_recv_complete_flag = true;
  40.                 }
  41.         }
  42. }

  43. // Uart0 initialize
  44. void US100_Init(void)
  45. {
  46.         fsp_err_t err = FSP_SUCCESS;
  47.        
  48.         /* Open the transfer instance with initial configuration. */
  49.     err = R_SCI_UART_Open(&g_uart0_ctrl, &g_uart0_cfg);
  50.     assert(FSP_SUCCESS == err);
  51. }

  52. /* Start US100 distance test */
  53. void US100_StartDistance(void)
  54. {
  55.         fsp_err_t err = FSP_SUCCESS;
  56.         uint8_t send_ch;
  57.        
  58.         /* 0x50 is command for get the distance from US-100 */
  59.         send_ch = 0x55U;

  60.         uart0_send_mode = 0U;
  61.         err = R_SCI_UART_Write(&g_uart0_ctrl, (uint8_t *)&send_ch, 1);
  62.         if(FSP_SUCCESS != err)
  63.                 __BKPT();
  64. }

  65. /* Start US100 temperature test */
  66. void US100_StartTemperature(void)
  67. {
  68.         fsp_err_t err = FSP_SUCCESS;
  69.         uint8_t send_ch;
  70.        
  71.         /* 0x50 is command for get the temperature from US-100 */
  72.         send_ch = 0x50U;

  73.         uart0_send_mode = 1U;
  74.         err = R_SCI_UART_Write(&g_uart0_ctrl, (uint8_t *)&send_ch, 1);
  75.         if(FSP_SUCCESS != err)
  76.                 __BKPT();
  77. }

  78. /* Read the distance from US100 */
  79. uint8_t US100_ReadDistance(uint16_t *distance)
  80. {
  81.         if ((true == uart0_recv_complete_flag) && (0U == uart0_send_mode))
  82.         {
  83. //                printf ("Distance reveived is %d\n", uart0_recv_char);
  84.                 *distance = uart0_recv_char & 0xFFFFU;
  85.                 uart0_recv_complete_flag = false;
  86.                 return 1;
  87.         }
  88.         else
  89.         {
  90.                 return 0;
  91.         }
  92.        
  93. }

  94. /* Read the temperature from US100 */
  95. uint8_t US100_ReadTemperature(uint8_t *temp)
  96. {
  97.         if ((true == uart0_recv_complete_flag) && (1U == uart0_send_mode))
  98.         {
  99. //                printf ("Temperature reveived is %d\n", uart0_recv_char);
  100.                 *temp = uart0_recv_char & 0xFFU;
  101.                 uart0_recv_complete_flag = false;
  102.                 return 1;
  103.         }
  104.         else
  105.         {
  106.                 return 0;
  107.         }
  108. }
复制代码
app_us100.h
  1. /*
  2. @hehung
  3. 2022-12-10
  4. */

  5. #ifndef APP_US100_H_
  6. #define APP_US100_H_

  7. #include "stdint.h"

  8. extern void US100_Init(void);
  9. extern void US100_StartDistance(void);
  10. extern void US100_StartTemperature(void);
  11. extern uint8_t US100_ReadDistance(uint16_t *distance);
  12. extern uint8_t US100_ReadTemperature(uint8_t *temp);

  13. #endif
复制代码


主函数
主函数中实现了相关模块初始化,发送测距函数开始距离测试,获取测试结果,发送温度获取命令,获取温度值,并通过OLED显示,每500ms更新一次数据。
  1. uint16_t dist;
  2. uint8_t temp;

  3. void hal_entry(void)
  4. {
  5.         char disp_str[16];
  6.        
  7.         /* Initialize the uart for implement the 'printf' and 'scanf' */
  8.         Uart_Init();
  9.         /* Initialize the os and some tasks */
  10. //        Task_Create();
  11.         /* Initialize the I2c */
  12.         I2c_Init();
  13.         /* Initialize the OLED */
  14.         OLED_Init();
  15.         /* Initialize the ADC */
  16.         Adc_Init();
  17.         /* initialize the US100 - Ultrasonic module */
  18.         US100_Init();
  19.        
  20.         OLED_ShowString(12, 0, (const uint8_t*)"R7FA4M2AD3CFP", 16, 1);
  21. //    OLED_ShowHzStringRow(32, 24, (const char*)"电子发烧友", 1);
  22.     OLED_ShowString(0, 16, (const uint8_t*)"elecfans", 16, 1);
  23.         OLED_ShowString(64, 16, (const uint8_t*)"|hehung", 16, 1);
  24.     OLED_Refresh_Gram();
  25.        
  26.         while (1)
  27.         {
  28.                 US100_StartDistance();
  29.                 while (!US100_ReadDistance(&dist))
  30.                 {
  31.                         R_BSP_SoftwareDelay(100, BSP_DELAY_UNITS_MICROSECONDS);
  32.                 }
  33.                        
  34.                 US100_StartTemperature();
  35.                 while (!US100_ReadTemperature(&temp))
  36.                 {
  37.                         R_BSP_SoftwareDelay(100, BSP_DELAY_UNITS_MICROSECONDS);
  38.                 }
  39.                
  40.                 sprintf(disp_str, "Dis:%03dmm", (dist));
  41.                 OLED_ShowString(0, 32, (const uint8_t*)disp_str, 16, 1);
  42.                 sprintf(disp_str, "Temp:%03dC", ((int)temp - 45));
  43.                 OLED_ShowString(0, 48, (const uint8_t*)disp_str, 16, 1);
  44.                 OLED_Refresh_Gram();
  45.                        
  46.                 R_BSP_SoftwareDelay(500, BSP_DELAY_UNITS_MILLISECONDS);
  47.         }

  48. #if BSP_TZ_SECURE_BUILD
  49.     /* Enter non-secure code */
  50.     R_BSP_NonSecureEnter();
  51. #endif
  52. }
复制代码


效果演示

我测试了20cm以及10cm,发现测试存在一定的误差,距离越远,误差越大。
20cm测试结果,可以看到,测试结果为21cm左右,存在1cm的误差。


10cm测试结果,可以看到,测试结果误差较大,但是还是偏大。
从测试结果可以看到,获取的温度数值明显不对,当前室内温度也就十几度,但是温度测试出来是20多度,估计是温度的影响导致测试距离存在一定的误差,但是在测试精度要求不是很严重的场合,超声波测距还是可以的,或者自己外接温度传感器对距离进行补偿。


回复

使用道具 举报

3

主题

195

帖子

1485

积分

金牌会员

Rank: 6Rank: 6

积分
1485
发表于 2023-3-14 10:32:38 | 显示全部楼层

不错学习一下
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

用户排行榜

RA助手

主题: 116帖子:134精华:0

RA_Lance

主题: 92帖子:132精华:9

lugl

主题: 44帖子:133精华:0

xujiwei263

主题: 16帖子:73精华:0

books咦

主题: 11帖子:11精华:2

Juggernaut

主题: 9帖子:95精华:0
快速回复 返回顶部 返回列表