基于超声波的自动跟随小车

  • 超声波跟随原理
    • 代码
      • 1.电机部分
      • 2.PWM定义部分
      • 3.串口部分
      • 4.控制部分
      • 主函数

超声波跟随原理

下面介绍的超声波跟随小车,是可以进行直线跟随,可以转弯,可以避障等等的一款小车,接下来主要介绍小车的自动跟随部分。

基本原理:在小车的两端各安装一个超声波(非收发一体),人手持一个超声波模块。这样左侧与右侧离人的距离就构成了一个三角形。

距离A
距离B
左超声波
右超声波

当小车正对着人时,装在小车上的2个超声波模块,距离A=B。

当人左拐时,A必定小于B,同理当人右拐时,A大于B。

当人向前走时,A和B的距离必定大于设定距离。我们只需要控制好这几个距离即可。

代码

话不多说,直接上代码。
接下来以STM32为例,下面是小车电机部分的代码:
代码片

1.电机部分

#include "motor.h"void Motor_Init(void)    //电机引脚的初始化
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);   //使能GPIOB端口时钟GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;    //端口配置GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //50MHZGPIO_Init(GPIOB, &GPIO_InitStructure);                          //根据设定参数初始化GPIOB
}
/**************************************************************************
函数功能:赋值给PWM寄存器
入口参数:左轮PWM、右轮PWM
返回  值:无
**************************************************************************/
void Set_Pwm(int moto1,int moto2)
{if(moto1<0){                AIN2=0;AIN1=1;}else{              AIN2=1;AIN1=0;}PWMA=myabs(moto1);if(moto2<0)  {BIN1=1;BIN2=0;}else{BIN1=0;BIN2=1;}PWMB=myabs(moto2);
}/**************************************************************************
函数功能:绝对值函数
入口参数:int
返回  值:unsigned int
目    的:经过直立环和速度环以及转向环计算出来的PWM有可能为负值而只能赋给定时器PWM寄存器只能是正值。故需要对PWM进行绝对值处理
**************************************************************************/
int myabs(int a)
{          int temp;if(a<0)  temp =- a;  else temp = a;return temp;
}

2.PWM定义部分

#include "pwm.h"//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
//TIM1_PWM_Init(7199,0);//PWM频率=72000/(7199+1)=10Khzvoid TIM1_PWM_Init(u16 arr,u16 psc)
{  GPIO_InitTypeDef GPIO_InitStructure;TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;TIM_OCInitTypeDef  TIM_OCInitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);// RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);  //使能GPIO外设时钟使能//设置该引脚为复用输出功能,输出TIM1 CH1 CH4的PWM脉冲波形GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_11; //TIM_CH1 //TIM_CH4GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值    TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  不分频TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_timTIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能TIM_OCInitStructure.TIM_Pulse = 0;                            //设置待装入捕获比较寄存器的脉冲值TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;     //输出极性:TIM输出比较极性高TIM_OC1Init(TIM1, &TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMxTIM_OC4Init(TIM1, &TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMxTIM_CtrlPWMOutputs(TIM1,ENABLE);    //MOE 主输出使能 TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);  //CH1预装载使能    TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);  //CH4预装载使能   TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器TIM_Cmd(TIM1, ENABLE);  //使能TIM1
}

3.串口部分

