前言
提示:这里可以添加本文要记录的大概内容:
智能小车是一种能够自主移动、感知周围环境并根据环境变化做出反应的设备。
然而,智能小车在移动过程中可能会遇到各种障碍物,如墙壁、家具等,这时就需要具备避障功能的智能小车来规避障碍。本篇文章将介绍如何通过添加摇头避障功能来提升智能小车的避障能力。
一、sg90舵机
1. sg90舵机的介绍
之前的文章中,我们学习使用了PWM实现控制电动机的速度.关于控制舵机的角度,与PWM控制速度差不多原理.只需要控制占空比就可以随意的控制旋转角度
最便宜的舵机sg90,常用三根或者四根接线,黄色为PWM信号控制
二、添加摇头功能
1.硬件接线
在上一篇接线的基础上
添加接线:
sg90 – PB9
2.CubeMX配置
我们复制上一节的项目,在他的基础上添加配置就行了
我们通过查询芯片手册,关于PB9的信息
发现PB9的备用功能默认位置是定时器4的通道4.
在这边我们接着将他频率设置为20Hz,记得要将自动重加载打开,勾选内部时钟
3. 添加代码
上篇博客中,我们在代码中,添加了一个全局变量,用于判断处于哪个模式,这篇博客,我们在模式中添加一个避障模式#define BZMS 3
在main函数中,对mode进行判断,是否为避障模式,是避障模式就一直走避障的代码.
在main.c中
// 先控制舵机实左右摇头
if(mode == BZMS)
{
sgMiddle();
HAL_Delay(1000);
sgRight();
HAL_Delay(1000);
sgMiddle();
HAL_Delay(1000);
sgLeft();
HAL_Delay(1000);
}
sg90.c中
#include "gpio.h"
#include "tim.h"
#include "sg90.h"
void sg90Init(void)
{
// 启动定时器4的通道4
HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_4);
//设置占空比
__HAL_TIM_SetCompare(&htim4,TIM_CHANNEL_4,16);
}
void sgMiddle(void)
{
__HAL_TIM_SetCompare(&htim4,TIM_CHANNEL_4,16);
}
void sgRight(void)
{
__HAL_TIM_SetCompare(&htim4,TIM_CHANNEL_4,5);
}
void sgLeft(void)
{
__HAL_TIM_SetCompare(&htim4,TIM_CHANNEL_4,25);
}
成功实现,摇头功能后,就可以考虑将超声波测距也封装进去了.
三. 添加超声波测距功能
1. 硬件接线
超声波测距模块是用来测量距离的一种产品,通过发送和收超声波,利用时间差和声音传播速度,
计算出模块到前方障碍物的距离。
超声波测距模块是用来测量距离的一种产品,通过发送和收超声波,利用时间差和声音传播速度,
计算出模块到前方障碍物的距离。
超声波的时序图
引脚接线
Trig – PB7
Echo – PB8
2. cubeMX配置
PB7为输出端口.设置为output
PB8为接收端口,设置为input
由于我们定时器2已经用过
这里我们使用定时器3
将预分频系数设置为71,由于公式(PSC+1)/时钟
通过将PSC设置为71,可算出计时器计时一下相当于一微秒
3.添加代码
sr04.c
#include "sr04.h"
#include "gpio.h"
#include "tim.h"
// 微妙级延时
void TIM3_Delay_us(uint16_t n_us)
{
// 使能定时器3
__HAL_TIM_ENABLE(&htim3);
// 设置值为0
__HAL_TIM_SetCounter(&htim3,0);
while(__HAL_TIM_GetCounter(&htim3) <= n_us);
// 关闭定时器
__HAL_TIM_DISABLE(&htim3);
}
// 获取距离
double get_distance(void)
{
int cnt = 0;
// Trig ,给Trig端口至少10us的高电平
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_SET);
TIM3_Delay_us(15);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_RESET);
// 等待echo被拉高
while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_8) == GPIO_PIN_RESET);
__HAL_TIM_ENABLE(&htim3); // 打开定时器
__HAL_TIM_SetCounter(&htim3,0); // 设置为0开始定时
// 等待echo被拉低,发送完毕
while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_8) == GPIO_PIN_SET);
//波回来的那一下,我们开始停止定时器
HAL_TIM_Base_Stop(&htim3);
//4. 计算出中间经过多少时间
cnt = __HAL_TIM_GetCounter(&htim3);
//5. 距离 = 速度 (340m/s)* 时间/2(计数1次表示1us)
return (cnt*340/2*0.000001*100); //单位:cm
}
main.c
if(mode == BZMS)
{
sgMiddle();
HAL_Delay(50);
mi_distance = get_distance();
if(mi_distance >= 45)
{
// 前进
goForward();
HAL_Delay(300);
}else if(mi_distance <= 15)
{
goback();
HAL_Delay(300);
}else
{
// 停止
stop();
// 测左距离
sgLeft();
HAL_Delay(300);
left_distance = get_distance();
sgMiddle();
HAL_Delay(300);
// 测右距离
sgRight();
HAL_Delay(300);
right_distance = get_distance();
if(right_distance >= left_distance)
{
turnRightfull();
HAL_Delay(300);
}
if(left_distance > right_distance)
{
turnLeftfull();
HAL_Delay(300);
}
}
}