二轮平衡小车3:PID速度环
使用芯片:STM32 F103 C8T6
今日继续我的二路平衡小车开发之路,今日编写的是二轮平衡小车的PID速度环,我准备了纸飞机串口助手软件来辅助测试调节PID。
本文主要贴代码,之前的文章都有原理,代码中相应初始化驱动部分也有注释~~
文章提供源码,解释以及工程下载,测试效果视频。
PID基础概念:
这里简单介绍一下PID算法是反馈调节的算法,只需输入期望值与传感器反馈值即可实现自动调节电机PWM控制速度始终在期望值附近,即:反馈小了就加占空比,反馈大了就减占空比,但却不是简单的加减运算。
原理之前写过,这里直接贴出文章连接:
PID输出反馈回路调控算法原理_NULL指向我的博客-CSDN博客
编码器测速逻辑:
此处贴出函数,相关逻辑在之前的文章讲过:
MSP432自主开发笔记1:编码器测速_外部中断捕获法测速\测正反转_msp432编码器_NULL指向我的博客-CSDN博客
对于速度单位的理解与计算有各种各样,有喜欢算到 (cm/s) (m / s) (rad / second )等等,需要通过不同电机转速,需求来选定。
这里我是用的电机减速比比较大,扭矩与载重大,但因此转速就慢,因此我采用每25ms采样的脉冲数作为速度来比较,使速度环闭合。
//定时器3中断服务程序 (编码器捕获脉冲数)
void TIM3_IRQHandler(void)
{ if(TIM_GetITStatus(TIM3, TIM_IT_CC1)) //通道1发生捕获事件{ Wheel[2].CAPTURE++;TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);} //每次进入中断都要清空中断标志,否则主函数将无法正常执行if(TIM_GetITStatus(TIM3, TIM_IT_CC2)) //通道2发生捕获事件{Wheel[2].CAPTURE++;TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);} //每次进入中断都要清空中断标志,否则主函数将无法正常执行 if(TIM_GetITStatus(TIM3, TIM_IT_CC3)) //通道3发生捕获事件{Wheel[1].CAPTURE++;TIM_ClearITPendingBit(TIM3, TIM_IT_CC3);} //每次进入中断都要清空中断标志,否则主函数将无法正常执行 if(TIM_GetITStatus(TIM3, TIM_IT_CC4)) //通道4发生捕获事件{Wheel[1].CAPTURE++;TIM_ClearITPendingBit(TIM3, TIM_IT_CC4);} //每次进入中断都要清空中断标志,否则主函数将无法正常执行
}void calculate_speed(void)
{uint16_t tt;tt=50;if(SPEED_flag==1){SPEED_flag=0;Wheel[1].SPEED=Wheel[1].CAPTURE;Wheel[2].SPEED=Wheel[2].CAPTURE;// printf("V1=%d,V2=%d\r\n",Wheel[1].SPEED,Wheel[2].SPEED);printf("P1=%d,P2=%d\r\n",Wheel[1].PWM_DIV,Wheel[2].PWM_DIV);PRINT(plotter, "%d, %d, %d",Wheel[1].SPEED,Wheel[2].SPEED,tt); PID_guide_peed(tt,tt);set_wheels(Wheel[1].PWM_DIV,Wheel[2].PWM_DIV,1,1);Wheel[1].CAPTURE=0; Wheel[2].CAPTURE=0;}
}
PID算法贴出:
参数需要自己调,玄学调参......
#include "PID.h"PID_TYPE suduhuan1;
PID_TYPE suduhuan2;//PID 1~4号轮设置期望速度
void PID_guide_peed(uint16_t w1,uint16_t w2)
{Pid_increment_Cal(&suduhuan1,w1,Wheel[1].SPEED);Pid_increment_Cal(&suduhuan2,w2,Wheel[2].SPEED); Wheel[1].PWM_DIV=suduhuan1.OutPut;Wheel[2].PWM_DIV=suduhuan2.OutPut;
}PID_结构体 target_目标 measure_当前值
void Pid_increment_Cal(PID_TYPE *PID, int target, int measure)
{PID->Error = target - measure; // 误差PID->Pout = PID->P * (PID->Error - PID->PreError); // 比例控制PID->Iout = PID->I * PID->Error; // 积分控制PID->Dout = PID->D * (PID->Error - 2 * PID->PreError + PID->PrePreError); // 微分控制// 比例 + 积分 + 微分总控制if (PID->Iout > PID->Irang) // 积分限幅PID->Iout = PID->Irang;if (PID->Iout < -PID->Irang) // 积分限幅PID->Iout = -PID->Irang;PID->OutPut += PID->Pout + PID->Iout + PID->Dout;PID->PrePreError = PID->PreError; // 记忆e(k-2)PID->PreError = PID->Error; // 记忆e(k-1)}void PidParameter_init(void)
{suduhuan1.P =38;suduhuan1.I=18;suduhuan1.D=0;suduhuan1.PreError=0;suduhuan1.PrePreError=0;suduhuan1.Irang=12;suduhuan1.OutPut=0;suduhuan2.P =38;suduhuan2.I=18;suduhuan2.D=0;suduhuan2.PreError=0;suduhuan2.PrePreError=0;suduhuan2.Irang=12;suduhuan2.OutPut=0;
}
#ifndef _PID_H_
#define _PID_H_#include "headfire.h"typedef struct PID
{int P; //参数int I;int D;float Error; //比例项e(k)float Integral; //积分项int Differ; //微分项int PreError; //e(k-1)int PrePreError;//e(k-2)float Ilimit;float Irang;int Pout;int Iout;int Dout;int OutPut;uint8_t Ilimit_flag; //积分分离
}PID_TYPE;extern PID_TYPE suduhuan1;
extern PID_TYPE suduhuan2;PID_结构体 target_目标 measure_当前值
void Pid_increment_Cal(PID_TYPE *PID, int target, int measure);
void PidParameter_init(void); //PID参数初始化 //PID 设置期望速度
void PID_guide_peed(uint16_t w1,uint16_t w2);#endif
相关文章:
二轮平衡小车3:PID速度环
使用芯片:STM32 F103 C8T6 今日继续我的二路平衡小车开发之路,今日编写的是二轮平衡小车的PID速度环,我准备了纸飞机串口助手软件来辅助测试调节PID。 本文主要贴代码,之前的文章都有原理,代码中相应初始化驱动部分也…...
C语言之练习题
欢迎来到我的世界 希望这篇文章对你有所帮助,有不足的地方还请指正,大家一起学习交流 ! 目录 前言编程题第一题:珠玑妙算第二题:寻找奇数第三题:寻找峰值第四题:数对 总结 前言 这是暑假题目的收尾文章&am…...
没钱,没人,没经验?传统制造型企业如何用无代码实现转型
2023年,国家市场监督管理总局发布了三项重要标准,包括《工业互联网平台选型要求》、《工业互联网平台微服务参考框架》和《工业互联网平台开放应用编程接口功能要求》。这些标准的发布对于完善工业互联网平台标准体系,提升多样化工业互联网平…...
CentOS ARM 部署 kubernetes v1.24.6
1.背景 之前安装的kubernetes版本为v1.19.0 树莓派使用(CentOS7.9 armv71 Kubernetes1.19.0), 由于版本过低,一些HPA相关的功能支持不是特别好,因此需要将版本升级,本次会将版本升级为v1.24.6. 2. 如何upgrade 2.1. 优雅升级 kubeadm自带…...
LeetCode 725. Split Linked List in Parts【链表】中等
本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章…...
云计算中的负载均衡技术,确保资源的平衡分配
文章目录 1. 硬件负载均衡器2. 软件负载均衡器3. DNS负载均衡4. 内容分发网络(CDN) 🎈个人主页:程序员 小侯 🎐CSDN新晋作者 🎉欢迎 👍点赞✍评论⭐收藏 ✨收录专栏:云计算 ✨文章内…...
探索 SOCKS5 代理在跨境电商中的网络安全应用
随着全球化的发展,跨境电商成为了商业界的一颗新星,为企业提供了无限的发展机遇。然而,随之而来的是网络安全的挑战,特别是在处理国际网络流量时。在这篇文章中,我们将探讨如何利用 SOCKS5 代理和代理 IP 技术来加强跨…...
全网独家:编译CentOS6.10系统的openssl-1.1.1多版本并存的rpm安装包
CentOS6.10系统原生的openssl版本太老,1.0.1e,不能满足一些新版本应用软件的要求,但是它又被wget、mysql-libs、python-2.6.6、yum等一众系统包所依赖,不能再做升级。故需考虑在不影响系统原生openssl的情况下,安装较新…...
【go】异步任务解决方案Asynq实战
文章目录 一.Asynq介绍二.所需工具三.代码示例四.Reference 一.Asynq介绍 Asynq 是一个 Go 库,一个高效的分布式任务队列。 Asynq 工作原理: 客户端(生产者)将任务放入队列服务器(消费者)从队列中拉出任…...
掌握 Android 自动化测试框架 UiAutomator UiAutomator2
掌握 Android 自动化测试框架 UiAutomator & UiAutomator2 一、UiAutomator 简介二、UiAutomator2 的诞生三、UiAutomator2 的应用实践总结你是否曾经在进行 Android 应用开发时,对于如何进行全面、有效的自动化测试感到困惑?你是否想要更高效地进行 UI 测试,而不是一遍…...
c#抽象类(abstract)
概述: C#中的抽象类是一种特殊类型的类,它不能被实例化,只能被继承。抽象类用于提供一个共享的基类,其中定义了一些方法和属性的签名,但没有具体的实现。这些方法和属性可以在派生类中进行实现。 使用抽象类的主要目…...
语义分割实践思考记录(个人备忘录)
一、任务管理器、NVDIA的GPU利用率显示[1][2] 若需要在任务管理器中查看基于Pytorch框架的GPU利用率,那么,我们需要将监控面板监测内容调整为cuda。图一(左)即为英伟达命令行工具面板。 图一 英伟达GPU使用率监控 二、基于混淆矩阵…...
Zebec Protocol 成非洲利比亚展会合作伙伴,并将向第三世界国家布局
在 9 月 6 日,The Digital Asset Summit ’23(利比亚大会)在尼日利亚首度阿布贾的 NAF 会议中心举办,该会议对 Web3 领域在非洲地区的发展进行了探索,旨在推动非洲地区区块链产业的进一步发展,据悉该会议室…...
随机流-RandomAccessFile
RandomAccessFile RandomAccessFile 基本操作案例 RandomAccessFile 基本操作 案例 import java.io.*;public class TestMain09 {public static void main(String[] args) throws Exception {insert("D:\\home\\product\\aa.txt",2,"ni");}public static…...
单例和静态类
C#中的单例(Singleton)和静态类(Static Class)是两种不同的设计模式,它们各自有不同的用途和特点。 单例模式是一种设计模式,它确保一个类只有一个实例,并提供全局访问点。通常,单例…...
PMP-项目风险管理的重要性
一、什么是项目风险管理 项目风险管理旨在识别和管理未被其他项目管理过程所管理的风险。如果不妥善管理,这些风险有可能导致项目偏离计划,无法达成既定的项目目标。因此,项目风险管理的有效性直接关乎项目成功与否。 每个项目都在两个层面…...
学习的心得
文章目录 第一节课心得**学会了敲写数学公式** 第一节课心得 老师讲得非常好,我们下载了xmind,如何制作思维导图 学会了敲写数学公式 ∫ 10 20 ( x 2 − 3 x 2 ) d x \displaystyle\int_{10}^{20}(x^2-3x2)dx ∫1020(x2−3x2)dx...
Python网络爬虫中这七个li标签下面的属性值,不是固定的,怎样才能拿到他们的值呢?...
点击上方“Python爬虫与数据挖掘”,进行关注 回复“书籍”即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 愚以为宫中之事,事无大小,悉以咨之,然后施行,必能裨补阙漏,有所广益。 大家好,我…...
白鲸开源 DataOps 平台加速数据分析和大模型构建
作者 | 李晨 编辑 | Debra Chen 数据准备对于推动有效的自助式分析和数据科学实践至关重要。如今,企业大都知道基于数据的决策是成功数字化转型的关键,但要做出有效的决策,只有可信的数据才能提供帮助,随着数据量和数据源的多样…...
(其他) 剑指 Offer 65. 不用加减乘除做加法 ——【Leetcode每日一题】
❓ 剑指 Offer 65. 不用加减乘除做加法 难度:简单 写一个函数,求两个整数之和,要求在函数体内不得使用 “”、“-”、“*”、“/” 四则运算符号。 示例: 输入: a 1, b 1 输出: 2 提示: a, b 均可能是负数或 0结果不会溢出 …...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...
