ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

STM32智能小车开发全攻略:从硬件选型到PID循迹算法实战

STM32智能小车开发全攻略:从硬件选型到PID循迹算法实战 简介本资源是一套完整的基于STM32的循迹避障小车开发套件面向嵌入式初学者、单片机课程设计学生及机器人实践爱好者解决从硬件原理理解、仿真验证到固件编程的一体化学习痛点。压缩包共334个文件涵盖120个.h头文件外设配置与函数声明、113个.c源文件传感器采集、PID循迹、超声波避障、PWM电机控制等核心逻辑、5份SchDoc原理图含AD转换、电机驱动与电源管理模块以及Keil工程文件.uvprojx/.uvoptx、Hex可执行镜像和Proteus仿真模型完整支撑“设计—仿真—烧录—调试”全流程。资源包仅3.07MB结构清晰、注释充分便于逐模块研读与二次开发。目前已有6604人学习下载是掌握STM32外设驱动、实时传感融合与智能小车控制策略的高实用性入门范例。1. 项目概述从零到一打造你的第一台智能小车如果你对嵌入式开发感兴趣想找一个能串联起单片机控制、传感器应用、电机驱动和简单算法的综合性实战项目那么基于STM32的循迹避障小车绝对是一个经典且完美的选择。它不像一些纯软件项目那样抽象你能亲眼看到代码如何驱动硬件让一个小车底盘动起来并赋予它“看见”黑线和“感知”障碍物的能力。这个项目涵盖了嵌入式工程师日常工作中最核心的几个环节硬件电路设计、微控制器编程、传感器数据采集与处理、以及最基础的决策逻辑实现。我当年就是从这样一个项目入门的它帮我理清了从原理图到代码再到物理世界反馈的完整闭环。今天我就把自己在多次指导学生和实际开发中积累的经验、踩过的坑以及如何高效利用“原理图Proteus仿真源码”这套组合拳系统地分享给你。无论你是正在学习STM32的学生还是希望夯实基础的爱好者这篇文章都能让你少走弯路快速搭建出一台稳定可靠、逻辑清晰的智能小车。2. 核心硬件设计与选型解析一台小车的稳定运行硬件是基石。盲目堆砌传感器或选用不匹配的电机只会让后续的调试变成噩梦。我们需要像搭积木一样为每个功能模块选择最合适的部件并确保它们能协同工作。2.1 主控芯片为什么是STM32STM32系列单片机是这个项目的绝对核心。相较于传统的51或AVR单片机STM32的优势在于其强大的性能、丰富的外设和成熟的生态。对于小车项目我们主要利用其以下几个特性足够的IO口与定时器我们需要连接多个传感器如5路循迹、超声波模块、驱动电机通常需要4个PWM输出还可能用到串口调试。STM32F103C8T6俗称“蓝桥杯”或“最小系统板”拥有48个引脚完全满足需求且内置多个高级定时器可以产生精准的PWM波控制电机速度。处理速度与实时性基于ARM Cortex-M内核主频可达72MHz能够快速处理传感器数据并做出决策这对于需要实时避障的小车至关重要。开发环境成熟Keil MDK、STM32CubeMX等工具链完善HAL库和标准库资料丰富极大降低了开发门槛。注意对于初学者强烈推荐从STM32F103系列开始。它的资料是最多的遇到问题几乎都能找到解决方案。切勿一开始就追求高性能的F4或H7系列那会引入不必要的复杂性。2.2 “眼睛”与“触角”传感器选型与电路设计小车的智能来源于传感器。循迹和避障功能分别依赖不同的传感器。循迹模块通常采用红外对管式传感器。它由一个红外发射管和一个红外接收管组成。地面为白色时反射红外光接收管导通输出低电平地面为黑色轨迹线时吸收红外光接收管截止输出高电平。常见的配置是“五路循迹模块”即并排安装五个这样的对管提供更丰富的路径信息实现更精确的循迹。电路连接要点传感器的输出端DO通常直接连接到STM32的GPIO口配置为上拉输入模式。因为传感器输出是数字信号高低电平读取非常方便。在原理图上需要为每个传感器设计一个滤波电容如0.1uF靠近其电源引脚以抑制干扰防止误触发。避障模块最常用的是HC-SR04超声波模块。它通过发射超声波并接收回波计算时间差来测量距离。其性价比高测距范围2cm-400cm完全满足小车避障需求。电路连接与驱动超声波模块有四个引脚VCC, GND, Trig触发, Echo回波。Trig接STM32的GPIO输出用于发送一个10us以上的高脉冲触发测距Echo接STM32的GPIO输入用于检测高电平的持续时间。这里有个关键点Echo脚的高电平时间可能长达几十毫秒必须使用STM32的输入捕获功能或者外部中断配合定时器来精确测量简单用延时循环读取是极不准确的。在原理图上除了电源滤波Trig和Echo信号线上可以串联一个22-100欧姆的电阻有助于抑制信号振铃。2.3 动力心脏电机与驱动电路小车要动起来电机和驱动电路是关键。通常我们使用直流减速电机它扭矩大速度可控。电机驱动芯片选型最经典的是L298N或TB6612FNG驱动模块。L298N老牌芯片驱动能力强但发热较大需要加装散热片。其逻辑简单通过IN1、IN2控制电机转向通过ENA使能端输入PWM控制速度。TB6612FNG更现代的选择效率高发热小内置保护电路。控制方式类似AIN1/AIN2, PWMA但性能更优是目前更推荐的选择。电源设计这是最容易出问题的地方电机驱动模块的电源必须与STM32控制板电源隔离或进行妥善处理。电机启动和急停时会产生巨大的电流尖峰和反向电动势如果共用一个电源且没有做好滤波会直接导致STM32复位或死机。标准做法是使用两节18650锂电池7.4V串联为电机驱动供电。通过一个降压模块如LM2596将7.4V降为稳定的5V单独为STM32核心板、传感器模块供电。在电机驱动模块的电源输入端并联一个大容量电解电容如470uF-1000uF以缓冲电流冲击。所有数字地GND最终需要在一点相连形成“星型接地”减少噪声环路。3. 软件架构与核心算法实现硬件搭好了接下来就是赋予小车灵魂的软件部分。一个好的软件架构能让代码清晰、易于调试和扩展。3.1 程序主循环与任务调度对于这样的小车我们通常采用一个简单的“前后台系统”。在main函数的while(1)主循环中以固定的周期比如10ms执行各个任务。int main(void) { // 硬件初始化时钟、GPIO、定时器、PWM、ADC、中断等 HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_TIM2_Init(); // 用于PWM生成 MX_TIM3_Init(); // 用于超声波测距计时 MX_USART1_UART_Init(); // 用于调试打印 // 模块初始化 Motor_Init(); TrackSensor_Init(); Ultrasonic_Init(); while (1) { // 任务1读取循迹传感器状态 (10ms一次) if(tick_10ms) { TrackSensor_Read(); tick_10ms 0; } // 任务2控制超声波触发测距 (100ms一次) if(tick_100ms) { Ultrasonic_StartMeasure(); tick_100ms 0; } // 任务3核心决策与控制 Car_Control_Loop(); // 其他任务...如按键扫描、状态显示 // 利用SysTick或定时器中断来设置 tick_10ms, tick_100ms 标志位 } }这种结构避免了在传感器读取或电机控制中使用HAL_Delay这类阻塞函数保证了系统的响应性。3.2 循迹算法从简单到复杂循迹算法的核心是根据五路传感器返回的二进制状态0/1决定小车的转向和速度。基础版本条件判断法这是最简单直观的方法适合直线和弧度不大的弯道。void Car_Control_Loop(void) { uint8_t track_state Get_TrackSensor_State(); // 例如0b00100 表示中间传感器压线 switch(track_state) { case 0b00100: // 中间压线直行 Motor_SetSpeed(LEFT_MOTOR, 70); Motor_SetSpeed(RIGHT_MOTOR, 70); break; case 0b00010: // 稍微偏右左轮微调 Motor_SetSpeed(LEFT_MOTOR, 60); Motor_SetSpeed(RIGHT_MOTOR, 70); break; case 0b00001: // 更偏右左轮调整更大 Motor_SetSpeed(LEFT_MOTOR, 40); Motor_SetSpeed(RIGHT_MOTOR, 70); break; case 0b01000: // 稍微偏左右轮微调 Motor_SetSpeed(LEFT_MOTOR, 70); Motor_SetSpeed(RIGHT_MOTOR, 60); break; // ... 其他状态 case 0b00000: // 全部脱线可能到终点或出错停车或原地旋转寻线 Motor_Stop(); break; } }进阶版本比例控制P控制条件判断法在弯道急时容易摇摆或冲出轨道。引入比例控制能让转弯更平滑。我们将传感器状态“量化”为一个偏差值error。// 假设传感器从左到右为S1,S2,S3,S4,S5定义权重 const int weight[5] {-2, -1, 0, 1, 2}; // 中间为0左负右正 int error 0; void Calculate_Error(void) { error 0; for(int i0; i5; i) { if(sensor_state (1i)) { // 如果第i个传感器检测到黑线 error weight[i]; } } } void Car_Control_Loop_P(void) { Calculate_Error(); float Kp 10.0; // 比例系数需要实际调试 int adjustment (int)(Kp * error); int base_speed 60; int left_speed base_speed - adjustment; int right_speed base_speed adjustment; // 限制速度在有效范围0-100 left_speed constrain(left_speed, 0, 100); right_speed constrain(right_speed, 0, 100); Motor_SetSpeed(LEFT_MOTOR, left_speed); Motor_SetSpeed(RIGHT_MOTOR, right_speed); }这样小车偏离中心越远error绝对值越大左右轮速度差就越大纠正力度越强实现了平滑的循迹。3.3 避障策略有限状态机FSM的应用避障逻辑比循迹稍复杂因为它涉及到模式的切换。使用有限状态机FSM来管理小车的行为状态是非常清晰的方法。我们可以定义几个状态循迹状态TRACKING默认状态执行循迹算法。避障状态AVOIDING检测到前方障碍物进入避障流程。恢复状态RECOVERING完成避障动作后尝试找回黑线。typedef enum { STATE_TRACKING, STATE_AVOIDING, STATE_RECOVERING } CarState_t; CarState_t g_car_state STATE_TRACKING; uint32_t avoid_timer 0; void Car_StateMachine_Update(void) { float distance Get_Ultrasonic_Distance(); switch(g_car_state) { case STATE_TRACKING: // 正常循迹 Car_Tracking(); // 检查障碍物 if(distance AVOID_DISTANCE distance 0) { // 检测到有效范围内有障碍 g_car_state STATE_AVOIDING; avoid_timer HAL_GetTick(); Motor_Stop(); // 先停车 } break; case STATE_AVOIDING: // 执行一个预设的避障动作例如右转90度前进一段再左转90度 if((HAL_GetTick() - avoid_timer) 500) { // 第一阶段右转 Motor_SetSpeed(LEFT_MOTOR, 50); Motor_SetSpeed(RIGHT_MOTOR, -50); // 右轮反转实现原地右转 } else if((HAL_GetTick() - avoid_timer) 1500) { // 第二阶段直行一段距离绕过障碍 Motor_SetSpeed(LEFT_MOTOR, 60); Motor_SetSpeed(RIGHT_MOTOR, 60); } else if((HAL_GetTick() - avoid_timer) 2000) { // 第三阶段左转尝试回归原方向 Motor_SetSpeed(LEFT_MOTOR, -50); Motor_SetSpeed(RIGHT_MOTOR, 50); } else { // 避障动作结束进入恢复寻线状态 g_car_state STATE_RECOVERING; avoid_timer HAL_GetTick(); } break; case STATE_RECOVERING: // 原地缓慢旋转或执行特定寻线策略直到重新检测到黑线 if(Detect_Track_Line()) { g_car_state STATE_TRACKING; // 找到线回归循迹 } else if((HAL_GetTick() - avoid_timer) 3000) { // 超过3秒没找到线可以进入错误处理如停车 Motor_Stop(); } else { // 执行原地顺时针慢速旋转寻线 Motor_SetSpeed(LEFT_MOTOR, 30); Motor_SetSpeed(RIGHT_MOTOR, -30); } break; } }这个状态机清晰地划分了不同行为使得程序逻辑一目了然易于调试和维护。你可以根据实际小车和场地情况调整每个状态下的具体动作和时间参数。4. Proteus仿真在电脑上验证你的逻辑在实际焊接电路和烧录代码之前用Proteus进行仿真是一个极好的习惯。它能帮你验证硬件连接逻辑和核心算法是否正确节省大量时间和物料成本。4.1 仿真电路搭建要点在Proteus中搭建STM32小车仿真电路你需要找到以下关键元件MCUSTM32F103C6或C8取决于你使用的具体型号。电机驱动可以用H桥电路如用MOSFET搭建来模拟或者直接用Proteus里的“DC Motor”元件配合电压控制来简化。循迹传感器用一排“红外对射传感器”模型或者更简单地用“逻辑状态”开关来模拟其数字输出连接到STM32的IO口。超声波模块Proteus中有“SRF04”或“SRF05”模型可以直接使用。注意连接好Trig和Echo引脚。虚拟仪器务必添加“Virtual Terminal”虚拟串口连接到STM32的USART1用于打印调试信息。添加“示波器”或“逻辑分析仪”可以观察PWM波形和传感器信号。实操心得Proteus仿真无法完全模拟真实的物理响应如电机惯性、地面摩擦因此仿真的重点应放在验证IO控制逻辑、PWM生成是否正确、中断和定时器是否正常工作、以及你的状态机算法流程是否合理。不要指望仿真小车能像真车一样完美跑完赛道它能帮你排除80%的软件逻辑错误。4.2 在仿真中调试代码生成Hex文件在Keil中编译你的工程确保在Output选项卡中勾选了“Create HEX File”。加载Hex文件在Proteus中双击STM32元件在“Program File”一栏选择上一步生成的.hex文件。设置晶振同样在STM32属性中将“Clock Frequency”设置为与你代码中SystemClock_Config()一致的值如8MHz外部晶振经PLL倍频到72MHz这里就填72M。运行与调试点击运行你可以通过虚拟串口窗口看到printf输出的传感器数据、状态信息。通过手动触发仿真图中的传感器开关或障碍物观察小车的电机控制信号变化验证你的避障和循迹逻辑。常见仿真问题程序不运行检查Hex文件路径是否正确晶振频率是否设置。有时需要给STM32的NRST引脚接一个上拉电阻到VDD并在仿真开始时手动触发一个复位脉冲。虚拟串口无输出检查USART的引脚连接是否正确代码中的串口初始化、重定向printf的函数int fputc(int ch, FILE *f)是否编写正确。外设不工作Proteus对STM32某些复杂外设如某些定时器模式、DMA支持可能不完美。如果遇到问题尝试简化代码先验证最基本的功能如点亮一个LED。5. 源码结构与管理写出可维护的工程一份清晰、模块化的源码不仅方便自己调试也便于日后复用和升级。切忌把所有代码都堆在main.c里。5.1 推荐的工程目录结构Your_Car_Project/ ├── Core/ │ ├── Inc/ // 主头文件如 main.h │ ├── Src/ // 主源文件如 main.c, stm32f1xx_it.c中断服务函数 │ └── Startup/ // 启动文件 ├── Drivers/ │ ├── STM32F1xx_HAL_Driver/ // HAL库文件由CubeMX生成 │ └── CMSIS/ // Cortex内核支持文件 ├── Middlewares/ // 中间件本项目可能用不到 ├── Application/ │ ├── App/ // 应用层 │ │ ├── car_fsm.c/.h // 小车状态机 │ │ ├── car_ctrl.c/.h // 小车控制逻辑整合循迹避障 │ │ └── system_task.c/.h // 系统任务调度 │ ├── Bsp/ // 板级支持包硬件驱动 │ │ ├── motor.c/.h // 电机驱动封装 │ │ ├── track_sensor.c/.h // 循迹传感器驱动 │ │ ├── ultrasonic.c/.h // 超声波模块驱动 │ │ └── buzzer_led.c/.h // 蜂鸣器、LED等外设 │ └── Utils/ // 工具函数 │ ├── delay.c/.h // 精确延时函数基于SysTick │ ├── my_printf.c/.h // 串口调试打印 │ └── filter.c/.h // 简单的软件滤波如用于超声波测距 ├── MDK-ARM/ // Keil工程文件 ├── STM32CubeMX/ // CubeMX的.ioc工程文件 └── README.md // 项目说明文档5.2 关键驱动模块代码示例以超声波为例ultrasonic.h:#ifndef __ULTRASONIC_H #define __ULTRASONIC_H #include main.h // 硬件引脚定义方便移植 #define US_TRIG_PORT GPIOB #define US_TRIG_PIN GPIO_PIN_6 #define US_ECHO_PORT GPIOB #define US_ECHO_PIN GPIO_PIN_7 // 测量相关 #define US_SOUND_SPEED 340.0f // 声速 m/s #define US_TIMEOUT 60000 // 超时时间对应约10米 void Ultrasonic_Init(void); void Ultrasonic_StartMeasure(void); float Ultrasonic_GetDistance(void); uint8_t Ultrasonic_IsMeasureDone(void); #endifultrasonic.c(使用输入捕获):#include ultrasonic.h #include tim.h // 假设使用TIM3进行输入捕获 static volatile uint32_t g_echo_start 0; static volatile uint32_t g_echo_end 0; static volatile uint8_t g_measure_done 0; void Ultrasonic_Init(void) { // 初始化Trig引脚为推挽输出 GPIO_InitTypeDef GPIO_InitStruct {0}; __HAL_RCC_GPIOB_CLK_ENABLE(); GPIO_InitStruct.Pin US_TRIG_PIN; GPIO_InitStruct.Mode GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(US_TRIG_PORT, GPIO_InitStruct); HAL_GPIO_WritePin(US_TRIG_PORT, US_TRIG_PIN, GPIO_PIN_RESET); // Echo引脚初始化在CubeMX中配置为上拉输入并绑定到TIM3的通道2输入捕获 // 这里主要开启定时器和中断 HAL_TIM_IC_Start_IT(htim3, TIM_CHANNEL_2); // 开启输入捕获中断 } void Ultrasonic_StartMeasure(void) { if(g_measure_done) return; // 上一次测量未结束忽略新触发 g_echo_start 0; g_echo_end 0; // 发送10us的高电平触发脉冲 HAL_GPIO_WritePin(US_TRIG_PORT, US_TRIG_PIN, GPIO_PIN_SET); delay_us(12); // 略微大于10us HAL_GPIO_WritePin(US_TRIG_PORT, US_TRIG_PIN, GPIO_PIN_RESET); } float Ultrasonic_GetDistance(void) { if(!g_measure_done) return -1.0f; // 测量未完成 uint32_t pulse_width g_echo_end - g_echo_start; float time_us (float)pulse_width / (SystemCoreClock / 1000000.0f); // 将计数转换为微秒 float distance_cm (time_us / 2.0f) * (US_SOUND_SPEED / 10000.0f); // 距离 (时间/2) * 声速 g_measure_done 0; // 读取后清除标志 return distance_cm; } // TIM3输入捕获中断回调函数在stm32f1xx_it.c中调用 void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if(htim-Instance TIM3 htim-Channel HAL_TIM_ACTIVE_CHANNEL_2) { if(g_echo_start 0) { // 捕获到上升沿记录起始时间 g_echo_start HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2); // 切换为下降沿捕获 __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_2, TIM_INPUTCHANNELPOLARITY_FALLING); } else { // 捕获到下降沿记录结束时间 g_echo_end HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2); g_measure_done 1; // 切换回上升沿捕获准备下一次测量 __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_2, TIM_INPUTCHANNELPOLARITY_RISING); g_echo_start 0; } } }这个驱动模块将硬件细节封装起来对外只提供Init、StartMeasure和GetDistance等简洁接口大大提高了主程序的清晰度和可移植性。6. 实物制作、调试与性能优化当仿真通过后就可以着手制作实物了。这是理论走向实践的关键一步也是最容易遇到各种“玄学”问题的时候。6.1 PCB设计与焊接注意事项如果条件允许自己设计一块PCB集成主控、驱动和传感器接口会让小车更整洁可靠。布局电机驱动部分大电流应远离STM32等模拟/数字小信号区域。电源模块放在板子入口处。走线电机驱动部分的电源线要宽建议1mm。数字信号线避免长距离平行于电源线以减少干扰。滤波在每个芯片的电源引脚附近越近越好放置一个0.1uF的陶瓷电容进行高频去耦。在电机驱动电源入口处放置一个100uF以上的电解电容进行储能和低频滤波。焊接检查有无虚焊、短路。特别是STM32这种多引脚芯片焊接后最好用放大镜检查一遍。6.2 系统联调与参数整定硬件连接无误后按以下顺序进行调试电源测试首先不上主控只接通电源用万用表测量各点电压是否正常如电机驱动输入7.4V降压模块输出5V/3.3V。基础IO测试写一个简单程序循环点亮一个LED确保最小系统工作正常程序能烧录。电机驱动测试编写测试代码分别控制左右电机正转、反转、停止并逐步增加PWM值观察电机转速变化是否平滑。注意此时最好把小车架起来让轮子悬空。传感器单独测试循迹传感器用printf打印出五路传感器的实时状态值拿黑白纸片在传感器下方移动观察打印值变化是否准确、迅速。超声波传感器同样用printf输出测距值用手在传感器前方移动观察数值变化是否连续、准确。注意测量死区通常2-3cm内不准确。算法集成与参数整定这是最耗时的部分。循迹PID参数先设Ki0, Kd0只调Kp。让小车在直道上跑如果它左右摇摆震荡说明Kp太大如果反应迟钝拐弯时总是冲出去说明Kp太小。找到合适的Kp后如果小车在出弯时总是纠正过头可以引入较小的Kd微分来抑制震荡。避障参数调整AVOID_DISTANCE如15cm这个距离需要给小车留出足够的刹车和转向空间。调整避障动作中的转弯角度和直行距离使其能流畅地绕开常见障碍物如矿泉水瓶。6.3 常见问题与排查技巧实录以下是我在多次项目中遇到的典型问题及解决方法希望能帮你快速定位问题现象可能原因排查步骤与解决方案上电后STM32不工作或偶尔复位1. 电源问题电压不稳、电流不足。2. 电机干扰通过电源串入。3. 复位电路或晶振电路有问题。1. 用示波器观察STM32的VDD电压在电机启停时是否有大幅跌落或毛刺。2.强化电源隔离与滤波确保电机电源与控制电源分离在STM32的VDD引脚就近增加一个10uF钽电容和一个0.1uF陶瓷电容。3. 检查复位引脚是否被意外拉低晶振是否起振可用示波器测OSC_OUT引脚。循迹小车左右剧烈摇摆走不了直线1. 传感器安装高度不一致或距离地面过高/过低。2. 传感器本身性能差异阈值不同。3. PID参数Kp过大或采样/控制周期不稳定。1. 调整传感器支架确保所有探头距地面高度一致通常5-10mm为宜。2. 单独测试每个传感器看其检测到黑线时输出的电平是否干净、一致。必要时可微调传感器上的电位器如果有。3.降低Kp并检查控制循环的周期是否固定使用定时器中断来触发控制任务而非随机的延时。超声波测距值跳动大或不准确1. 测量环境有干扰多个超声波同时工作、强反射面。2. Echo引脚受到噪声干扰。3. 定时器计数溢出或中断处理不当。1. 避免多个超声波同时触发可错开时间。2. 在Echo引脚与STM32之间串联一个100欧姆电阻并加一个20pF对地电容滤波。3.软件滤波连续采样5次去掉最大最小值取中间三值的平均。确保定时器时钟配置和计数范围能覆盖最大测距时间。Proteus仿真正常但实物不工作1. 实物引脚连接与仿真或代码定义不一致。2. 外设时钟未使能。3. 硬件初始化顺序问题。1.仔细核对原理图、PCB和代码中的引脚定义这是最高频的错误使用HAL_GPIO_WritePin测试每个关键引脚是否能正常输出高低电平。2. 检查CubeMX配置或代码中是否开启了对应GPIO端口和外围设备如USART, TIM的时钟__HAL_RCC_XXX_CLK_ENABLE()。3. 确保初始化顺序先初始化系统时钟和基本外设再初始化功能模块。电机一个转一个不转或转速不一致1. 电机或驱动芯片本身损坏。2. PWM输出通道配置错误。3. 机械结构卡滞。1. 交换两个电机的接线如果问题跟随电机走则是电机问题如果问题跟随驱动通道走则是驱动或代码问题。2. 用示波器或LED检查两个电机对应的PWM引脚是否有正常波形输出占空比是否随代码改变。3. 检查车轮是否安装过紧齿轮箱是否有异物。最后的建议调试时串口打印是你最好的朋友。把关键变量传感器值、计算出的偏差error、PID输出、超声波距离、小车状态实时打印出来能让你清晰地看到程序的“内心活动”绝大部分逻辑错误都能通过这种方式发现。当小车行为异常时不要盲目修改代码先看看数据发生了什么。本文还有配套的精品资源点击获取
返回列表