当前位置: 首页 > news >正文

用STM32F103C8T6和TB6612驱动模块,从零搭建一辆能自动避障的小车(附完整代码)

用STM32F103C8T6和TB6612驱动模块从零搭建自动避障小车

第一次接触嵌入式开发时,最令人兴奋的莫过于让冰冷的硬件"活"起来。本文将带你用最常见的STM32蓝色小板(F103C8T6)和TB6612电机驱动模块,从焊接电路到编写代码,完整实现一个能自主避开障碍物的智能小车。不同于市面上复杂的多功能方案,我们聚焦最核心的避障功能,确保每个步骤都能被初学者理解并复现。

1. 硬件准备与电路连接

1.1 核心元件清单

确保备齐以下基础组件(总成本控制在200元内):

  • 主控:STM32F103C8T6最小系统板(带USB转串口)
  • 电机驱动:TB6612FNG模块(比L298N更高效)
  • 测距传感器:HC-SR04超声波模块
  • 动力系统:TT马达+车轮套件(配3.7V锂电池)
  • 结构件:亚克力小车底盘、万向轮
  • 连接件:杜邦线(建议用20cm公对公+公对母组合)

提示:TB6612的VM引脚需接5V电源,但逻辑控制端(VCC)接3.3V即可,避免与STM32电平不匹配。

1.2 关键电路连接图示

用表格梳理必须的接线关系:

STM32引脚连接目标功能说明
PA6TB6612 PWMA左侧电机PWM信号
PA7TB6612 PWMB右侧电机PWM信号
PB0TB6612 AIN1左侧电机方向控制1
PB1TB6612 AIN2左侧电机方向控制2
PB10TB6612 BIN1右侧电机方向控制1
PB11TB6612 BIN2右侧电机方向控制2
PC8HC-SR04 Trig超声波触发信号
PC9HC-SR04 Echo超声波回波信号
// 示例:GPIO初始化代码片段 void GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE); // 配置PB0/PB1为推挽输出(电机方向控制) GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStruct); }

2. 电机驱动与PWM配置

2.1 TB6612双路控制原理

TB6612相比传统L298N有三个显著优势:

  1. 效率提升:MOSFET驱动架构使功耗降低70%
  2. 体积缩小:模块面积仅硬币大小
  3. 保护完善:内置过热关断和低压检测

电机转向真值表:

AIN1AIN2电机动作
00刹车
01正转
10反转
11停止

2.2 STM32的PWM生成实战

使用TIM3的通道1/2生成两路PWM:

void PWM_Init(uint16_t arr, uint16_t psc) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct; TIM_OCInitTypeDef TIM_OCInitStruct; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); // 时基配置:72MHz/(719+1)/(999+1) = 100Hz TIM_TimeBaseStruct.TIM_Prescaler = psc; TIM_TimeBaseStruct.TIM_Period = arr; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStruct); // PWM模式配置 TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStruct.TIM_Pulse = 0; // 初始占空比0% TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init(TIM3, &TIM_OCInitStruct); // 通道1(PA6) TIM_OC2Init(TIM3, &TIM_OCInitStruct); // 通道2(PA7) TIM_Cmd(TIM3, ENABLE); TIM_CtrlPWMOutputs(TIM3, ENABLE); }

注意:实际调试时先用TIM_SetCompare1(TIM3, 500)设置50%占空比,观察电机是否匀速转动。

3. 超声波测距模块驱动

3.1 HC-SR04时序解析

完整测距流程分为三步:

  1. 触发:给Trig引脚10μs以上高电平
  2. 回波检测:Echo引脚高电平持续时间即声波往返时间
  3. 距离计算:距离(cm) = 高电平时间(μs)/58
float Get_Distance(void) { GPIO_SetBits(GPIOC, GPIO_Pin_8); delay_us(15); GPIO_ResetBits(GPIOC, GPIO_Pin_8); while(!GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_9)); // 等待Echo变高 uint32_t start = micros(); while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_9)); // 等待Echo变低 uint32_t duration = micros() - start; return (float)duration / 58.0f; }

3.2 滤波算法优化

原始数据易受干扰,建议采用移动平均滤波

#define SAMPLE_SIZE 5 float distance_buffer[SAMPLE_SIZE]; float Filtered_Distance(void) { // 滑动窗口更新数据 for(int i=SAMPLE_SIZE-1; i>0; i--) { distance_buffer[i] = distance_buffer[i-1]; } distance_buffer[0] = Get_Distance(); // 计算平均值 float sum = 0; for(int i=0; i<SAMPLE_SIZE; i++) { sum += distance_buffer[i]; } return sum / SAMPLE_SIZE; }

4. 避障算法设计与实现

4.1 三阶段避障策略

根据距离采取不同动作:

距离范围(cm)执行动作PWM占空比
>30全速前进80%
15-30减速前进50%
<15后退→右转90°→继续检测30%

4.2 状态机实现代码

