> 技术文档 > 单片机:实现超声波避障小车(附带源码)

单片机:实现超声波避障小车(附带源码)


单片机:实现超声波避障小车

1. 项目背景与目标

随着自动驾驶技术和机器人技术的不断发展,超声波避障小车成为了基础的机器人应用之一。本项目的目标是设计并实现一辆通过超声波传感器检测障碍物并进行避障的小车。我们将使用单片机(如STM32)控制超声波模块(如HC-SR04)来检测前方的障碍物,并控制电机驱动小车进行前进、后退、转弯等动作,从而实现避障功能。

2. 硬件设计
2.1 硬件组件
  1. 单片机:如STM32、AVR或8051。本项目以STM32为例。
  2. 超声波模块:HC-SR04或类似模块,用于测量前方障碍物的距离
  3. 直流电机:用于驱动小车移动。
  4. 电机驱动模块:如L298N、L293D,用于控制电机的启停和方向。
  5. 电源:为单片机和电机提供适当的电源,通常为5V或12V。
  6. 轮子与底盘:用于构建小车的物理结构。
  7. 按键(可选):用于手动控制小车的启动、停止或其他功能。
2.2 硬件连接
  • 超声波模块连接

    • VCC:连接到单片机的3.3V或5V电源。
    • GND:接地。
    • Trig:连接到单片机的任意GPIO引脚,用于发射超声波。
    • Echo:连接到单片机的任意GPIO引脚,用于接收回波信号。
  • 电机驱动模块连接

    • IN1、IN2:连接到单片机的GPIO引脚,用于控制电机的正反转。
    • ENA:控制电机启停。
    • VCC、GND:分别连接电源和接地。
    • 电机连接:连接电机的两个端口,用于驱动小车。
3. 软件设计
3.1 超声波测距原理

HC-SR04超声波模块通过发射和接收超声波来测量距离。它的工作原理如下:

  1. Trig引脚发出一个短暂的高电平脉冲,超声波模块发射超声波信号。
  2. 超声波遇到障碍物后反射回来,经过一定的时间后,Echo引脚返回高电平脉冲。
  3. 根据Echo引脚返回高电平的时间,可以计算出超声波的传播时间,从而得出距离。

测量距离的公式为: 距离=传播时间×声速2\\text{距离} = \\frac{\\text{传播时间} \\times \\text{声速}}{2}距离=2传播时间×声速​ 假设声速为343米/秒(在标准温度下)。

3.2 避障算法
  1. 距离判断:通过超声波测距获取前方的距离,如果距离小于设定的阈值,表示前方有障碍物。
  2. 前进:如果没有障碍物,小车继续前进。
  3. 后退:如果前方障碍物距离过近,后退一定距离。
  4. 转弯:如果前方有障碍物,可以转向左或右进行避障,直到障碍物不再阻挡路径。
3.3 电机控制
  • 控制电机的方向和速度,可以通过PWM信号调整速度。使用电机驱动模块(如L298N)控制电机的前进、后退和转弯。
3.4 程序设计思路
  1. 初始化超声波模块:配置Trig和Echo引脚,定时发射超声波信号并接收回波。
  2. 测量距离:定期测量前方的距离,并与设定的阈值进行比较。
  3. 控制小车动作:根据测量结果判断是否需要前进、后退或转弯。
  4. 电机驱动控制:通过控制电机驱动模块的输入端口来实现小车的运动。
3.5 代码实现

以下是基于STM32单片机的超声波避障小车的代码示例:

#include \"stm32f4xx_hal.h\"// 定义超声波模块引脚#define TRIG_PIN GPIO_PIN_9#define ECHO_PIN GPIO_PIN_8#define TRIG_PORT GPIOA#define ECHO_PORT GPIOA// 定义电机控制引脚#define MOTOR1_IN1 GPIO_PIN_0#define MOTOR1_IN2 GPIO_PIN_1#define MOTOR2_IN1 GPIO_PIN_2#define MOTOR2_IN2 GPIO_PIN_3#define MOTOR_PORT GPIOB// 设置超声波传感器的测量时间间隔#define MEASURE_INTERVAL 100 // 100ms测量一次// 定义电机的控制指令#define STOP 0#define FORWARD 1#define BACKWARD 2#define TURN_LEFT 3#define TURN_RIGHT 4// 定义距离阈值(单位:厘米)#define DISTANCE_THRESHOLD 20// 声速(假设为343m/s)#define SOUND_SPEED 343// 定义定时器和延时函数void Delay_ms(uint32_t delay);// 超声波测距函数uint32_t Get_Distance(void) { uint32_t pulseTime = 0; uint32_t distance = 0; // 发送Trig信号 HAL_GPIO_WritePin(TRIG_PORT, TRIG_PIN, GPIO_PIN_SET); Delay_ms(10); // 延时10us HAL_GPIO_WritePin(TRIG_PORT, TRIG_PIN, GPIO_PIN_RESET); // 等待Echo信号 while (HAL_GPIO_ReadPin(ECHO_PORT, ECHO_PIN) == GPIO_PIN_RESET); // 等待Echo高电平 uint32_t startTime = HAL_GetTick(); // 获取起始时间 while (HAL_GPIO_ReadPin(ECHO_PORT, ECHO_PIN) == GPIO_PIN_SET); // 等待Echo低电平 uint32_t endTime = HAL_GetTick(); // 获取结束时间 pulseTime = endTime - startTime; // 获取Echo高电平时间 // 计算距离 distance = (pulseTime * SOUND_SPEED) / 2; // 声波的传播时间计算得到的距离 // 返回距离(单位:厘米) return distance;}// 电机控制函数void Motor_Control(uint8_t direction) { switch (direction) { case STOP: HAL_GPIO_WritePin(MOTOR_PORT, MOTOR1_IN1, GPIO_PIN_RESET); HAL_GPIO_WritePin(MOTOR_PORT, MOTOR1_IN2, GPIO_PIN_RESET); HAL_GPIO_WritePin(MOTOR_PORT, MOTOR2_IN1, GPIO_PIN_RESET); HAL_GPIO_WritePin(MOTOR_PORT, MOTOR2_IN2, GPIO_PIN_RESET); break; case FORWARD: HAL_GPIO_WritePin(MOTOR_PORT, MOTOR1_IN1, GPIO_PIN_SET); HAL_GPIO_WritePin(MOTOR_PORT, MOTOR1_IN2, GPIO_PIN_RESET); HAL_GPIO_WritePin(MOTOR_PORT, MOTOR2_IN1, GPIO_PIN_SET); HAL_GPIO_WritePin(MOTOR_PORT, MOTOR2_IN2, GPIO_PIN_RESET); break; case BACKWARD: HAL_GPIO_WritePin(MOTOR_PORT, MOTOR1_IN1, GPIO_PIN_RESET); HAL_GPIO_WritePin(MOTOR_PORT, MOTOR1_IN2, GPIO_PIN_SET); HAL_GPIO_WritePin(MOTOR_PORT, MOTOR2_IN1, GPIO_PIN_RESET); HAL_GPIO_WritePin(MOTOR_PORT, MOTOR2_IN2, GPIO_PIN_SET); break; case TURN_LEFT: HAL_GPIO_WritePin(MOTOR_PORT, MOTOR1_IN1, GPIO_PIN_RESET); HAL_GPIO_WritePin(MOTOR_PORT, MOTOR1_IN2, GPIO_PIN_SET); HAL_GPIO_WritePin(MOTOR_PORT, MOTOR2_IN1, GPIO_PIN_SET); HAL_GPIO_WritePin(MOTOR_PORT, MOTOR2_IN2, GPIO_PIN_RESET); break; case TURN_RIGHT: HAL_GPIO_WritePin(MOTOR_PORT, MOTOR1_IN1, GPIO_PIN_SET); HAL_GPIO_WritePin(MOTOR_PORT, MOTOR1_IN2, GPIO_PIN_RESET); HAL_GPIO_WritePin(MOTOR_PORT, MOTOR2_IN1, GPIO_PIN_RESET); HAL_GPIO_WritePin(MOTOR_PORT, MOTOR2_IN2, GPIO_PIN_SET); break; default: break; }}// 延时函数void Delay_ms(uint32_t delay) { HAL_Delay(delay);}int main(void) { HAL_Init(); // 初始化GPIO引脚和定时器 // 在此初始化GPIO、PWM和定时器... uint32_t distance; while (1) { // 获取前方障碍物的距离 distance = Get_Distance(); // 根据距离判断动作 if (distance > DISTANCE_THRESHOLD) { // 距离大于阈值,前进 Motor_Control(FORWARD); } else { // 距离小于阈值,后退或转弯 Motor_Control(BACKWARD); Delay_ms(500); // 后退一定时间后再判断 Motor_Control(TURN_LEFT); Delay_ms(500); } Delay_ms(MEASURE_INTERVAL); // 每100ms测量一次 }}
3. 代码解释
  1. 超声波测距

    • Get_Distance()函数通过控制Trig引脚发射超声波,并根据Echo引脚返回的高电平时间计算距离。
    • 使用HAL_GetTick()函数获取时间差,计算声波的传播时间,从而得出障碍物距离。
  2. 电机控制

    • Motor_Control()函数通过设置电机驱动模块的输入引脚来控制电机的方向。根据不同的动作(如前进、后退、左转、右转),调整电机的工作状态。
  3. 主程序

    • main()函数定期测量前方的障碍物距离,并根据测得的距离判断小车是继续前进、后退,还是进行转弯。
4. 总结

本项目实现了一个基于超声波避障的小车,通过STM32单片机控制HC-SR04超声波模块来测量前方的障碍物距离,并控制电机驱动小车进行前进、后退或转弯操作,从而实现避障功能。通过定期测量距离并根据测量结果调整小车动作,可以实现一个简单的避障系统。