PID算法在电机速度控制上的应用

目录

概述

1 系统硬件框架

1.1 框架介绍

1.2 硬件实物图

2 STM32Cub生成工程

2.1 软件版本信息

2.2  配置参数

​编辑2.3 生成项目

3 PID算法实现

3.1 概念

3.2 代码实现

4 其他功能实现

4.1 设置电机速度

4.2 PID算法控制电机

4.3 功能函数的调用

5 测试

5.1 测试案例1

5.2 测试案例2


源代码下载地址:

PID算法在电机速度控制上的应-测试源码资源-CSDN文库

概述

本文主要介绍使用PID算法实现电机速度的控制,笔者使用IO外部中断测试码盘的脉冲实现测速功能,通过该速度值,应用PID算法实现调制PWM的占空比,以实现电机速度的控制。

1 系统硬件框架

1.1 框架介绍

1) 系统使用光电编码器进行速度测试,具体实现方式可以参看原文:

电机转速计算(基于码盘和IO外部中断)-CSDN博客

2) TIMER7实现定时器功能,其会产生10us的定时器中断,为系统工作提供基准时钟。

3)TIMER8用于产生PWM实现电机速度控制,系统通过电机速度的反馈值以调节PWM的脉冲宽度,以实现电机速度的闭环控制。

1.2 硬件实物图

 使用STM32F103RC作为主控芯片,LN298N用于驱动电机,光电码盘用于测试电机转速。具体的测试实物图如下:

2 STM32Cub生成工程

2.1 软件版本信息

软件名称版本信息
STM32CubeSTM32CubeMX 6.11
STM32 HALSTM32Cube_FW_F1_V1.8.5

2.2  配置参数

1)配置EXTI IO中断,其用测监测编码器的冲击脉冲,选择PC0接口,同时要使能外部中断函数

 使能中断函数

2)配置Timer7,中断间隔为10us,其具体配置参数如下:

 使能中断函数

 3)配置PWM相关的参数和使能通道

定时器相关的参数配置如下,计数周期为10ms

 

 PWM通道相关的参数:

各个通道对应的IO接口如下:

2.3 生成项目

配置完成各个参数后,就可以生成项目,打开项目后,其结构如下:

3 PID算法实现

3.1 概念

PID是一种常用的控制算法,全名为比例-积分-微分控制算法(Proportional-Integral-Derivative Control)。它通过对系统的误差进行比例、积分和微分运算,从而对系统进行控制。

PID控制算法的基本原理是:根据当前系统的误差,分别计算比例、积分和微分项,并将它们加权叠加作为最终的控制量。

具体来说,比例项(Proportional)是根据误差的大小与比例系数的乘积来计算的,它决定了控制量与误差之间的直接关系。比例项越大,控制量的调整越快。

积分项(Integral)是根据误差的累积进行计算的,它可以消除系统存在的静态误差,并且对于系统的稳定性有所影响。积分项越大,控制量的调整越缓慢。

微分项(Derivative)是根据误差的变化率进行计算的,它可以预测误差的未来变化趋势,并提前调整控制量。微分项越大,控制量的调整越灵敏。

PID算法的最终控制量是比例项、积分项和微分项的加权叠加,其中比例系数、积分系数和微分系数可以根据实际需求进行调整,以达到最佳的控制效果。

理想的PID控制算法:

• Kp     ——  比例增益, Kp 与比例度成倒数关系
• Tt      ——  积分时间常数
• TD     ——  微分时间常数
• u(t)——  PID 控制器的输出信号
• e(t)——  给定值 r(t)与测量值误差

3.2 代码实现

代码117行: 计算目标值与实际值的误差

代码124行:累计误差值

代码127行:实现PID的功能

代码130行: 传递误差值

实际代码:

