三路超声波自动跟随小车

我个人一直都觉得自动跟随小车很酷,所以我的单片机课设就决定做这个了。其实现在网上有这个的代码不多,反正我怎么找也找不到,当时还没学完STM32的时候觉得好难实现,接近期末的时候终于搞出来了,虽然不是很理想,但还是不错滴,看一下效果。

这个是只有超声波传感器的,看上去有点简约,可以实现基本的自动跟随功能了


这个是接了火焰传感器、烟雾传感器、蜂鸣器、红外避障模块等等,看上去酷多了。

小车的系统结构图

代码部分

超声波初始化函数:

可能因为板子的端口有冲突,没有把三个超声波的引脚定义到同一组GPIO口上,但是这并不影响。

void CH_SR04_Init(void)
{GPIO_InitTypeDef GPIO_InitStructer;TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructer;RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);/*TRIG触发信号*/GPIO_InitStructer.GPIO_Speed=GPIO_Speed_50MHz;GPIO_InitStructer.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitStructer.GPIO_Pin=GPIO_Pin_8 |GPIO_Pin_6;GPIO_Init(GPIOB, &GPIO_InitStructer);/*ECOH回响信号*/GPIO_InitStructer.GPIO_Mode=GPIO_Mode_IN_FLOATING;GPIO_InitStructer.GPIO_Pin=GPIO_Pin_9 |GPIO_Pin_7;GPIO_Init(GPIOB, &GPIO_InitStructer);/*定时器TIM2初始化*/TIM_DeInit(TIM4);TIM_TimeBaseInitStructer.TIM_Period=999;//定时周期为1000TIM_TimeBaseInitStructer.TIM_Prescaler=71; //分频系数72TIM_TimeBaseInitStructer.TIM_ClockDivision=TIM_CKD_DIV1;//不分频TIM_TimeBaseInitStructer.TIM_CounterMode=TIM_CounterMode_Up;TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructer);TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);//开启更新中断NVIC_Config();TIM_Cmd(TIM4,DISABLE);//关闭定时器使能}

我把右边的超声波分开定义了,你也可以自己修改。

