HAL库版STM32双轮自平衡车(一) ———代码思路和PID的简单介绍(本篇)
HAL库版STM32双轮自平衡车(二) ——— CubeMX的配置、原理图接线、物料准备
HAL库版STM32双轮自平衡车(四) ———— 原理图以及PCB绘制
目录
完整工程以及学习资料(设置了收费望理解)
https://m.tb.cn/h.UHqbvHr?tk=gXkZdkAKGX1
趁着暑假时间充裕,我也是完成了平衡小车的制作,现在实现的功能仅限于小车自平衡保持直立以及外界干扰(如:手用力推小车)时小车能够以很快的响应速度恢复平衡直立。接下来会写关于制作HAL库版平衡小车的系列文章。系列文章的链接放在了文章开头的系列文章目录里。
这篇文章也就是HAL库版STM32平衡小车的第一篇将重点讲解一下怎么编写平衡小车代码的思路以及一些基础的PID知识点,跟着我的思路相信你一定能在自己的脑海里面形成一个完整的框架,话不多说我们开始吧。
p控制器(比例)
作用是:减小测量值和期望值之间的误差,让测量值不断接近期望值。
缺点是:存在稳态误差(静差)。若存在固定扰动时,P控制律不能迅速响应。
I控制器(积分)
作用是:消除静差,所谓静差,就是系统稳定后输出值和设定值之间的差值,积分环节实际上就是偏差累计的过程,把累计的误差加到原有系统上以抵消系统造成的静差。
缺点是:控制不及时。因为积分输出的累积是渐进的,其产生的控制作用总是落后于偏差的变化,不能及时有效地克服干扰的影响,难以使控制系统稳定下来。
D控制器(微分)
作用是:反应了偏差信号的变化规律,或者说是变化趋势,根据偏差信号的变化趋势来进行超前调节,从而增加了系统的快速性。
缺点是:放大噪声。
通过上述的代码框架,可以知道我的这个平衡小车用的是位置式并联型PID控制
式中输出的u(k)可直接用来控制 系统需要控制的对象,u(k)的值和控制对象是一一对应的,因此通常称该公式为位置式PID控制算法。位置式PID缺点是每次输出均与过去的状态有关,计算时要对e(k)进行累加,计算繁琐,保存e(i)占用很多内存,控制不方便。增量式PID和位置式PID没有本质区别,就是数字PID的两种不同表示形式而已,在不同的系统中,根据题的具体内容选择适合的方法,位置式需要历次的偏差信号,而增量式只需一个增量信号即可。增量式误动作小,易于实现手动/自动的无扰动切换,不产生积分失控。但是缺点在于积分截断效应大,溢出影响大。
下面也给出增量式PID的数学公式:
并联型PID实现了比例项,积分项和微分项的完全解耦,调节其中的Kp,Ki 与 Kd即可独立的作用在比例,积分和微分项上;而标准形式的Kp将同时影响比例,积分和微分三项行为。串联型类似

