完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
写在前面:
这是一个新的栏目,用于记录硬件方面学习的历程。 之前硬件学习是比较零散的,没有系统性的整理过,希望这个栏目的开设能让我的学习更加系统。 注:本栏目是在学习进程中新增的,内容无任何顺序、关联。 仅是个人记录用,不适合学习者观看。 准备: 知识储备:
电机接口为6PIN 排线,左右两根为电机正负极,接至L298N的一个电机口 中间四根为编码器线路,外两根为编码器电源,最中间两根为编码器脉冲输出 L298N使用: 12V供电 L298N使用PWM控制时需要拔掉跳线帽,并通过BIN1和BIN2的电平高低控制正反转(4根线连接至F103,分别为PWM、GND、BIN1、BIN2) 编码器使用: ams1117 -5.0给予5V供电 3根线接至F103,分别为脉冲2条、GND 定时器配置: F103总共有4个定时器,配置如下: TIM1——空代码逻辑: 当TIM2计时,回调函数获取电机脉冲并换算为速度,输入到PID控制器中,PID控制器输出占空比到L298N PID闭环控制逻辑(重点学习): 相关笔记: 此处图片存在错误,增量式PID中的OUT无需+=,因为后面的return已经加上原始值。注意增量PID和位置PID输出值的区别!! 代码实现(部分) control.h #ifndef __CONTROL_H #define __CONTROL_H //全局变量 extern unsigned int MotorSpeed; extern int SpeedTarget; extern int MotorOutput; //函数声明 void GetMotorPulse(void); int SpeedInnerControl(int Speed,int Target); void SetMotorVoltageAndDirection(int Pwm); #endif control.c #include "control.h" #include "tim.h" #include "main.h" #include "math.h" unsigned int MotorSpeed;//全局变量,电机当前速度数值,在encoder.c中获取 int SpeedTarget = 300; //全局变量,速度目标值 int MotorOutput; //全局变量,电机输出 //1.通过TIM4读取电机脉冲并计算速度 void GetMotorPulse(void) { MotorSpeed = (short)(__HAL_TIM_GET_COUNTER(&htim4)/10);//TIM4计数器获得电机脉冲,该电机在10ms采样的脉冲/10则为实际转速的rpm __HAL_TIM_SET_COUNTER(&htim4,0);//计数器清零 } //2.增量式PID控制器 int Error_Last,Error_Prev;//上一次偏差值,上上次误差 int Pwm_add,Pwm;//PWM增量,PWM输出占空比 float Kp = 10.0, Ki = 0.9, Kd = 0.0;//PID系数 int SpeedInnerControl(int Speed,int Target)//速度内环控制 { int Error = Speed - Target; //偏差 = 目标速度 - 实际速度 Pwm_add = Kp * (Error - Error_Last) + //比例 Ki * Error + //积分 Kd * (Error - 2.0f * Error_Last + Error_Prev); //微分 Pwm += Pwm_add; //原始量+增量=输出量 Error_Prev = Error_Last; //保存上上次误差 Error_Last = Error; //保存上一次偏差 if(Pwm > 100) Pwm = 100; //限制上下限,防止超出PWM量程 if(Pwm <-100) Pwm =-100; return Pwm; //返回输出值 } //3.电机电压和方向控制函数 void SetMotorVoltageAndDirection(int Pwm) { if(Pwm < 0)//如果是反转 { HAL_GPIO_WritePin(BIN1_GPIO_Port, BIN1_Pin, GPIO_PIN_SET);//L298N反向 HAL_GPIO_WritePin(BIN2_GPIO_Port, BIN2_Pin, GPIO_PIN_RESET); Pwm = (-Pwm);//如果计算值是负值,先取负得正,因为PWM寄存器只能是正值 __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, Pwm);//输出 } else { HAL_GPIO_WritePin(BIN1_GPIO_Port, BIN1_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(BIN2_GPIO_Port, BIN2_Pin, GPIO_PIN_SET); __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, Pwm); } } TIM2回调函数 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim == &htim2) { //1.获取电机速度 GetMotorPulse(); //2.PID控制器,取回占空比 MotorOutput = SpeedInnerControl(MotorSpeed,SpeedTarget); //3.将占空比导入至电机控制函数 SetMotorVoltageAndDirection(MotorOutput); } } 实际调试: 使用Keil5自带Debug调试 使用STM32Studio调试 用手尝试让电机停止,观察控制效果 按住RST键在放开,可以观察到电机启动的曲线 |
|
|
|
只有小组成员才能发言,加入小组>>
2460 浏览 0 评论
9278 浏览 4 评论
36960 浏览 19 评论
5055 浏览 0 评论
24971 浏览 34 评论
1607浏览 2评论
1861浏览 1评论
2306浏览 1评论
1639浏览 0评论
618浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-13 22:24 , Processed in 1.213724 second(s), Total 44, Slave 38 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (威廉希尔官方网站 图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号