超声波避障小车原理就是通过给超声波模块超过10us的高电平信号,自动发送8个40KHZ的方波,来检测是不是有信号的返回,如果有信号的返回,那么就判断为前方有障碍物,并且通过舵机云台,来实现180度的旋转,检测左右两边是否的有障碍物,从而进行避障的功能。
说完原理,接下来就是根据各部件的原理来进行编程,我的超声波避障小车主要涉及了超声波HC-SR04模块,L298N电机驱动模块,舵机sg90模块。
首先是最基本的电机驱动模块的相关代码:
#include "bsp_motor.h"
#include "delay.h"
#include
void TIM4_PWM_Motor(unsigned int arr,unsigned int psc)
{
GPIO_InitTypeDef GPIO_InitStuct;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStuct;
TIM_OCInitTypeDef TIM_OCInitStuct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStuct.GPIO_Pin=GPIO_Pin_7; //左电机控制
GPIO_InitStuct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStuct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStuct);
GPIO_InitStuct.GPIO_Pin=GPIO_Pin_8; //左电机PWM
GPIO_InitStuct.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStuct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStuct);
GPIO_InitStuct.GPIO_Pin=GPIO_Pin_9; //右电机PWM
GPIO_InitStuct.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStuct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStuct);
GPIO_InitStuct.GPIO_Pin=GPIO_Pin_4; //右电机方向控制
GPIO_InitStuct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStuct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStuct);
TIM_TimeBaseInitStuct.TIM_ClockDivision=0;
TIM_TimeBaseInitStuct.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitStuct.TIM_Period=arr;
TIM_TimeBaseInitStuct.TIM_Prescaler=psc;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseInitStuct);
TIM_OCInitStuct.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStuct.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStuct.TIM_Pulse = 0;
TIM_OCInitStuct.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC3Init(TIM4, &TIM_OCInitStuct);
TIM_OC4Init(TIM4, &TIM_OCInitStuct);
TIM_CtrlPWMOutputs(TIM4,ENABLE);
TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable);
TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable);
TIM_Cmd(TIM4, ENABLE);
}
void car_run(unsigned char ucChannel,signed char cSpeed)
{
short PWM;
PWM = 7201 - fabs(cSpeed)*72;
switch(ucChannel)
{
case 0://右轮
TIM_SetCompare3(TIM4,PWM);
if (cSpeed>0)
GPIO_ResetBits(GPIOA,GPIO_Pin_4);
else if(cSpeed<0)
GPIO_SetBits(GPIOA,GPIO_Pin_4);
break;
case 1://左轮
TIM_SetCompare4(TIM4,PWM);
if (cSpeed>0)
GPIO_SetBits(GPIOB,GPIO_Pin_7);
else if (cSpeed<0)
GPIO_ResetBits(GPIOB,GPIO_Pin_7);
break;
}
}
void Run_Go(signed char speed,int time) //前进函数
{
signed char f_speed = - speed;
car_run(1,f_speed);
car_run(0,speed);
delay_ms(time);
}
void Run_stop(int time) //刹车函数
{
car_run(1,0);
car_run(0,0);
GPIO_ResetBits(GPIOA,GPIO_Pin_4);;
GPIO_ResetBits(GPIOB,GPIO_Pin_7);;
delay_ms(time);
}
void Run_left(signed char speed,int time) //左转
{
car_run(1,0);
car_run(0,speed);
delay_ms(time);
}
void Run_Spin_left(signed char speed,int time) //左旋转
{
signed char u_speed = 100 - speed;
car_run(1,speed);
car_run(0,u_speed);
delay_ms(time);
}
void Run_right(signed char speed,int time) //右转
{
signed char f_speed = - speed;
car_run(1,f_speed);
car_run(0,0);
delay_ms(time);
}
void Run_Spin_right(signed char speed,int time) //右旋转
{
signed char u_speed = 100 - speed;
signed char f_speed = - speed;
car_run(1,-u_speed);
car_run(0,f_speed);
delay_ms(time);
}
void Run_back(signed char speed,int time) //后退
{
signed char u_speed = 100- speed;
signed char f_speed = - u_speed;
car_run(1,u_speed);
car_run(0,f_speed);
delay_ms(time);
}
超声波检测距离的相关代码:
#include "bsp_hc.h"
#include "delay.h"
#define TRIG_PORT GPIOC
#define ECHO_PORT GPIOC
#define TRIG_PIN GPIO_Pin_0
#define ECHO_PIN GPIO_Pin_1
float UltrasonicWave_Distance;
void UltrasonicWave_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOC,&GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource1);
EXTI_InitStructure.EXTI_Line = EXTI_Line1;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void EXTI1_IRQHandler(void)
{
delay_us(10);
if(EXTI_GetITStatus(EXTI_Line1) != RESET)
{
TIM_SetCounter(TIM2,0);
TIM_Cmd(TIM2, ENABLE);
while(GPIO_ReadInputDataBit(GPIOC,ECHO_PIN));
TIM_Cmd(TIM2, DISABLE);
UltrasonicWave_Distance=TIM_GetCounter(TIM2)*5*34/200.0;
EXTI_ClearITPendingBit(EXTI_Line1);
}
}
void Timerx_Init(uint16_t arr,uint16_t psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseStructure.TIM_Period = 5000;
TIM_TimeBaseStructure.TIM_Prescaler =(7200-1);
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_ITConfig(TIM2,TIM_IT_Update|TIM_IT_Trigger,ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update );
}
}
int UltrasonicWave_StartMeasure(void)
{
int temp;
GPIO_SetBits(TRIG_PORT,TRIG_PIN);
delay_us(20);
GPIO_ResetBits(TRIG_PORT,TRIG_PIN);
temp = UltrasonicWave_Distance*10;
return temp;
}
舵机云台的相关代码:
#include "bsp_duoji.h"
void TIM5_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_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;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM5, &TIM_OCInitStructure);
TIM_CtrlPWMOutputs(TIM5,ENABLE);
TIM_OC1PreloadConfig(TIM5, TIM_OCPreload_Enable);
TIM_OC2Init(TIM5, &TIM_OCInitStructure);
TIM_ARRPreloadConfig(TIM5, ENABLE);
TIM_Cmd(TIM5, ENABLE);
}
最后是主函数:
#include "stm32f10x.h"
#include "bsp_motor.h"
#include "bsp_duoji.h"
#include "bsp_hc.h"
#include "delay.h"
void duojizhuantou(float angle)
{
angle=(u16)(50.0*angle/9.0+249.0);
TIM_SetCompare1(TIM5,angle);
}
int front_detection()
{
duojizhuantou(90);
delay_ms(100);
return UltrasonicWave_StartMeasure();
}
int left_detection()
{
duojizhuantou(175);
delay_ms(300);
return UltrasonicWave_StartMeasure();
}
int right_detection()
{
duojizhuantou(5);
delay_ms(300);
return UltrasonicWave_StartMeasure();
}
int main(void)
{
Timerx_Init(4999,7199);
HC_GPIO();
TIM4_PWM_Motor(7199,0);
TIM5_PWM_Init(9999,143);
while(1)
{
if(front_detection()<60 && front_detection()>0)
{
Run_stop(500);
Run_back(60,500);
Run_stop(1000);
left_detection();
delay_ms(500);
right_detection();
delay_ms(500);
if((left_detection() < 60 ) &&( right_detection() < 60 ))
{
Run_Spin_left(60,1000);
}
else if(left_detection() > right_detection())
{
Run_left(60,1000);
Run_stop(500);
}
else
{
Run_right(60,1000);
Run_stop(500);
}
}
else
{
Run_Go(60,10);
}
}
}