虽然位置式计算较为繁琐,但是在位置式直立环的微分项中,角度的微分可以直接采用mpu6050采集到的y轴角速度值,比较容易理解。
采用并联型PID是因为可以让直立环和角度环独立开来,易于理解,调参也比较容易。当然如果采用串联型,那么就要将直立环设置为内环,速度环设置为外环,并且速度环的输出就要作为直立环期望角度的输入,因为重点在于保持直立状态。
当角度接近机械零度时,P控制器就不工作了,控制器认为完成了任务,然而控制器忽略了角度在机械零度时电机还存在角速度,简单来说就是小车还有惯性。这时候就需要加入D控制器,预测下一时刻的偏差,进行超前调节,从而增加了系统的快速性。反过来想就是这个PID控制器中为什么不用积分。这里必须知道的一点是当比例系数很大的时候系统几乎没有静差。平衡小车直立控制需要快速性,相比之下P是很大的,积分的作用是消除静差,而静差对于直立控制的影响很小自然就不需要积分了。实际上平衡小车不一定要完全处于机械中值,稍微偏一点点也没有关系,只要稳定就行了。再有一点,小车需要尽可能快的达到直立平衡,I控制存在着控制不及时的缺点。
所以对于准确性要求不高的系统可以不加入积分控制。
小车光有直立环也是可以直立一小会儿的,但是一但外界有干扰(比如用手推了小车),小车只能通过单方向运动维持平衡,加入速度环就是修正小车的角度,小车一直往前面开时,速度环让小车以更快速度行驶使得小车后仰,这时直立控制让小车后退以维持平衡。
对于速度控制当然是越精确越好,平衡小车当然希望速度一直为0。但是光有P控制器是不够的,因为P控制器的主要缺点是存在静差。那么就需要用I积分控制器来消除静差。
虽然D控制器可以预测未来,提前响应,但是微分控制的缺点是放大噪声。速度控制的速度偏差是由直立控制电机运动引起的,即速度噪声很大,所以不加入微分控制。
所以对于准确性要求高,系统噪声大时可以采用PI控制。
我认为这是关于制作HAL库版平衡小车的重中之重,在编写代码前应该在脑海里面有一个大体的思路至关重要,这一步的完成度关系着之后编写代码的效率和质量。
下面就来开始吧,一步步进行。
之后在CubeMX中的配置就可以按上述步骤一步步来。
这篇文章就叙述完了,下一篇文章重点讲解CubeMX的配置、原理图接线、物料准备,以及在配置时遇到的“大坑”,CubeMX的配置思路也是与本篇文章所讲息息相关。
码字不易,希望喜欢的小伙伴别忘了点赞+收藏+关注,你们的肯定就是我创作的动力
欢迎大家积极交流,本文未经允许谢绝转载!!!
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has
如何匹配未被反斜杠转义的平衡定界符对(其本身未被反斜杠转义)(无需考虑嵌套)?例如对于反引号,我试过了,但是转义的反引号没有像转义那样工作。regex=/(?!$1:"how\\"#expected"how\\`are"上面的正则表达式不考虑由反斜杠转义并位于反引号前面的反斜杠,但我愿意考虑。StackOverflow如何做到这一点?这样做的目的并不复杂。我有文档文本,其中包括内联代码的反引号,就像StackOverflow一样,我想在HTML文件中显示它,内联代码用一些spanMaterial装饰。不会有嵌套,但转义反引号或转义反斜杠可能出现在任何地方。
我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru
我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的
几个月前,我读了一篇关于rubygem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:
我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur
前言作为一名程序员,自己的本质工作就是做程序开发,那么程序开发的时候最直接的体现就是代码,检验一个程序员技术水平的一个核心环节就是开发时候的代码能力。众所周知,程序开发的水平提升是一个循序渐进的过程,每一位程序员都是从“菜鸟”变成“大神”的,所以程序员在程序开发过程中的代码能力也是根据平时开发中的业务实践来积累和提升的。提高代码能力核心要素程序员要想提高自身代码能力,尤其是新晋程序员的代码能力有很大的提升空间的时候,需要针对性的去提高自己的代码能力。提高代码能力其实有几个比较关键的点,只要把握住这些方面,就能很好的、快速的提高自己的一部分代码能力。1、多去阅读开源项目,如有机会可以亲自参与开源
嗨~大家好,这里是可莉!今天给大家带来的是7个C语言的经典基础代码~那一起往下看下去把【程序一】打印100到200之间的素数#includeintmain(){ inti; for(i=100;i 【程序二】输出乘法口诀表#includeintmain(){inti;for(i=1;i 【程序三】判断1000年---2000年之间的闰年#includeintmain(){intyear;for(year=1000;year 【程序四】给定两个整形变量的值,将两个值的内容进行交换。这里提供两种方法来进行交换,第一种为创建临时变量来进行交换,第二种是不创建临时变量而直接进行交换。1.创建临时变量来
文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,