引言
本项目设计了一个基于STM32的智能运输机器人,能够自动识别路径、避开障碍物,并根据用户的指令将物品运输到指定地点。该机器人集成了超声波传感器、红外传感器、无线通信模块等,通过STM32对电机的控制,实现平稳、智能的运输功能。系统适用于仓库自动化、工厂物料配送等场景。
环境准备
1. 硬件设备
- STM32F103C8T6 开发板(或其他 STM32 系列)
- 超声波传感器(如 HC-SR04,用于避障)
- 红外传感器模块(如 TCRT5000,用于路径识别)
- L298N 电机驱动模块(用于控制机器人驱动电机)
- 直流电机和车轮(用于机器人移动)
- NRF24L01 无线通信模块(用于远程控制)
- 蜂鸣器(用于提示运输状态)
- OLED 显示屏(用于显示当前状态)
- USB-TTL 串口调试工具
2. 软件工具
- STM32CubeMX:用于初始化 STM32 外设。
- Keil uVision 或 STM32CubeIDE:用于编写和下载代码。
- ST-Link 驱动程序:用于下载程序到 STM32。
- Arduino IDE 或其他 NRF24L01 编程工具(如果需要调试通信模块)。
项目实现
1. 硬件连接
- 超声波传感器连接:将 HC-SR04 的 Trig 和 Echo 引脚连接到 STM32 的 GPIO(如 PA0 和 PA1),用于测距和避障。
- 红外传感器连接:将 TCRT5000 的输出引脚连接到 STM32 的 ADC 引脚(如 PA2),用于检测地面反射信号进行路径识别。
- 电机驱动连接:将 L298N 电机驱动模块的输入引脚连接到 STM32 的 GPIO(如 PA3、PA4、PA5、PA6),用于控制机器人电机的前进、后退、左转和右转。
- NRF24L01 无线模块连接:将 NRF24L01 的 CE、CSN、MISO、MOSI 和 SCK 引脚连接到 STM32 的 SPI 接口(如 PB6、PB7、PB8、PB9、PB10),用于无线通信。
- 蜂鸣器连接:将蜂鸣器的控制引脚连接到 STM32 的 GPIO(如 PA7),用于提示运输完成或异常。
- OLED 显示屏连接:将 OLED 的 SDA 和 SCL 引脚连接到 STM32 的 I2C 接口(如 PB6 和 PB7),用于显示机器人状态。
2. STM32CubeMX 配置
- 打开 STM32CubeMX,选择你的开发板型号。
- 配置系统时钟为 HSI,确保系统稳定运行。
- 配置 GPIO 引脚用于电机控制、超声波传感器、蜂鸣器等。
- 配置 I2C 用于与 OLED 显示屏通信。
- 配置 SPI 用于与 NRF24L01 无线模块通信。
- 配置 TIM1 生成 PWM 信号,用于调节电机速度。
- 生成代码,选择 Keil 或 STM32CubeIDE 作为工具链。
3. 编写主程序
在生成的项目基础上,编写避障逻辑、路径跟踪、无线控制、电机控制以及状态显示的代码。以下是智能运输机器人的基本代码示例:
#include "stm32f1xx_hal.h"
#include "ultrasonic.h"
#include "motor.h"
#include "nrf24l01.h"
#include "oled.h"
// 定义避障阈值
#define OBSTACLE_DISTANCE 15 // 当距离小于15cm时认为有障碍物
#define PWM_SPEED 80 // 电机默认速度
// 定义引脚
#define BUZZER_PIN GPIO_PIN_7
#define BUZZER_PORT GPIOA
// 函数声明
void System_Init(void);
void Detect_Obstacle(void);
void Follow_Path(void);
void Receive_Command(void);
void Control_Motor(uint8_t left_speed, uint8_t right_speed, int8_t left_dir, int8_t right_dir);
void Display_Status(const char *status);
// 全局变量
uint32_t distance = 0;
uint8_t command = 0; // 接收到的无线命令
void System_Init(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C1_Init();
MX_SPI1_Init();
MX_TIM1_Init();
OLED_Init();
Ultrasonic_Init();
Motor_Init();
NRF24L01_Init();
OLED_ShowString(0, 0, "Transport Robot Ready");
}
// 检测障碍物并进行避障
void Detect_Obstacle(void)
{
distance = Ultrasonic_Measure();
if (distance < OBSTACLE_DISTANCE)
{
Control_Motor(0, 0, 0, 0); // 停止电机
HAL_GPIO_WritePin(BUZZER_PORT, BUZZER_PIN, GPIO_PIN_SET); // 触发蜂鸣器报警
Display_Status("Obstacle Detected");
HAL_Delay(1000); // 等待1秒钟
HAL_GPIO_WritePin(BUZZER_PORT, BUZZER_PIN, GPIO_PIN_RESET); // 停止蜂鸣器
Control_Motor(PWM_SPEED, PWM_SPEED, -1, -1); // 后退
HAL_Delay(500); // 后退0.5秒
Control_Motor(0, 0, 0, 0); // 停止
}
}
// 路径跟踪(基于红外传感器)
void Follow_Path(void)
{
uint16_t ir_value = HAL_ADC_GetValue(&hadc1); // 假设红外传感器连接到 ADC 通道
if (ir_value < 1000) // 假设检测到黑线时,红外传感器值较低
{
Control_Motor(PWM_SPEED, PWM_SPEED, 1, 1); // 直行
Display_Status("Following Path");
}
else
{
Control_Motor(PWM_SPEED, PWM_SPEED, 1, -1); // 转向调整
Display_Status("Adjusting Path");
}
}
// 接收无线控制命令
void Receive_Command(void)
{
if (NRF24L01_Receive(&command))
{
switch (command)
{
case 1:
Control_Motor(PWM_SPEED, PWM_SPEED, 1, 1); // 前进
Display_Status("Command: Forward");
break;
case 2:
Control_Motor(PWM_SPEED, PWM_SPEED, -1, -1); // 后退
Display_Status("Command: Backward");
break;
case 3:
Control_Motor(PWM_SPEED, PWM_SPEED, 1, -1); // 左转
Display_Status("Command: Turn Left");
break;
case 4:
Control_Motor(PWM_SPEED, PWM_SPEED, -1, 1); // 右转
Display_Status("Command: Turn Right");
break;
case 5:
Control_Motor(0, 0, 0, 0); // 停止
Display_Status("Command: Stop");
break;
}
}
}
// 控制电机
void Control_Motor(uint8_t left_speed, uint8_t right_speed, int8_t left_dir, int8_t right_dir)
{
Motor_SetSpeed(left_speed, right_speed);
Motor_SetDirection(left_dir, right_dir);
}
// 显示状态
void Display_Status(const char *status)
{
OLED_Clear();
OLED_ShowString(0, 0, status);
}
int main(void)
{
System_Init();
while (1)
{
Detect_Obstacle(); // 避障
Follow_Path(); // 路径跟踪
Receive_Command(); // 接收远程指令
HAL_Delay(100); // 每0.1秒更新一次状态
}
}
4. 各模块代码
超声波传感器测距
以下是超声波传感器测距的代码示例:
#include "ultrasonic.h"
// 初始化超声波传感器
void Ultrasonic_Init(void)
{
// 配置 GPIO 引脚,设置 Trig 为输出,Echo 为输入
}
// 测量距离
uint32_t Ultrasonic_Measure(void)
{
uint32_t distance = 0;
uint32_t local_time = 0;
// 发送 Trig 脉冲
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);
HAL_Delay(10); // 10 微秒脉冲
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);
// 等待 Echo 的高电平并计算时间
while (!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1)); // 等待 Echo 引脚变高
while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1)) // 计算 Echo 高电平的时间
{
local_time++;
HAL_Delay(1); // 延时 1 微秒,注意:需要根据实际时钟调整
}
// 计算距离 (声音速度 34000 cm/s)
distance = (local_time * 0.034) / 2; // 除以 2 是因为声音往返
return distance;
}
电机控制
通过 L298N 驱动电机模块,设置电机的速度和方向,实现前进、后退、左转、右转等操作:
#include "motor.h"
#include "tim.h"
// 初始化电机
void Motor_Init(void)
{
// 初始化电机的 GPIO 引脚和 PWM 通道
}
// 设置电机的速度
void Motor_SetSpeed(uint8_t left_speed, uint8_t right_speed)
{
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, left_speed); // 左电机 PWM
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, right_speed); // 右电机 PWM
}
// 设置电机的方向,1 表示前进,-1 表示后退,0 表示停止
void Motor_SetDirection(int8_t left_dir, int8_t right_dir)
{
if (left_dir == 1)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
}
else if (left_dir == -1)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
}
if (right_dir == 1)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET);
}
else if (right_dir == -1)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET);
}
}
NRF24L01 无线通信
用于接收远程控制命令,实现用户对机器人的远程控制:
#include "nrf24l01.h"
#include "spi.h"
// 初始化 NRF24L01 模块
void NRF24L01_Init(void)
{
// 配置 NRF24L01 的工作模式、信道和数据速率
// 配置地址和接收管道
}
// 接收数据
uint8_t NRF24L01_Receive(uint8_t *data)
{
if (NRF24L01_DataAvailable())
{
NRF24L01_ReadPayload(data); // 读取接收到的数据
return 1; // 表示接收成功
}
return 0; // 没有新数据
}
OLED 显示
用于显示机器人的当前状态,如前进、后退、避障、接收到的命令等:
#include "oled.h"
// 初始化 OLED 显示屏
void OLED_Init(void)
{
// OLED 初始化代码
}
// 显示字符串
void OLED_ShowString(uint8_t x, uint8_t y, const char *str)
{
// 在 OLED 的指定位置显示字符串
}
// 显示数字
void OLED_ShowNumber(uint8_t x, uint8_t y, uint16_t num, uint8_t len)
{
// 在 OLED 显示数字
}
// 清屏
void OLED_Clear(void)
{
// 清除 OLED 上的显示内容
}
⬇帮大家整理了单片机的资料
包括stm32的项目合集【源码+开发文档】
点击下方蓝字即可领取,感谢支持!⬇
点击领取更多嵌入式详细资料
问题讨论,stm32的资料领取可以私信!
系统工作原理
- 避障功能:机器人通过超声波传感器实时测量前方的距离。当检测到前方有障碍物且距离小于设定的阈值时,机器人会自动停止,并后退一段距离以避免碰撞,同时触发蜂鸣器进行报警。
- 路径跟踪:红外传感器检测地面黑线或白线的反射光强度,通过对比不同区域的光强,机器人可以调整其方向以跟随预设的轨迹行驶,实现路径跟踪功能。
- 远程控制:用户可以通过 NRF24L01 无线模块发送指令,如前进、后退、左转、右转和停止,机器人接收到指令后执行相应的操作。
- 状态显示:OLED 显示屏实时显示机器人的当前状态,如前进、避障、路径调整等,便于用户在调试时查看机器人的动作。
常见问题与解决方法
1. 无线通信不稳定
- 问题原因:NRF24L01 信号干扰或电源供电不足。
- 解决方法:确保无线模块的天线安装良好,检查供电是否稳定。如果干扰较大,可以尝试改变通信信道。
2. 电机运行不平稳
- 问题原因:PWM 信号设置不合理或电机驱动模块连接不良。
- 解决方法:调整 PWM 信号频率和占空比,确保电机能够平稳运转。检查 L298N 驱动模块的连接,确保电机驱动电压和电流满足要求。
3. 红外传感器无法正确识别路径
- 问题原因:环境光干扰或传感器位置安装不合适。
- 解决方法:调整红外传感器的位置和角度,确保其能正确检测地面反射光强。适当调节检测阈值,以减少环境光的影响。
4. 超声波测距不准确
- 问题原因:测量时的反射角度不合适或 Echo 信号处理不当。
- 解决方法:确保超声波传感器正对目标物体,并调整安装角度。检查测距算法中的时间计算是否符合实际时钟频率。
扩展功能
- 自动充电功能:可以增加无线充电模块或充电底座,当机器人电量低时,自动返回充电点进行充电。
- 云端控制与数据存储:通过 Wi-Fi 模块将运输数据上传到云端服务器,便于在手机或电脑上查看机器人完成的运输任务和状态数据。
- 多机器人协作:可以通过扩展通信协议,实现多台机器人之间的通信与协作,在大型仓库或工厂中实现复杂的物料调度。
结论
通过本项目,我们成功设计了一个基于 STM32 的智能运输机器人,实现了避障、路径跟踪、远程控制和状态显示等功能。该机器人可以根据预设的路径自主行驶,并通过无线通信模块接受用户的远程指令,适用于各种物流运输和仓库自动化场景。项目的可扩展性和开放性使其成为学习嵌入式系统和机器人技术的良好平台,也为工业自动化领域的应用提供了有效的解决方案。