typedef enum { STATE_FORWARD, STATE_BACKWARD, STATE_TURN_RIGHT, STATE_CHECK } ObstacleState; void Avoidance_Logic(void) { static ObstacleState state = STATE_FORWARD; float dist = Filtered_Distance(); switch(state) { case STATE_FORWARD: if(dist < 15) { state = STATE_BACKWARD; Set_Motor(-30, -30); // 后退 delay_ms(500); } else if(dist < 30) { Set_Motor(50, 50); // 慢速前进 } else { Set_Motor(80, 80); // 全速前进 } break; case STATE_BACKWARD: state = STATE_TURN_RIGHT; Set_Motor(30, -30); // 原地右转 delay_ms(300); // 调整延时可改变转向角度 break; case STATE_TURN_RIGHT: state = STATE_CHECK; Set_Motor(0, 0); // 停止 delay_ms(200); break; case STATE_CHECK: if(Filtered_Distance() > 25) { state = STATE_FORWARD; } else { state = STATE_TURN_RIGHT; } break; } }

4.3 性能优化技巧

  • 中断优化:将超声波Echo检测改为外部中断+定时器捕获
  • 能耗控制:无障碍时进入低速模式,检测到障碍再全速运行
  • 异常处理:增加超时判断,防止Echo信号卡死
// 改进的Echo检测(使用输入捕获) void TIM4_IRQHandler(void) { if(TIM_GetITStatus(TIM4, TIM_IT_CC1) != RESET) { if(echo_state == 0) { // 上升沿 capture_start = TIM_GetCapture1(TIM4); echo_state = 1; } else { // 下降沿 capture_end = TIM_GetCapture1(TIM4); echo_state = 0; new_data_ready = 1; } TIM_ClearITPendingBit(TIM4, TIM_IT_CC1); } }

5. 系统整合与调试

5.1 主循环设计要点

int main(void) { SystemInit(); GPIO_Config(); PWM_Init(999, 719); // 100Hz PWM Ultrasonic_Init(); while(1) { Avoidance_Logic(); delay_ms(100); // 控制检测频率 } }

5.2 常见问题排查

  • 电机不转

    1. 检查TB6612的VM电压是否≥5V
    2. 测量STM32输出引脚是否有信号
    3. 确认STBY引脚已接高电平
  • 距离测量不准

    1. 确保超声波模块与障碍物表面平行
    2. 避免测量柔软材质(如窗帘)
    3. 检查电源纹波(建议并联100μF电容)
  • 小车跑偏

    1. 对两个电机分别校准PWM占空比
    2. 检查车轮是否安装牢固
    3. 在光滑地面测试(减少摩擦力差异)
http://www.jsqmd.com/news/800323/

相关文章:

  • Unity编辑器笔记
  • MiniMax-M2.1开源智能体模型:本地部署与实战应用指南
  • Blob Detection原理与工程实践:从OpenCV斑点检测到工业落地
  • 神经风格迁移实战:一行命令实现梵高/莫奈画风转换
  • 神经科学启发的边缘AI持续学习:从突触修剪到双记忆系统的架构设计
  • Spectral Compact Training:低秩分解技术在大模型训练中的应用
  • Geodesic Active Contours图像分割原理与工程实践
  • 【DeepSeek Service Mesh安全白皮书首发】:零信任网络策略如何实现API级微隔离与自动证书轮转?
  • 为什么92%的Midjourney用户误用--cabbage参数?资深印相工程师亲授3个致命配置误区
  • ARM GICv5 IRS寄存器架构与缓存控制机制详解
  • 【Python】PATH环境变量配置详解:从WARNING到丝滑执行
  • 原生PDF向量化:基于多模态嵌入的免文本提取RAG方案实践
  • 深入解析GD工具插件开发:从原理到实战,打造高效设计工作流
  • AI驱动无卤质子交换膜设计:从分子结构预测到材料性能优化
  • 和室友开黑泰拉瑞亚?手把手教你用腾讯云轻量服务器5分钟搞定Linux私服
  • 基于OODA循环的智能体决策系统设计与工程实践
  • Python Web框架flect:现代高性能异步开发实践与架构解析
  • 统一内存引擎:异构计算时代的内存管理革命
  • AI重塑视频剪辑:Whisper与MediaPipe驱动的智能工作流实战
  • AI战略会议助手:融合EOS、OKR、4DX与Scaling Up的智能引导实践
  • Claude代码助手深度集成:AI编程助手的编辑器权限管理与工作流优化
  • 构建动态AI伦理评估工具链:从公平性、可解释性到全流程治理
  • 张量分解在深度学习模型压缩与鲁棒性增强中的应用实践
  • 使用Docker运行Mysql并通过Docker指令管理Mysql
  • 算法创新驱动AI效率革命:算力增强型进步如何超越摩尔定律
  • ArcGIS/ArcMap中如何创建地图格网之经纬网的创建
  • NORDIC nRF52833开发实战:从协议栈解析到外设驱动
  • 终极指南:如何使用TensorFlow-Course计算多类别目标检测的mAP指标
  • AI编码智能体如何引发认知债务?识别、应对与团队协作策略
  • 利用GitHub Action统一管理AI编码助手配置:从碎片化到自动化