基于STM32F103与L9110s的直流电机PWM调速实战
1. 硬件准备与电路连接在开始STM32F103与L9110s的直流电机控制项目前我们需要先准备好必要的硬件组件。这个部分我会详细列出所需材料并解释如何正确连接它们。我第一次做这个项目时就因为接线问题折腾了半天希望你们能避开这些坑。核心硬件清单STM32F103C8T6最小系统板蓝色小板子淘宝30块钱就能买到L9110s电机驱动模块注意是双H桥版本别买成单路的5V直流电机建议先用小功率电机测试比如130电机杜邦线若干建议用公对母的连接方便电源可以用USB供电或者外接5V电源电路连接示意图STM32的PB8引脚 → L9110s的B-IASTM32的PB9引脚 → L9110s的B-IB电机两端 → L9110s的电机输出端电源正极 → L9110s的VCC电源负极 → L9110s的GND这里有个容易出错的地方L9110s模块上有两组接口A和B我们只需要用其中一组来控制单个电机。我第一次就傻乎乎地把电机接在了A组和B组之间结果电机根本不转。后来仔细看手册才发现每组接口是独立的应该把电机接在同一组的两个输出端上。注意给电机供电时建议先用可调电源测试慢慢调高电压观察电机反应。直接上大电压可能会烧毁驱动芯片。2. GPIO配置与PWM初始化硬件连接好后就要开始写代码了。这部分我会带大家一步步配置STM32的GPIO和PWM功能。虽然标准库已经帮我们封装了很多细节但理解底层原理还是很重要的。GPIO配置步骤首先开启GPIOB的时钟这个千万不能忘配置PB8为通用推挽输出模式控制方向配置PB9为复用推挽输出模式PWM输出void GPIO_Config(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitTypeDef GPIO_InitStruct; // PB8 方向控制 GPIO_InitStruct.GPIO_Pin GPIO_Pin_8; GPIO_InitStruct.GPIO_Mode GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOB, GPIO_InitStruct); // PB9 PWM输出 GPIO_InitStruct.GPIO_Pin GPIO_Pin_9; GPIO_InitStruct.GPIO_Mode GPIO_Mode_AF_PP; // 复用推挽 GPIO_Init(GPIOB, GPIO_InitStruct); }PWM初始化关键点使用TIM4的通道4对应PB9引脚预分频值(PSC)设为71这样计数器时钟为1MHz72MHz/(711)自动重装载值(ARR)设为999这样PWM频率约为1kHz1MHz/1000PWM模式选择模式1高电平有效void PWM_Init(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct; TIM_TimeBaseStruct.TIM_Prescaler 71; TIM_TimeBaseStruct.TIM_Period 999; TIM_TimeBaseStruct.TIM_ClockDivision 0; TIM_TimeBaseStruct.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseInit(TIM4, TIM_TimeBaseStruct); TIM_OCInitTypeDef TIM_OCInitStruct; 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_OC4Init(TIM4, TIM_OCInitStruct); TIM_Cmd(TIM4, ENABLE); }在实际项目中我发现PWM频率设置在1kHz-5kHz之间效果最好。频率太低电机会有噪音太高则可能导致驱动芯片发热。可以根据实际电机特性调整TIM_Prescaler和TIM_Period的值。3. 电机方向控制逻辑控制电机正反转是驱动模块的核心功能。L9110s的逻辑其实很简单但刚开始使用时容易混淆。下面我通过真值表来解释控制逻辑。L9110s控制真值表IAIB电机状态00停止10正转01反转11停止根据这个表我们可以写出控制函数void Motor_Ctrl(MotorState state, uint16_t speed) { switch(state){ case MOTOR_STOP: GPIO_ResetBits(GPIOB, GPIO_Pin_8); GPIO_ResetBits(GPIOB, GPIO_Pin_9); break; case MOTOR_CW: // 正转 GPIO_SetBits(GPIOB, GPIO_Pin_8); GPIO_ResetBits(GPIOB, GPIO_Pin_9); TIM4-CCR4 speed; break; case MOTOR_CCW: // 反转 GPIO_ResetBits(GPIOB, GPIO_Pin_8); GPIO_SetBits(GPIOB, GPIO_Pin_9); TIM4-CCR4 speed; break; } }这里有个实用技巧在切换方向前最好先让电机停止一小会儿比如50ms。我遇到过直接切换方向导致驱动芯片保护的情况加入短暂延时后就解决了。4. 动态调速实现与优化PWM调速的精髓在于动态调整占空比。我们可以通过改变TIM4-CCR4的值来实时调整电机速度。下面分享几种常见的调速方式。基础调速示例// 简单递增调速 for(int i0; i1000; i100){ TIM4-CCR4 i; Delay_ms(500); }按键调速实现// 按键控制速度增减 if(KEY_UP_Pressed()){ // 加速 if(speed 1000) speed 50; TIM4-CCR4 speed; } if(KEY_DOWN_Pressed()){ // 减速 if(speed 0) speed - 50; TIM4-CCR4 speed; }PID调速进阶 对于需要精确控制速度的场景可以加入PID算法。这里给出一个简化版的实现思路float PID_Control(float target, float actual) { static float integral 0; static float last_error 0; float error target - actual; integral error * dt; float derivative (error - last_error) / dt; last_error error; return Kp*error Ki*integral Kd*derivative; } // 使用时 speed PID_Control(targetSpeed, actualSpeed); TIM4-CCR4 (uint16_t)speed;在实际应用中我发现电机启动时需要较大的初始PWM值才能转动这个值称为启动阈值。可以在代码中加入判断当速度从0开始增加时先给一个较大的初始值比如300然后再按正常逻辑调整。5. 常见问题排查调试过程中难免会遇到各种问题这里总结几个我踩过的坑和解决方法。电机不转检查电源用万用表测量VCC和GND之间是否有电压检查接线确认电机接在同一个H桥的输出端检查信号用示波器看PWM波形是否正常输出电机抖动或噪音大调整PWM频率尝试1kHz-5kHz不同频率检查电源容量电源功率不足会导致电压跌落加入滤波电容在电机两端并联0.1uF电容驱动芯片发热严重检查负载电机电流是否超过L9110s的额定值800mA检查死区时间快速切换方向可能导致直通加强散热可以加装小型散热片有个特别隐蔽的问题当PWM占空比为0%或100%时有些电机驱动芯片会进入特殊模式。我建议将占空比限制在5%-95%范围内这样可以避免一些奇怪的问题。6. 项目扩展思路基础功能实现后可以考虑加入更多实用功能。这里分享几个我实践过的扩展方案。速度闭环控制 通过编码器或霍尔传感器获取实际转速与目标转速比较后调整PWM。可以使用正交编码器接口如TIM2或TIM3的编码器模式来读取电机转速。电流检测保护 在电机回路串联小电阻用运放放大电压后通过ADC检测。当电流过大时自动切断输出保护驱动芯片。无线控制 加入蓝牙模块如HC-05或WiFi模块ESP8266通过手机APP远程控制电机速度和方向。多电机同步 如果需要控制多个电机可以使用多个定时器的PWM通道。STM32F103有多个定时器资源合理分配可以实现复杂的多轴控制。我在一个机械臂项目中就用到了三路PWM分别控制三个关节电机。关键是要规划好定时器资源避免通道冲突。比如TIM1_CH1 → 电机1TIM2_CH2 → 电机2TIM4_CH4 → 电机37. 实际应用案例最后分享一个真实的项目案例帮助大家理解这些技术如何应用到实际产品中。智能小车速度控制系统使用两个L9110s分别控制左右轮电机通过TIM1和TIM4产生两路独立PWM编码器反馈实际转速PID算法维持恒定速度无线遥控调整目标速度关键代码结构void main() { Hardware_Init(); PID_Init(); while(1){ leftSpeed Get_Target_Speed(LEFT); rightSpeed Get_Target_Speed(RIGHT); leftActual Encoder_Read(LEFT); rightActual Encoder_Read(RIGHT); leftPWM PID_Calc(leftSpeed, leftActual); rightPWM PID_Calc(rightSpeed, rightActual); Motor_Set(LEFT, leftPWM); Motor_Set(RIGHT, rightPWM); Delay_ms(10); } }在这个项目中最大的挑战是两轮速度同步。由于电机特性差异同样的PWM值可能导致不同转速。后来我加入了PID算法和转速反馈问题才得到解决。这也说明单纯的PWM开环控制精度有限闭环控制才是更可靠的方案。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2499058.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!