[文章]基于搭载 OpenHarmony 避障小车心得体会

阅读量0
0
5
文章提供:福州市凌睿智捷电子有限公司

一、 避障小车简介
这是一款基于OpenHarmony系统和小凌派-RK2206开发板的避障小车。同时,小车上搭载了超声波测距模块、舵机模块、红外寻迹模块、直流电机模块。
具体实验成果展示如上:

二、 避障小车模块介绍
小凌派-RK2206开发板的示意图
2.jpg


小凌派配置了一个E53外接拓展口,这是E53接口的原理图:
1.png


这是E53模块的原理图:
3.png


1. 直流电机模块
直流电机模块由E53模块上的L9110S驱动芯片进行驱动。L9110S驱动芯片所引出的引脚对应接口的GPIO0_B7、GPIO0_B6,另一块驱动芯片对应GPIO1_D0、GPIO0_A5。我们对相应的GPIO引脚进行初始化并设置为上拉模式。
  1.     //右直流电机 IA GPIO0_PB7
  2.     PinctrlSet(GPIO0_PB7, MUX_FUNC0, PULL_UP, DRIVE_KEEP);
  3.     LzGpioInit(GPIO0_PB7);

  4. //右直流电机 IB GPIO0_PB6
  5.     PinctrlSet(GPIO0_PB6, MUX_FUNC0, PULL_UP, DRIVE_KEEP);
  6.     LzGpioInit(GPIO0_PB6);

  7. //左直流电机 IB GPIO1_PD0
  8.     PinctrlSet(GPIO1_PD0, MUX_FUNC0, PULL_UP, DRIVE_KEEP);
  9.     LzGpioInit(GPIO1_PD0);

  10.     //左直流电机 IA GPIO0_PA5
  11.     PinctrlSet(GPIO0_PA5, MUX_FUNC0, PULL_UP, DRIVE_KEEP);
  12.     LzGpioInit(GPIO0_PA5);
复制代码

通过阅读L9110S的芯片手册可以得到以下真值表:
4.png

通过真值表,我们可以通过对IO口的输出来控制直流电机的正转、反转还有停止
GPIO0_B7
GPIO0_B6
电机状态
GPIO1_D0
GPIO0_A5
电机状态
H
L
正转
H
L
正转
L
H
反转
L
H
反转
H
H
停止
H
H
停止
L
L
停止
L
L
停止
2. 超声波测距模块
超声波测距模块用来计算出模块到前方障碍物的距离。采用IO口TRIG触发测距,给最少10us的高电平信号。模块自动发送8个40khz的方波,自动检测是否有信号返回;有信号返回,通过IO口ECHO输出一个高电平,同时开定时器计时,当此口变为低电平时就可以读定时器的值,高电平持续的时间就是超声波从发射到返回的时间。
模块Trig对应引脚GPIO_B0,Echo对应引脚GPIO_B1,对这两个引脚进行初始化
  1.     // Echo 超声波传感器
  2.     PinctrlSet(GPIO0_PB1, MUX_FUNC0, PULL_KEEP, DRIVE_KEEP);
  3.     LzGpioInit(GPIO0_PB1);
  4.     LzGpioSetDir(GPIO0_PB1, LZGPIO_DIR_IN);

  5.     // Trig 超声波传感器
  6.     PinctrlSet(GPIO0_PB0, MUX_FUNC0, PULL_KEEP, DRIVE_KEEP);
  7.     LzGpioInit(GPIO0_PB0);
  8.     LzGpioSetDir(GPIO0_PB0, LZGPIO_DIR_OUT);
  9.     LzGpioSetVal(GPIO0_PB0, LZGPIO_LEVEL_LOW);
复制代码
触发信号
  1. //通过Trig发送触发信号
  2. LzGpioSetVal(GPIO0_PB0, LZGPIO_LEVEL_HIGH);
  3. HAL_DelayUs(20);
  4. LzGpioSetVal(GPIO0_PB0, LZGPIO_LEVEL_LOW);
复制代码
获取定时器计数器当前值
  1. while (1)
  2.     {
  3.         LzGpioGetVal(GPIO_8, &value);
  4.         //获取上升沿的定时器计数器当前值
  5.         if (value == LZGPIO_LEVEL_HIGH && flag == 0)
  6.         {
  7.             m_echo_info.time_rise = *m_ptimer5_current_value_low;
  8.             m_echo_info.flag = EECHO_FLAG_CAPTURE_FALL;
  9.             flag = 1;
  10.         }
  11.         //获取下降沿的定时器计数器当前值
  12.         if (value == LZGPIO_LEVEL_LOW && flag == 1)
  13.         {
  14.             m_echo_info.time_fall = *m_ptimer5_current_value_low;
  15.             m_echo_info.flag = EECHO_FLAG_CAPTURE_SUCCESS;
  16.             break;
  17.         }
  18.     }
复制代码
上升沿和下降沿的节拍数差计算距离。其中,系统时钟为40MHz,超声波速度为340米/秒,高电平时间宽度为超声波的往返之和,所以实际距离 = 节拍数差 / 40MHz / 340(米/秒) / 2(往返2次)。具体计算代码如下:
  1. if (m_echo_info.flag == EECHO_FLAG_CAPTURE_SUCCESS)
  2. {/* 如果是采集成功,则计算距离 */
  3.      if (m_echo_info.time_rise <= m_echo_info.time_fall)
  4.     {
  5.        time_diff = m_echo_info.time_fall - m_echo_info.time_rise;
  6.     }
  7.      else
  8.    {
  9.      time_diff = 0xFFFFFFFF - m_echo_info.time_rise + m_echo_info.time_fall + 1;
  10.    }
  11.     }
  12.     float f_time = (float)time_diff;
  13.     float f_freq = (float)ECHO_TIMER_FREQ;
  14.     distance = f_time / f_freq * 170.0 * 100.0;