void right(void){    //右边超声波的引脚声明GPIO_InitTypeDef GPIO_InitStructer;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);/*TRIG触发信号*/GPIO_InitStructer.GPIO_Speed=GPIO_Speed_50MHz;GPIO_InitStructer.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitStructer.GPIO_Pin=GPIO_Pin_3;GPIO_Init(GPIOA, &GPIO_InitStructer);/*ECOH回响信号*/GPIO_InitStructer.GPIO_Mode=GPIO_Mode_IN_FLOATING;GPIO_InitStructer.GPIO_Pin=GPIO_Pin_4;GPIO_Init(GPIOA, &GPIO_InitStructer);    }

下面这部分就是超声波工作的过程了,也是核心代码。注释也解释得很清楚了,需要注意的是这里的超声波是测量了五次才返回一个值的,这样做的好处是起到一个滤波的作用,使得超声波的值更精确、稳定。但是他也有不好的地方,在小车前进过程可能会识别很慢或者转向失败,因为三个超声波是使用同一个定时器的,分时复用的,也就是同一时刻只能有一个超声波工作,所以如果处理器不够快的话可以把次数降低一点,我就是值检测一次的,效果也还行。左右超声波的函数也是一样的,把函数名改一下就好了。

//中间超声波的工作过程
float Senor_Using(void)
{float length=0,sum=0;u16 tim;uint i=0;/*测5次数据计算一次平均值*/while(i!=5){PBout(8)=1; //拉高信号,作为触发信号delay_us(25); //高电平信号超过10usPBout(8)=0;/*等待回响信号*/while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_9)==RESET);TIM_Cmd(TIM4,ENABLE);//回响信号到来,开启定时器计数i+=5; //每收到一次回响信号+1,收到5次就计算均值while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_9)==SET);//回响信号消失TIM_Cmd(TIM4,DISABLE);//关闭定时器tim=TIM_GetCounter(TIM4);//获取计TIM4数寄存器中的计数值,一边计算回响信号时间length=(tim+overcount*1000)/58.0;//通过回响信号计算距离sum=length+sum;TIM4->CNT=0; //将TIM4计数寄存器的计数值清零overcount=0; //中断溢出次数清零delay_ms(10);}length=sum/5;return length;//距离作为函数返回值
}

这个是定时器的中断服务函数,避免因为距离过长,定时器中的值溢出。

void TIM4_IRQHandler(void) //中断,当回响信号很长是,计数值溢出后重复计数,用中断来保存溢出次数
{if(TIM_GetITStatus(TIM4,TIM_IT_Update)!=RESET){TIM_ClearITPendingBit(TIM4,TIM_IT_Update);//清除中断标志overcount++;}
}

PWM电机驱动代码:

#include "moter.h"
void CarGo(void)
{TIM_SetCompare1(TIM3 , 300);  //数值越大速度越慢TIM_SetCompare2(TIM3 , 900);TIM_SetCompare3(TIM3 , 300);  TIM_SetCompare4(TIM3 , 900);
}void CarStop(void)
{TIM_SetCompare1(TIM3 , 900);TIM_SetCompare2(TIM3 , 900);TIM_SetCompare3(TIM3 , 900);   TIM_SetCompare4(TIM3 , 900);
}void CarBack(void)
{TIM_SetCompare1(TIM3 , 900);TIM_SetCompare2(TIM3 , 400);TIM_SetCompare3(TIM3 , 900);   TIM_SetCompare4(TIM3 , 400);
}void CarLeft(void)
{TIM_SetCompare1(TIM3 , 900);TIM_SetCompare2(TIM3 , 200);TIM_SetCompare3(TIM3 , 200);TIM_SetCompare4(TIM3 , 900);
}void CarBigLeft(void)
{TIM_SetCompare1(TIM3 , 900);TIM_SetCompare2(TIM3 , 100);TIM_SetCompare3(TIM3 , 100);TIM_SetCompare4(TIM3 , 900);
}void CarRight(void)
{TIM_SetCompare1(TIM3 , 200);TIM_SetCompare2(TIM3 , 900);TIM_SetCompare3(TIM3 , 900);TIM_SetCompare4(TIM3 , 200);}void CarBigRight(void)
{TIM_SetCompare1(TIM3 , 100);TIM_SetCompare2(TIM3 , 900);TIM_SetCompare3(TIM3 , 900);TIM_SetCompare4(TIM3 , 100);}void TIM3_PWM_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3 , ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);TIM_TimeBaseStructure.TIM_Period = 899;TIM_TimeBaseStructure.TIM_Prescaler = 0;TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseStructure.TIM_ClockDivision = 0;TIM_TimeBaseInit(TIM3 , &TIM_TimeBaseStructure);//端口复用GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  GPIO_Init(GPIOA, &GPIO_InitStructure);   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  GPIO_Init(GPIOB, &GPIO_InitStructure);   //PWM通道1TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;TIM_OCInitStructure.TIM_Pulse = 900;TIM_OC1Init(TIM3 , &TIM_OCInitStructure);TIM_OC1PreloadConfig(TIM3 , TIM_OCPreload_Enable);//PWM通道2TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;TIM_OCInitStructure.TIM_Pulse = 900;TIM_OC2Init(TIM3 , &TIM_OCInitStructure);TIM_OC2PreloadConfig(TIM3 , TIM_OCPreload_Enable);//PWM通道3TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;TIM_OCInitStructure.TIM_Pulse = 900;TIM_OC3Init(TIM3 , &TIM_OCInitStructure);TIM_OC3PreloadConfig(TIM3 , TIM_OCPreload_Enable);//PWM通道4TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;TIM_OCInitStructure.TIM_Pulse = 900;TIM_OC4Init(TIM3 , &TIM_OCInitStructure);TIM_OC4PreloadConfig(TIM3 , TIM_OCPreload_Enable);TIM_Cmd(TIM3 , ENABLE);
}

主函数

while(1){    length_res[0]=Senor_Using();delay_ms(100);if(length_res[0]>100.00){CarGo();}if(length_res[0]<=40.00){CarBack();//先后退一段距离delay_ms(200);CarBack();//先后退一段距离delay_ms(200);     length_res[0] =Senor_Using();//再次测量前方距离delay_ms(50);length_res[1]=Senor_Using_left();delay_ms(10);if(length_res[1]<=110.00&&length_res[0]>150.00){         CarLeft();delay_ms(10);}length_res[2]=Senor_right();if(length_res[2]<=110.00&&length_res[0]>150.00){CarRight();delay_ms(10);}           }length_res[1]=Senor_Using_left();delay_ms(10);if(length_res[1]<=110.00&&length_res[0]>150.00){         CarLeft();delay_ms(50);CarLeft();delay_ms(50);if(length_res[1]<=30){CarRight();delay_ms(50);}}length_res[2]=Senor_right();if(length_res[2]<=110.00&&length_res[0]>150.00){CarRight();delay_ms(50);CarRight();delay_ms(50);if(length_res[2]<=30){CarLeft();delay_ms(50);}}   }

完成的工程代码已上传,有积分的土豪可以直接下载,链接:工程代码点这里

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

  1. 【毕业设计】基于超声波智能跟随小车 - 单片机 物联网 stm32 c51

    文章目录 1 项目简介 2 课题背景 3 硬件说明 3.1 小车硬件设计 3.2 小车底座 3.3 无线收发器 3.4 超声波模块 3.5 直流电机和电源 3.6 目标携带装置 3.7 整体电路图 4 ...

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

    基于超声波的自动跟随小车 超声波跟随原理 代码 1.电机部分 2.PWM定义部分 3.串口部分 4.控制部分 主函数 超声波跟随原理 下面介绍的超声波跟随小车,是可以进行直线跟随,可以转弯,可以避障等 ...

  3. 毕业设计 单片机超声波智能跟随小车 - 物联网 嵌入式 stm32

    文章目录 1 项目简介 2 课题背景 3 硬件说明 3.1 小车硬件设计 3.2 小车底座 3.3 无线收发器 3.4 超声波模块 3.5 直流电机和电源 3.6 目标携带装置 3.7 整体电路图 4 ...

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

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

  5. 基于stm32的两轮自平衡小车4(软件调试篇)

    本篇是软件调试篇,接上一篇硬件篇:基于stm32的两轮自平衡小车3(硬件篇),本篇内容是对硬件部分的软件实现,具体模块详见目录.这里先上效果:转B站 目录 定时器PWM驱动程序 定时器编码器模式驱动程 ...

  6. Arduino毕业设计——基于Arduino+PID+AI的自动驾驶小车控制系统设计与实现(毕业论文+程序源码)——自动驾驶小车控制系统

    基于Arduino+PID+AI的自动驾驶小车控制系统设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于Arduino+PID+AI的自动驾驶小车控制系统设计与实现,文章末尾附有本毕业设计的 ...

  7. 基于stm32的两轮自平衡小车3(硬件篇)

    此篇为硬件篇,接上一篇"基于stm32的两轮自平衡小车2(原理篇)".包含自行设计电路板原理图与PCB电路图的过程.详见目录. 目录 stm32管脚分配 硬件原理图 PCB电路图 ...

  8. 基于51单片机的超声波避障小车设计(含Proteus仿真)

    超声波避障程序随处可见,基于51单片机的超声波避障小车也很成熟,但是完整的Proteus仿真并不容易找到开源资料. 这次主要给大家分享其Proteus仿真部分. 涉及到的模块有:超声波模块(hc-sr ...

  9. 基于STM32的最简易蓝牙遥控小车

    基于STM32的最简易蓝牙遥控小车 硬件准备 硬件连接 STM32cubeMX配置 代码部分 视频演示 本篇博客主要针对的读者为有一定单片机基础,但是第一次自制蓝牙遥控小车的小白同学,所用物件型号选择 ...

最新文章

  1. mysql left join超时,MySQL 行锁超时排查方法优化
  2. Linux下Sniffer程序的实现
  3. 7-69 超市促销 (6 分)
  4. python一个中文占几个字节_python中英文字母和中文汉字所占的字节
  5. jQuery UI 应用不同Theme的办法
  6. I/O操作不占用CPU的任何线程
  7. 让.net 2.0支持并行计算
  8. NASA 美国国家航空航天局开源项目列表
  9. Citrix XenDesktop 4.0 Setup Wizard crash
  10. Laravel 5.4 首次搭建,从 clone 到运行成功
  11. 2019版PHP自动发卡平台源码
  12. PKI/CA工作原理及架构
  13. 彻底卸载vscode Linux,Linux环境中Visual Studio Code 安装配置及其卸载(详细教程)
  14. 关于Maven,这些应该够用了
  15. My97DatePicker时间控件在asp.net的应用
  16. 计算机ifand函数补考科目,Excel函数公式:逻辑函数IF、AND、OR、NOT、IFERROR实用技巧解读...
  17. Ubuntu终端Terminator的安装与配置使用
  18. 浏览器兼容性问题(IE9+;PC)
  19. [个人资料整理]游戏类型总结
  20. M3D GIS三维数字沙盘可视化交互地理信息系统开发教程第44课

热门文章

  1. 秒杀服务------技术点及亮点
  2. 数据中心服务器备份,三分钟掌握数据中心“容灾和备份的区别”
  3. 计算机用户文件夹加密,怎么把文件夹加密(怎么给电脑文件夹加密)
  4. android moba源码,Unity3D MOBA游戏 完整源码 uMOBAv 1.34
  5. 【语音分析】短时自相关基音周期检测+LPC预测增益计算【含Matlab源码 1517期】
  6. nbr服务器端代码的编译和运行
  7. 人生苦短,我用Python。
  8. 专利的18个好处,看这一篇就够了!
  9. Oracle gsd服务是什么,如何处理11gR2 RAC下oc4j和gsd服务为OFFLINE状态 | 旺旺知识库
  10. Google File Stream(谷歌云端硬盘)安装在Windows Server(服务器版本)上