typedef struct
{float target_val;       //目标值float actual_val;       //实际值float err;              //定义偏差值float err_last;         //定义上一个偏差值float Kp,Ki,Kd;         //定义比例、积分、微分系数float integral;         //定义积分值
}_pid;/*** @brief  速度PID算法实现* @param  actual_val:实际值@note   无* @retval 通过PID计算后的输出*/
float pid_speed_realize(_pid *pid, float actual_val)
{/*计算目标值与实际值的误差*/pid->err = pid->target_val - actual_val;if((pid->err<0.2f )&& (pid->err>-0.2f)){pid->err = 0.0f;}pid->integral += pid->err;    // 误差累积/*PID算法实现*/pid->actual_val = pid->Kp*pid->err+pid->Ki*pid->integral+pid->Kd*(pid->err-pid->err_last);/*误差传递*/pid->err_last=pid->err;/*返回当前实际值*/return pid->actual_val;
}

4 其他功能实现

4.1 设置电机速度

代码80行: 设置通道1的占空比值

代码81行: 设置通道2的占空比值为0,用于控制方向

实际代码:

void set_motor_speed( uint16_t actual_speed )
{HAL_TIM_SetPWM_Pulse( actual_speed, TIM_CHANNEL_1);HAL_TIM_SetPWM_Pulse( 0, TIM_CHANNEL_2);
}

4.2 PID算法控制电机

代码195行:获取当前电机的转速

代码198行:比较实际值和期望值的差值,便于将实际值控制在一定的范围之内

代码201行:使用实际值进行PID运行,计算出占空比的值,以调节转速

代码205行:设置电机速度

 实际代码:

void motor_pid_control(void)
{float actual_speed, cal_speed ;uint8_t value;bool is_match;uint8_t buff[16];uint32_t delta_value;actual_speed = get_motor_speed();cal_speed = pid_get_target(&pid_speed);is_match = abs((int)((actual_speed- cal_speed)*10)) > 10 ? false : true;if( !is_match ){cal_speed = pid_speed_realize( &pid_speed,actual_speed);    // 进行 PID 计算cal_speed = convet_speed( cal_speed );cal_speed = (cal_speed > PWM_PERIOD_MAX_COUNT) ? PWM_PERIOD_MAX_COUNT : cal_speed;    // 速度上限处理set_motor_speed(cal_speed);                                 // 设置 PWM 占空比}#if defined(PID_ASSISTANT_EN)value = (uint8_t)actual_speed;buff[0] =  value;protocol_computer_value(SEND_FACT_CMD, CURVES_CH1, buff, 1);               // 给通道 1 发送实际值#elseprintf("实际值:%.02f 目标值:%.0f\n", actual_speed, pid_get_target(&pid_speed));      // 打印实际值和目标值#endif
}

4.3 功能函数的调用

代码211行:计算电机的转速

代码217行:电机PID控制函数

 实际源码:

void motor_pid_control(void)
{float actual_speed, cal_speed ;uint8_t value;bool is_match;uint8_t buff[16];uint32_t delta_value;actual_speed = get_motor_speed();cal_speed = pid_get_target(&pid_speed);is_match = abs((int)((actual_speed- cal_speed)*10)) > 10 ? false : true;if( !is_match ){cal_speed = pid_speed_realize( &pid_speed,actual_speed);    // 进行 PID 计算cal_speed = convet_speed( cal_speed );cal_speed = (cal_speed > PWM_PERIOD_MAX_COUNT) ? PWM_PERIOD_MAX_COUNT : cal_speed;    // 速度上限处理set_motor_speed(cal_speed);                                 // 设置 PWM 占空比}#if defined(PID_ASSISTANT_EN)value = (uint8_t)actual_speed;buff[0] =  value;protocol_computer_value(SEND_FACT_CMD, CURVES_CH1, buff, 1);               // 给通道 1 发送实际值#elseprintf("实际值:%.02f 目标值:%.0f\n", actual_speed, pid_get_target(&pid_speed));      // 打印实际值和目标值#endif
}

5 测试

5.1 测试案例1

PID参数设置如下类型,观察速度值的变化(Expect value: speed = 50

    pid_speed.Kp = 7.0;pid_speed.Ki = 20.0;pid_speed.Kd = 14.0;

串口log如下,在5s左右就完成速度定速功能

5.2 测试案例2

PID参数设置如下类型,观察速度值的变化(Expect value: speed = 50

    pid_speed.Kp = 7.0;pid_speed.Ki = 2.0;pid_speed.Kd = 4.0;

串口log如下,在2min左右才完成速度定速功能

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/848489.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python怎么给图片加水印

在Python中&#xff0c;可以使用PIL&#xff08;Python Imaging Library&#xff09;库或者其更活跃的分支Pillow来给图片添加水印。下面是一个简单的示例&#xff0c;展示如何使用Pillow给图片添加文本水印&#xff1a; from PIL import Image, ImageDraw, ImageFont# 打开原…

3072. 将元素分配到两个数组中 II Rust 线段树 + 离散化

题目 给你一个下标从 1 开始、长度为 n 的整数数组 nums 。 现定义函数 greaterCount &#xff0c;使得 greaterCount(arr, val) 返回数组 arr 中 严格大于 val 的元素数量。 你需要使用 n 次操作&#xff0c;将 nums 的所有元素分配到两个数组 arr1 和 arr2 中。在第一次操…

winscp无法上传,删除,修改文件并提示权限不够的分析

使用winscp删除文件,报了个错如下 根据这个错就去百度,网上大部分都是通过下面这种方法解决: 在winscp端进行设置 输入主机名(即IP地址)、用户名和密码,然后点击高级 在箭头所指位置输入sudo + sftp应用程序的路径 先查询 sudo find / -name sftp-server -print点击Sh…

如何让 AI 自动阅读文档样例,编写符合你需求的代码?

&#xff08;注&#xff1a;本文为小报童精选文章。已订阅小报童或加入知识星球「玉树芝兰」用户请勿重复付费&#xff09; 痛点 我本科读的计算机专业。当时编程&#xff0c;讲究的就是个扎实。例如哈夫曼编码用来压缩解压文件&#xff0c;那真的是自己一行行代码写过来的。更…

【Pytorch】计算机视觉项目——卷积神经网络TinyVGG模型图像分类(如何使用自定义数据集)

目录 一、前言二、工作流程回顾三、详细步骤流程1. 环境配置2. 数据准备数据集下载数据存储结构&路径查看图片 3. 数据转换4. 自定义数据集&#xff08;Custom Dataset &#xff09;4.1 方法一&#xff1a;使用ImageFolder加载数据集信息查看张量转图片创建DataLoader 4.2 …

大型ERP设计-业务与功能指引:委托加工二(有偿供料)

委托加工二&#xff08;有偿提供材料&#xff09; 前言&#xff1a;在对ORACLE和SAP的核心模块功能全面解读的基础上&#xff0c;给出大型ERP设计的建议-业务与功能指引&#xff0c;企业选型、开发大型ERP软件的公司和ERP顾问可以参考。模块包括财务、计划与制造、供应链、项目…

Android AAudio——C API创建AudioTrack(六)

虽然 AAudio 试图提供一种直接的硬件访问途径,但在某些场景下,如处理兼容性问题、使用系统服务(如 AudioFlinger)或者在某些设备上,使用 AudioTrack 可能是最有效或最合适的途径。这并不违背 AAudio 的初衷,因为它的目标是提供高性能的音频处理,而不是避免使用系统服务。…

Java Web学习笔记12——JavaScript字符串

String&#xff1a; String字符串对象创建方法有两种&#xff1a; 方式一&#xff1a; var str new String("Hello String"); 方式二&#xff1a; var str "Hello String"; 常见的属性和方法&#xff1a; <!DOCTYPE html> <html lang"…

SwiftUI中ContentUnavailableView的使用(iOS 17、tvOS 17推出的新组件)

iOS 17为SwiftUI带来了一个新的组件ContentUnavailableView&#xff0c;它允许我们向用户呈现一个空状态&#xff0c;而不需要创建自定义错误或者无内容视图。 ContentUnavailableView易于使用&#xff0c;可自定义&#xff0c;并且具有用于空搜索状态的预定义视图。 建议在无…

【考研数学】基础到强化如何衔接? 强化阶段该怎么用书?

我的个人经验在强化阶段之前&#xff0c;只需要基本题型都掌握就足够了。 就比如1800基础篇的习题&#xff0c;你盖住答案自己能做对八九成&#xff0c;那就进入强化绝对够够的了。&#x1f609; 强化的时候&#xff0c;你的正确率可能骤降到三四成&#xff0c;但是完全不用慌!…

【C语言】详解函数(下)(庖丁解牛版)

文章目录 1. 前言2. 数组做函数形参3. 函数嵌套调用和链式访问3.1 嵌套调用3.2 链式访问 1. 前言 详解C语言函数(上)的链接&#xff1a;http://t.csdnimg.cn/EGsfe 经过对函数的初步了解之后,相信大家已经对C语言标准库里的函数已经有初步的认知了&#xff0c;并且还学会了如…

C++面试经验分享

C面经 文章目录 C面经智能指针**内存泄露与智能指针****智能指针有什么类型&#xff0c;各自的原理有什么区别 / 解释下智能指针的实现原理****shared_ptr怎么实现多指针指向同一个地址****引用计数如何保证不同类实例的指针之间共享同步****循环引用会在什么情况下产生&#x…

MATLAB基础应用精讲-【数模应用】二元Logit分析(补充篇)(附python和R语言代码实现)

目录 几个高频面试题目 Logistic与多重线性回归区别 什么情况下用Logistic回归 算法原理

设计模式-工厂方法(创建型)

创建型-工厂方法 简单工厂 将被创建的对象称为“产品”&#xff0c;将生产“产品”对象称为“工厂”&#xff1b;如果创建的产品不多&#xff0c;且不需要生产新的产品&#xff0c;那么只需要一个工厂就可以&#xff0c;这种模式叫做“简单工厂”&#xff0c;它不属于23中设计…

nvme-cli常见命令分析

一、背景 nvme-cli命令常常用于获取或者设置SSD参数&#xff0c;比如常见的nvme list&#xff0c;nvme id-ctrl等&#xff0c;都是获取SSD的基本信息&#xff0c;也有nvme admin-passthru用于读取或者设置自定义命令。作为使用者&#xff0c;我们并不知道nvme-cli源码怎么实现…

光波长 深入程度

UV深入程度&#xff08;UVC&#xff0c; UVB&#xff0c; UVA&#xff09;https://mp.weixin.qq.com/s?__bizMzkwNTM0Njk3MA&mid2247483934&idx1&sn92d1ba67ead404e7714af11ec0526786&chksmc0f868ebf78fe1fd0610493e6f49a5d90835a20a829a900746906cda12f2fa12…

ultralytics-极市平台打榜

ultralytics 应用教程 ultralytics简介 UltralyticsYOLOv8YOLOv8 基于深度学习和计算机视觉领域的尖端技术,在速度和准确性方面具有无与伦比的性能。其流线型设计使其适用于各种应用,并可轻松适应从边缘设备到云 API 等不同硬件平台。链接 安装教程 作为第三方python包直接…

深入探讨Python高级技术

Python作为一种广泛应用的编程语言,以其简洁、易读和强大的功能著称。在高级应用中,Python不仅在数据科学、人工智能和自动化等领域大放异彩,还在性能优化、异步编程和元编程等方面表现出色。本文将深入探讨Python高级技术,包括但不限于性能优化、多线程与多进程编程、异步…

c#通过sqlsugar查询信息并日期排序

c#通过sqlsugar查询信息并日期字段排序 public static List<Sugar_Get_Info_Class> Get_xml_lot_xx(string lot_number){DBContext<Sugar_Get_Info_Class> db_data DBContext<Sugar_Get_Info_Class>.OpDB();Expression<Func<Sugar_Get_Info_Class, b…

RuoYiConfig新增一个路径存储用户头像

/** 上传头像路径 */ private static String userAvatar; public static String getUserAvatar() {return userAvatar; }public void setUserAvatar(String userAvatar) {RuoYiConfig.userAvatar userAvatar; } /*** 获取头像上传路径*/ public static String getUserAvata…