void uart2_init(u32 bound)
{    //GPIO端口设置GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); //使能UGPIOA时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);  //使能USART2时钟//USART2_TX  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA2   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出GPIO_Init(GPIOA, &GPIO_InitStructure);//USART2_RX     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA3GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);//USART 初始化设置USART_InitStructure.USART_BaudRate = bound;//串口波特率USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;  //收发模式USART_Init(USART2, &USART_InitStructure);     //初始化串口2USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启串口接受中断USART_Cmd(USART2, ENABLE);                    //使能串口2
}/**************************************************************************
函数功能:串口3初始化
入口参数: bound:波特率
返回  值:无
**************************************************************************/
void uart3_init(u32 bound)
{    //GPIO端口设置GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);  //使能GPIOB时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);   //使能USART3时钟//USART3_TX  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB.10GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出GPIO_Init(GPIOB, &GPIO_InitStructure);//USART3_RX     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;//PB11GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOB, &GPIO_InitStructure);//USART 初始化设置USART_InitStructure.USART_BaudRate = bound;//串口波特率USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;    //收发模式USART_Init(USART3, &USART_InitStructure);     //初始化串口3USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启串口接受中断USART_Cmd(USART3, ENABLE);                    //使能串口3
}/**************************************************************************
函数功能:串口2接收中断
入口参数:无
返回  值:无
**************************************************************************/
void USART2_IRQHandler(void)
{   if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收到数据{  dat_left[num_left]=USART_ReceiveData(USART2); if(dat_left[0] != 0xA5) num_left = 0; else num_left++;//判断超声波串口接收的数据,如果是0XA5就接收,否则不予接收if(num_left==3)   //当接收到3个字节数之后,开始对数据进行解算并处理。得出最终的距离。{num_left = 0;distance_left = dat_left[1]<<8 | dat_left[2];}}
}
/**************************************************************************
函数功能:串口3接收中断
入口参数:无
返回  值:无
**************************************************************************/
void USART3_IRQHandler(void)
{   if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) //接收到数据{   dat_right[num_right]=USART_ReceiveData(USART3); if(dat_right[0] != 0xA5) num_right = 0;    else num_right++;//判断超声波串口接收的数据,如果是0XA5就接收,否则不予接收if(num_right==3) //当接收到3个字节数之后,开始对数据进行解算并处理。得出最终的距离。{      num_right = 0;distance_right = dat_right[1]<<8 | dat_right[2];}}
} 

4.控制部分

控制部分主要包括定时器中断、直线跟随、转向PD控制,很简单接下来的部分就自己写啦。

#include "control.h"
.......

主函数


#include "sys.h"
int main(void)
{ delay_init();                //=====延时函数初始化  uart1_init(128000);            //=====串口1初始化uart3_init(115200);            //=====通信超声波串口uart2_init(115200);            //=====通信超声波串口NVIC_Configuration();         //=====中断优先级分组,其中包含了所有的中断优先级的配置,方便管理和一次性修改。TIM3_Int_Init(99,7199);     //=====控制周期10ms          TIM1_PWM_Init(7199,0);        //=====10Khz PWMMotor_Init();                  //=====初始化与电机连接的硬件IO接口 while(1) {}
}

具体的内容也就这些了,如果还有什么技术问题想咨询可以留言,鉴于这是我的第一篇博客,因此有问必回,欢迎留言交流!想要快速回复的话也可以加我的个人微信咨询:supreme__fan