复制代码
3. 舵机模块
舵机模块用来控制超声波测距模块测量左右方向的距离,舵机引脚为GPIO0_B4,对GPIO0_B4进行初始化。
  1.         //舵机
  2.     PinctrlSet(GPIO0_PB4, MUX_FUNC0, PULL_KEEP, DRIVE_KEEP);
  3.     LzGpioInit(GPIO0_PB4);
  4.     LzGpioSetDir(GPIO0_PB4, LZGPIO_DIR_OUT);
复制代码
通过模拟PWM波让舵机工作。具体代码如下:
  1. void set_angle(unsigned int duty)
  2. {
  3.     LzGpioSetDir(GPIO0_PB4, LZGPIO_DIR_OUT);
  4.     LzGpioSetVal(GPIO0_PB4, LZGPIO_LEVEL_HIGH);
  5.     HAL_DelayUs(duty);
  6.     LzGpioSetVal(GPIO0_PB4, LZGPIO_LEVEL_LOW);
  7.     HAL_DelayUs(20000 - duty);
  8. }
复制代码
4. 红外寻迹模块
红外寻迹模块,在避障小车中的功能是防止小车意外掉落。红外寻迹模块与小凌派的GPIO0_A2、GPIO0_C4连接,对这两个引脚进行初始化。
  1.     //初始化PA2 红外传感器
  2.     PinctrlSet(GPIO0_PA2, MUX_FUNC0, PULL_UP, DRIVE_KEEP);
  3.     LzGpioInit(GPIO0_PA2);
  4.     LzGpioSetDir(GPIO0_PA2, LZGPIO_DIR_IN);
  5.     LzGpioSetVal(GPIO0_PA2, LZGPIO_LEVEL_HIGH);

  6.     //初始化PC7 红外传感器
  7.     PinctrlSet(GPIO0_PC4, MUX_FUNC0, PULL_UP, DRIVE_KEEP);
  8.     LzGpioInit(GPIO0_PC4);
  9.     LzGpioSetDir(GPIO0_PC4, LZGPIO_DIR_IN);
  10.     LzGpioSetVal(GPIO0_PC4, LZGPIO_LEVEL_HIGH);
复制代码

三、 避障小车功能实现
通过小凌派开发板自带的按键启动小车的避障功能
  1. void car_ Obstacle_avoidance(void)
  2. {
  3.     float m_distance = 0.0;
  4.     regress_middle();

  5.     /*获取前方物体的距离*/
  6.     m_distance = GetDistance();
  7.     car_where_to_go(m_distance);
  8.     osDelay(20);
  9. }
复制代码

通过超声波测距模块测量前方距离来判断小车接下来要运动的方向。若距离大于等于20cm继续前进。若距离小于20cm,先停止再后退0.5s,再继续进行测距,再进行判断。通过两个红外寻迹传感器可以防止小车掉落,当红外传感器输出为高电平时,小车就会停止前进,并且重新寻找安全方向。
  1. static void car_where_to_go(float distance)
  2. {
  3.     LzGpioValue io_status_left;
  4.     LzGpioValue io_status_right;

  5.     LzGpioGetVal(GPIO0_PA2, &io_status_left);
  6.     LzGpioGetVal(GPIO0_PC4, &io_status_right);
  7.     if (io_status_left == 0 || io_status_right == 0)
  8.     {
  9.         if (io_status_left == 0 && io_status_right != 0)
  10.         {
  11.             car_stop();
  12.             LOS_Msleep(500);
  13.             car_backward();
  14.             LOS_Msleep(500);
  15.             car_stop(); // meet wall
  16.             car_rightward();
  17.             LOS_Msleep(800);
  18.             car_stop(); // meet wall
  19.         }
  20.         else if (io_status_left != 0 && io_status_right == 0)
  21.         {
  22.             car_stop();
  23.             LOS_Msleep(500);
  24.             car_backward();
  25.             LOS_Msleep(500);
  26.             car_stop(); // meet wall
  27.             car_leftward();
  28.             LOS_Msleep(800);
  29.             car_stop(); // meet wall
  30.         }
  31.         else if (io_status_left == 0 || io_status_right == 0)
  32.         {
  33.             car_stop();
  34. car_backward();
  35.             LOS_Msleep(500);
  36.             car_stop(); // meet wall

  37.         }
  38.     }
  39.     else if (distance < DISTANCE_BETWEEN_CAR_AND_OBSTACLE)
  40.     {
  41.         car_stop();
  42.         LOS_Msleep(500);
  43.         car_backward();
  44.         printf("This is backwardrn");
  45.         LOS_Msleep(500);
  46.         car_stop();
  47.         unsigned int ret = engine_go_where();
  48.         printf("ret is %drn", ret);
  49.         if (ret == CAR_TURN_LEFT)
  50.         {
  51.             car_left();
  52.             LOS_Msleep(800);
  53.         }
  54.         else if (ret == CAR_TURN_RIGHT)
  55.         {
  56.             car_right();
  57.             LOS_Msleep(800);
  58.         }
  59.         car_stop();
  60.     }
  61.     else
  62.     {
  63.         car_forward();
  64.         printf("This is forwardrn");
  65.     }
  66. }
复制代码
四、 心得体会
通过使用OpenHarmony操作系统 + 小凌派-RK2206开发板来控制小车完成距离检测、前进、后退、左转、右转、判断算法等功能,实现了避障小车的基本功能。经过这一次实验测试,加强我个人对OpenHarmony的理解,实在是一次不错的学习体验,特此记录!

回帖

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉
链接复制成功,分享给好友