单片机实现寻迹小车功能详解(附源码解析)
1. 硬件组成
实现一个基本的寻迹小车系统,需要以下硬件组件:
2. 硬件连接
3. 基本控制逻辑
寻迹小车的工作原理通常是通过传感器检测到的黑白轨迹来判断方向。如果传感器在黑线上,表示小车需要向该方向移动,否则小车需要调整行驶方向。具体控制逻辑如下:
- 前进:如果两个传感器都检测到黑线,表示小车在轨道上,需要前进。
- 左转:如果左侧传感器检测到黑线,而右侧传感器检测到白线,表示小车偏离了轨道,需要左转。
- 右转:如果右侧传感器检测到黑线,而左侧传感器检测到白线,表示小车偏离了轨道,需要右转。
- 停止:如果两个传感器都检测到白线,表示小车脱离轨道,需要停下来进行修正。
4. 软件设计
假设使用 STM32 单片机,下面是一个简单的代码实现方案。
#include "stm32f4xx_hal.h"
// 电机控制引脚定义
#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_GPIO_PORT GPIOB // 假设电机控制引脚连接到 GPIOB
// 红外传感器引脚定义
#define LEFT_SENSOR_PIN GPIO_PIN_4 // 左侧传感器
#define RIGHT_SENSOR_PIN GPIO_PIN_5 // 右侧传感器
#define SENSOR_GPIO_PORT GPIOA
void GPIO_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
// 初始化电机控制引脚
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Pin = MOTOR1_IN1 | MOTOR1_IN2 | MOTOR2_IN1 | MOTOR2_IN2;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(MOTOR_GPIO_PORT, &GPIO_InitStruct);
// 初始化传感器引脚
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = LEFT_SENSOR_PIN | RIGHT_SENSOR_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(SENSOR_GPIO_PORT, &GPIO_InitStruct);
}
// 电机控制函数
void move_forward(void) {
HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR1_IN1, GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR1_IN2, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR2_IN1, GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR2_IN2, GPIO_PIN_RESET);
}
void move_backward(void) {
HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR1_IN1, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR1_IN2, GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR2_IN1, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR2_IN2, GPIO_PIN_SET);
}
void turn_left(void) {
HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR1_IN1, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR1_IN2, GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR2_IN1, GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR2_IN2, GPIO_PIN_RESET);
}
void turn_right(void) {
HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR1_IN1, GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR1_IN2, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR2_IN1, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR2_IN2, GPIO_PIN_SET);
}
void stop_car(void) {
HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR1_IN1, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR1_IN2, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR2_IN1, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_GPIO_PORT, MOTOR2_IN2, GPIO_PIN_RESET);
}
// 传感器读取与决策逻辑
void track_car(void) {
int left_sensor = HAL_GPIO_ReadPin(SENSOR_GPIO_PORT, LEFT_SENSOR_PIN); // 读取左侧传感器状态
int right_sensor = HAL_GPIO_ReadPin(SENSOR_GPIO_PORT, RIGHT_SENSOR_PIN); // 读取右侧传感器状态
if (left_sensor == GPIO_PIN_SET && right_sensor == GPIO_PIN_SET) {
move_forward(); // 两个传感器都在黑线上,前进
}
else if (left_sensor == GPIO_PIN_RESET && right_sensor == GPIO_PIN_SET) {
turn_left(); // 只有右侧在黑线,左转
}
else if (left_sensor == GPIO_PIN_SET && right_sensor == GPIO_PIN_RESET) {
turn_right(); // 只有左侧在黑线,右转
}
else {
stop_car(); // 两个传感器都不在黑线上,停止
}
}
int main(void) {
HAL_Init(); // 初始化 HAL 库
GPIO_Init(); // 初始化 GPIO 引脚
while (1) {
track_car(); // 根据传感器输入,控制小车运动
}
}
代码解释
1. GPIO 初始化
在 GPIO_Init()
函数中,我们初始化了两个主要的硬件部分:
GPIOB
。GPIOA
。2. 电机控制函数
move_forward()
:控制电机前进。通过设置适当的电机驱动引脚状态来使电机旋转。move_backward()
:控制电机后退,反转电机的旋转方向。turn_left()
:控制小车左转。左转时,左电机反向转动,右电机正向转动。turn_right()
:控制小车右转,原理与左转相反。stop_car()
:停止小车运动,将电机的所有控制引脚置为低电平。3. 传感器读取与决策逻辑
track_car()
:读取左右传感器的值并作出决策。
4. 主循环
在 main()
函数中,程序进入无限循环,不断读取传感器数据并根据判断结果控制小车的运动。每次通过 track_car()
来判断小车的动作。
5. 总结
作者:Katie。