基于超声波的自动跟随小车相关推荐

  1. 自动跟随机器人:一种简易的自动跟随方案,自动跟随小车、自动跟随平衡小车、STM32、基于超声波的自动跟随小车

    目的:一种廉价的跟随方案,让大家都能够参与进来,技术难度不大,一些人也能够DIY一些属于自己的"跟随"机器人!并不是要做工业应用什么的.只是做出来玩玩~ / 1 / 介绍 先看视频 ...

  2. 基于STM32的三路超声波自动跟随小车

    三路超声波自动跟随小车 我个人一直都觉得自动跟随小车很酷,所以我的单片机课设就决定做这个了.其实现在网上有这个的代码不多,反正我怎么找也找不到,当时还没学完STM32的时候觉得好难实现,接近期末的时候 ...

  3. 使用超声波传感器采用图形化编程制作Arduino自动跟随小车

    在智能小车项目中,我们通过控制直流电机的正反转.刹车和转速来控制小车的行动. 在这台小车中,对直流电机发出的控制指令来自于Arduino主控板,而Arduino主控板的外部输入则来自于超声波传感器.灰 ...

  4. 基于单片机的自动分拣小车的设计--毕业设计参考

    基于单片机的自动分拣小车的设计 第1章.课题内容 1.系统应用单片机的基础功能,设计相关的电子电路,搭配合适的电子器件和传感器技术等,实现自动分拣的功能. 2.对方案的总体成份进行论证和设计. 3.根 ...

  5. 基于红外感应的远距离智能跟随小车,自动跟随小车

    跟随原理 下面介绍红外感应的跟随小车的自动跟随部分. 基本原理:在小车上安装一个红外接收器(能测量红外入射角的感应器),人手持一个红外发射模块. 根据不同的入射角,调整小车前进方向.若入射角在右边,就 ...

  6. 树莓派智能小车python论文_基于树莓派的自动驾驶小车,利用树莓派和tensorflow实现小车在赛道的自动驾驶...

    self_drive 基于树莓派的人工智能自动驾驶小车 Artificial intelligence automatic driving car based on raspberry pie git ...

  7. 基于树莓派搭建自动驾驶小车;Donkey Car组装硬件DIY

    还是想朝着人工智能方向靠一靠,之前研究图像有关的分类.识别,还是觉得太枯燥了.后来结合自己接触较多的Unity引擎,发现有自动驾驶用Unreal或者Unity之类的游戏引擎进行虚拟训练.接着发现了微软 ...

  8. 自动跟随小车c语言,基于OpenCV的智能小车运动轨迹跟踪方法研究

    摘要: 随着人工智能技术的快速发展,智能小车开发受到越来越多研究者的关注,也已经成为一个重要的研究方向,而解决智能小车在路径规划中行驶的运动故障重要手段是对其进行的视频监控,但是智能小车的视频监控只能 ...

  9. 自动跟随小车c语言,智能小车跟随系统的设计与制作.doc

    本科毕业论文(设计) 题目: 智能小车跟随系统的设计与制作 学院: 物理与电子科学学院 班级: 姓名: 指导教师: 职称: 完成日期: 年 月 日 PAGE \* MERGEFORMAT PAGE \ ...

最新文章

  1. Forrester发表2010年度MSS市场分析报告
  2. 如何分割字符串以便可以访问项目x?
  3. 【Lv1-Lesson002】He and She
  4. 洛谷 - P2774 方格取数问题(最小割-最大流+奇偶拆点)
  5. 【标签组件与图标 3.3】
  6. 【STM32】HAL库 STM32CubeMX教程十---DAC
  7. 【SpringClould】Spring Cloud Eureka源码分析
  8. iOS 评论APP撰写评论
  9. 大话中国骨干网(上)
  10. 期货基础知识 第四节 期货交易流程
  11. Nginx安装SSL证书
  12. 【冷知识】火车票座位分布知识点
  13. 【高等数学】空间曲线积分、斯托克斯公式、参数方程
  14. css所有缩写属性,CSS常见属性缩写与全写对比
  15. NSIS 头文件介绍_TextFunc.nsh(2)
  16. z370完美黑苹果_完工!搞掂i5-8600K 华硕PRIME Z370-P GTX 1060黑苹果安装
  17. 计算机的创新知识,创新高中计算机知识学习的策略分析
  18. Red Panda DEV-C++更新到6.7.5啦
  19. 1124: 成语接龙
  20. 任务调度之Oozie简介

热门文章

  1. Barsetto百胜图咖啡机引领办公咖啡潮流
  2. 怎么清洁计算机主机内部,电脑主机内部清洁的技巧
  3. Protel99SE的使用
  4. Vue(三)——数据绑定
  5. oracle 11g rac 状态,Oracle 11g RAC实例INTERMEDIATE Stuck Archiver状态解决
  6. 数字图像处理之低通滤波器实现原理及方法(Matlab)
  7. Python---蹒跚学步
  8. Unity Animation设置动画播放初始时间
  9. 计算机主板的天敌,“选择困难症”克星 Rolling让你不再纠结
  10. ubuntu9.10稳定运行QQ2008和迅雷