精华内容
下载资源
问答
  • 智能车PID 控制

    千次阅读 2018-09-01 03:53:09
    PID 控制策略其结构简单, 稳定性好, 可靠性高, 并且易于实现。 其缺点在于控制器的参数整定相当繁琐, 需要很强的工程经验。 相对于其他的控制方式,在成熟性和可操作性上都有着很大的优势。 使用试凑法来确定...

    PID 控制策略其结构简单, 稳定性好, 可靠性高, 并且易于实现。 其缺点在于控制器的参数整定相当繁琐, 需要很强的工程经验。 相对于其他的控制方式,在成熟性和可操作性上都有着很大的优势。 使用试凑法来确定控制器的比例、 积分和微分参数。
    试凑法是通过闭环试验, 观察系统响应曲线, 根据各控制参数对系统响应的大致影响, 反复试凑参数, 以达到满意的响应, 最后确定 PID 控制参数。 试凑不是盲目的,而是在控制理论指导下进行的。在控制理论中已获得如下定性知识:

    比例调节(P)作用:
    是按比例反应系统的偏差, 系统一旦出现了偏差, 比例调节立即产生调节作用用以减少偏差。 比例作用大, 可以加快调节, 减少误差, 但是过大的比例,使系统的稳定性下降, 甚至造成系统的不稳定。
    积分调节(I) 作用:
    是使系统消除稳态误差, 提高无差度。 因为有误差, 积分调节就进行, 直至无差, 积分调节停止, 积分调节输出一常值。 积分作用的强弱取决与积分时间常数 Ti, Ti 越小, 积分作用就越强。 反之 Ti 大则积分作用弱, 加入积分调节可使系统稳定性
    下降, 动态响应变慢。 积分作用常与另两种调节规律结合, 组成 PI 调节器或 PID调节器。

    微分调节(D) 作用:
    微分作用反映系统偏差信号的变化率, 具有预见性, 能预见偏差变化的趋势, 因此能产生超前的控制作用, 在偏差还没有形成之前, 已被微分调节作用消除。 因此, 可以改善系统的动态性能。 在微分时间选择合适情况下, 可以减少超调, 减少调节时间。 微分作用对噪声干扰有放大作用,因此过强的加微分调节, 对系统抗干扰不利。 此外, 微分反应的是变化率, 而当输入没有变化时, 微分作用输出为零。 微分作用不能单独使用, 需要与另外两种调节规律相结合, 组成 PD 或 PID 控制器。

    舵机pd控制

    舵机控制
    其关键部分代码如下:
    servo_pwm_change = (wucha_Now* Kp_servo + Kd_servo*(wucha_Now-wucha_Last)) / 100;
    其中, KP_servoKD_servo 两个重要的参数需要经过不断调整。 在实际调试中发现, 针对赛道类型给定参数更符合实际。 例如, 在直道和小 S 路上相应的KP_servo 可以给小, 以防舵机打角过大。 分段各段之间参数的给定要连续, 否
    则会出现舵机在参数切换之后出现较大突变, 导致智能汽车的路径变差。 我们设置一个数学函数控制参数的输出, 减少调节参数的工作量。 当然为了防止把舵机的齿轮打坏, 应该对舵机的打角进行限幅处理。

    展开全文
  • pid控制算法,pid算法介绍,从熟悉到精通pid,pid控制实际应用例程
  • 智能车PID控制学习笔记

    千次阅读 多人点赞 2020-05-30 15:29:14
    智能车中还有方向PID控制(舵机调整方向),不过考虑到舵机相当于简化版的伺服电机,还是调节速度收益更大。 为什么要用PID 在理想情况下,小车的速度调节成线性,即当PWM=60%时,小车速度是2M/S;把PWM提高到90%...

    主要谈及直流电机的速度PID控制,在智能车中还有方向PID控制(舵机调整方向)。

    为什么要用PID

    在理想情况下,小车的速度调节成线性,即当PWM=60%时,小车速度是2M/S;把PWM提高到90%,则小车速度为3M/S;但实际上由于各种因素的影响,往往实际速度和输入速度有误差,因此必须要通过某种算法进行调整,PID控制的意义就在于消除这种误差。
    在这里插入图片描述

    PID理论基础

    PID控制器(比例-积分-微分控制器),由比例单元§、积分单元(I)和微分单元(D)组成,通过Kp, Ki和Kd三个参数进行设定。
    P代表了当前的信息,起纠正偏差的作用,使反应迅速;
    D代表了将来的信息,在过程开始时强迫过程进行,过程结束时减小超调,克服振荡,提高系统的稳定性,加快系统的过渡过程;
    I代表了过去积累的信息,它能消除静差,改善系统的静态特性。

    比例环节(放大环节):输出量以一定比例不失真也无时间滞后地复现输入信号
    积分环节:输出量正比于输入量单独积分
    微分环节:其输出与输入量的导数成比例

    PID控制器主要适用于线性且动态特性不随时间变化的系统。当不完全了解一个系统和被控对象或不能通过有效的测量手段来获得系统参数时,最适合采用PID控制技术。
    在这里插入图片描述

    动态性能指标:
    见下方时域图。
    在这里插入图片描述

    1.比例(proportion)控制
    比例控制器能立即成比例地响应输入的变化量,其实质相当于一个放大器。调节器输出u与其输入偏差e之间的关系是比例关系,误差值和kp相乘,然后和预定的值相加。仅有比例控制时,系统输出存在稳态误差,这是由比例控制的本质决定的,如果偏差为0,比例控制器就会失去作用,从而导致偏差增大,因此很少单独使用比例控制。

    u=kp*error
    

    在这里插入图片描述
    上图为比例控制。

    稳态误差是指时间趋于无穷时(即系统稳定后)输出量与期望输出的偏差。控制系统的稳态误差越小说明控制精度越高。

    2.比例积分(PI)控制
    即比例+积分(PI)控制器。
    为了消除稳态误差,在控制器中必须引入“积分项”。积分项对误差的运算取决于时间的积分,随着时间增加,积分项会增大,所以即便误差很小,积分项也会随时间增加而加大,它推动控制器的输出增大,使稳态误差进一步减小,直到等于零。但是积分作用的引入,会使系统稳定性变差(见图)。
    比例积分控制对于时间滞后的被控对象使用不够理想。

    u=kp*error+ ki∗∫ error
    

    在这里插入图片描述
    上图为比例积分控制。

    3.比例微分(PD)控制
    即比例+微分(PD)控制器。
    在微分控制中,控制器的输出与输入误差信号的微分(即误差的变化率)成正比关系。自动控制系统在克服误差的调节过程中可能会出现振荡甚至失稳。其原因是由于存在有较大惯性组件(如储能元件)或有滞后(delay)组件,具有抑制误差的作用,其变化总是落后于误差的变化。
    解决的办法是使抑制误差的作用的变化“超前”,即在误差接近零时,抑制误差的作用就应该是零。目前需要增加的是“微分项”,它能预测误差变化的趋势,这样,具有比例+微分的控制器,就能够提前使抑制误差的控制作用等于零,甚至为负值,从而避免了被控量的严重超调。
    所以对有较大惯性或滞后的被控对象,比例+微分(PD)控制器能改善系统在调节过程中的动态特性,否则反而会使系统的控制受到影响。

    u=kd*(error(t)-error(t-1))
    

    4.PID控制
    PID的离散化公式(便于计算机处理)为:
    在这里插入图片描述
    在这里插入图片描述
    上图为比例积分微分控制(理想情况)。

    变频器的闭环运行就是在变频器控制的拖动系统中引入负反馈,进行反馈控制,以提高反馈精度。

    关于对PID算法的通俗理解,可参考:
    https://zhuanlan.zhihu.com/p/39573490 PID控制算法原理 (抛弃公式,从本质上真正理解PID控制)

    PID控制器的参数整定

    PID参数对控制质量的影响不十分敏感,因而不同的PID系数的组合可能达到相近的控制效果。

    编写可行的PID程序从来不是什么难点,难的是PID参数整定,异常麻烦以至于我们宁愿用开环控制。
    需要设定的值有:

    ● Setpoint:目标值
    ● Kp,Ki,Kd: pid参数
    ● OutputLimits:输出极限
    ● SampleTime:采样时间

    一般采用的是临界比例法(属于工程整定法)。

    工程整定法主要依赖工程经验,直接在控制系统的试验中进行,且方法简单、易于掌握,在工程实际中被广泛采用。(简单来讲就是试凑)

    利用该方法进行PID控制器参数的整定步骤如下:
    (1)首先预选择一个足够短的采样周期让系统工作,输入设定为系统允许的最大值的60%~70%;
    (2)仅加入P比例控制环节。初调时,选小一些,然后慢慢调大,直到系统对输入的阶跃响应出现临界振荡,记下这时的比例放大系数和临界振荡周期,设定PID的比例增益P为当前值的60%~70%;
    (3)加入I积分控制环节。积分系数初调时要把积分时间设置长些,然后慢慢调小直到系统稳定为止,设定PID的积分时间常数Ti为当前值的150%~180%。

    一般情况下到此为止

    (4)D微分控制环节一般不用设定。如果通过比例、积分参数的调节还是收不到理想的控制要求,才调节微分时间。初调时把这个系数设小,然后慢慢调大,直到系统稳定。

    1.PID控制器的参数整定(经验总结)
    2.PID:从入门到放弃

    舵机的PID参数整定

    舵机通常采用PD算法,智能车过弯是一个比较特殊的环境,去掉参数I可以加快系统的反应速度,使小车过弯更加顺畅。

    展开全文
  • 本课题以MC9S12XS128芯片开发的自动寻迹智能车为研究对象, 主要针对增量式PID控制在复杂多变的系统中抗干扰性不强,时变系 统中的响应不够快等问题,进行算法上的改进。主要研究内容: (1)构建了以MC9S12XS...
  • 两轮智能车PID控制如何实现

    千次阅读 2020-01-03 15:52:39
    都知道PID控制,但是总是没有搞清楚,看了很多公式和图形就是没整明白。下面这个图形就是pid控制的原理图。 PID算法在很多方面都有重要应用,比如电机的速度控制,恒温槽的温度控制,四轴飞行器的平衡控制等等,...

    PID基础理论知识

    都知道PID控制,但是总是没有搞清楚,看了很多公式和图形就是没整明白。下面这个图形就是pid控制的原理图。

    PID算法在很多方面都有重要应用,比如电机的速度控制,恒温槽的温度控制,四轴飞行器的平衡控制等等,作为闭环控制系统中的一种重要算法,PID算法是有比例,积分,微分三部分组成。关于PID通俗易懂的一篇文章介绍,推荐博客网址:https://blog.csdn.net/qq_25352981/article/details/81007075

    比例部分

                Kp:比例系数

               SetValue:预设值

               FactValue:当前实际值

               Error_1:当前误差

    则比例部分为:Sp= Kp*(SetValue - FactValue)   或者 Sp=Kp*Error_1

    注解:Sp大小反应需要控制的量大小,比如Sp越大,功率越大。当Sp为负值时,表示要超过预设值,如果是电机,则需要反转。

    积分部分

               Ki:积分系数  

               Error_1:当前误差  

               Error_2:上一次误差  

               Error_3:上上一次误差

                ........

               Error_n:开始时的误差

    则积分部分为:Si=Ki*(Error_1+Error_2+Error_3+......+Error_n)

    注解:因为整个是一个过程,所以上一次误差其实就是上一次的当前误差。

    微分部分

               Kd:微分系数 

               Error_1:当前误差  

               Error_2:上一次误差 

    则微分部分为:Sd=Kd*(Error_1-Error_2)。

    综上部分的PID得:

        PID=Sp + Si + Sd = Kp*Error_1 + Ki*(Error_1+Error_2+Error_3+......+Error_n) + Kd*(Error_1-Error_2)

    两轮智能车的PID控制技术

    我做的智能车主要是两轮,那就介绍两轮的PID控制方法,多轮可以照样改写。把之前制作的遥控收球机的代码放到这里跟大家分享。

    对于两轮智能车的PID控制主要使用了下面这个函数:

    
    void bieber_moto_Control(float current_speed,float target_speed, unsigned char Moto_ID)
    {
    	float Error   = 0;
    	float P_Error = 0;
    	float I_Error = 0;
    	float D_Error = 0;
    	float add     = 0;
    	
    	if(Moto_ID == LEFT)
    	
    		Error = target_speed - current_speed;                  //计算误差
    		P_Error = Error;                                       //比例环节
    		I_Error = Error - Left_L_Error;                        //积分环节
    		D_Error = Error - 2*Left_L_Error + Left_LL_Error;      //微分环节
    		
    		add = KP * P_Error + KI * I_Error + KD * D_Error;      //左轮PID增加值
    		Left_ESC_Output_PWM += add;                            //计算PWM输出值
    		
    		Left_LL_Error = Left_L_Error;
    		Left_L_Error = Error;
    		
    	
    	else if(Moto_ID == RIGHT)
    	{
    		Error = target_speed - current_speed;                   //计算误差
    		P_Error = Error;                                        //比例环节
    		I_Error = Error - Right_L_Error;                        //积分环节
    		D_Error = Error - 2*Right_L_Error + Right_LL_Error;     //微分环节
    
    		add = KP * P_Error + KI * I_Error + KD * D_Error;       //左轮PID增加值
    		Right_ESC_Output_PWM += add;                            //计算PWM输出值
    		
    		Right_LL_Error = Right_L_Error;
    		Right_L_Error = Error;
    	}
    
    	PWM_Output(Left_ESC_Output_PWM, Right_ESC_Output_PWM);  //输出左右轮的PWM
    }
    

     希望上面代码对你开发两轮智能车有一定帮助,谢谢大家!

    展开全文
  • 智能小车PID算法资料,一些自己用的7788的资料
  • 51单片机智能小车PID速度控制算法源代码,该PID算法可以将智能小车的速度控制在设定的速度值上。需要结合测速模块使用。
  • Arduino智能小车直线控制-模糊PID控制

    千次阅读 多人点赞 2020-04-20 22:07:10
    本文主要由三部分构成:模糊PID控制器的原理,模糊PID控制器C++的实现与测试,把模糊PID控制算法应用于Arduino 智能小车走直线的过程中。 一,模糊PID原理 模糊PID控制流程如下图所示,把目标值Xtarget与...

    本文主要是基于Arduino智能小车直线走不直的问题,运用模糊PID算法进行控制。本文主要由三部分构成:模糊PID控制器的原理,模糊PID控制器C++的实现与测试,把模糊PID控制算法应用于Arduino 智能小车走直线的过程中。

     

    一,模糊PID原理

           模糊PID控制流程如下图所示,把目标值 Xtarget 与输出值 Xout 的误差 与 的变化率 de/dt 作为模糊控制器的输入,模糊控制器先对输入进行模糊化处理,接着进行模糊推理,最后把模糊推理的结果进行去模糊处理输出PID控制器的三个参数 kp, ki, kd,从而达到对PID控制器参数自适应整定的效果。

     

           根据以上的描述可知,模糊控制器主要由去模糊化,模糊推理以及去模糊三部分组成。以下将对三部分进行详细讲解。

        1.1  模糊化

                   要实现模糊化首先需要对模糊化进行初始化,初始化包括论域的确定以及隶属度函数的确定。

                  1.1.1 论域

                          论域可以说是一个人为确定的范围,由于输入e,de/dt,输出kp.ki,kd的范围各不相同,把输入映射到论域上更好统一处理。确定论域的范围后,需要对论域进行模糊分类,模糊分类即对论域进行划分。假设论域的范围为[-3,3],把论域平均分为5等份,即[-3,-2],[-2,-1],[-1,0],[0,1],[1,2],[2,3]。接着把每个端点进行等级划分,依次为-3--->NB(负大),-2--->NM(负中),-1---->NS(负小),0--->ZO(零),1---->PS(正小),2---->PM(正中),3---->PB(正大)。假设输入e的范围为[-10,10],此刻e的值为8,通过映射后的值为2.4,2.4在[2,3]区间,则该点在正中与正大之间。示意图如下:

     

               1.1.2 隶属度函数的确定。

                      常见的隶属度函数有三角形隶属度函数,梯形隶属度函数,抛物线型隶属度函数。以最简单的三角性隶属度函数为例,形状如下图所示:

       由上图可知,隶属度函数的值域为[0,1]。若输入e经过映射后的值为2.4,那么对应下图红线与绿线的值分别为0.6,0.4,这两个就是隶属度,表示该输入属于PM的概率为0.6,而属于PB的概率为0.4。所以隶属度也为概率。

          由上述论域和隶属度函数的讲解,可总结出模糊化的过程:区间映射,根据隶属度函数计算隶属度,流程图如下:

     

        1 2. 模糊推理

              模糊推理,即根据e与de/dt 的隶属度进行查表得到输出的大小程度,即NB,NS等。所以模糊推理的核心工作是建立推理表。其中模糊PID常用的推理表如下图所示:

     

     

     

    以下以一个例子说明规则表的使用方法。

    假设此刻的输入e为8,de/dt为-12,而e的范围为[-10,10],de/dt的范围为[-20,20]。则通过模糊化得到e的隶属度为0.6(PM)与0.4(PB),de/dt的隶属度为0.8(NM)与0.2(NS),然后,对e与de/dt的隶属度进行两两组合,并进行查表,得到下表的关系:

    接着,计算各输出Kp,Ki,Kd的隶属度。

    Kp:       

                                     

    同理Ki.Kd也计算隶属度。

    最后进行个输出的隶属度进行整合,例如Kp,由上面计算可知,Kp的隶属度为0.8(ZO),0.12(NS),0.08(NM)。

    1.3 去模糊

      去模糊是根据模糊推理得到的各输出的隶属度算出输出在论域中的哪个值,然后根据区间映射关系,得到输出。

      1.3.1   计算输出在论域中的值

                以上面的例子进行阐述计算的过程。由上面可知,Kp的隶属度为0.8(ZO),0.12(NS),0.08(NM),而在论域讲解时,已经将ZO的值定为0,NS的值定为-1,NM的值定为-2。那么Kp的期望为:

                                             把期望作为Kp在论域的值,在确定Kp的范围后,根据区间映射公式,可得出Kp的输出值。

     

    以上为模糊控制器的流程。值得注意的是,输出的Kp,Ki,Kd为增量。在初始化时要确定输入与输出的范围(区间),用于进行区间映射。

     

    2.1  C++实现模糊PID控制 器

          该本版隶属度函数为固定三角形隶属度函数,论域固定为[-3,3]。

      FuzzyPID.h头文件

    #ifndef FuzzyPID_H
    #define FuzzyPID_H
    class FuzzyPID
    {
    public:
    	FuzzyPID();
    	~FuzzyPID();
    	void Get_grad_membership(float erro, float erro_c);
    	float Quantization(float maximum, float minimum, float x);
    	float Inverse_quantization(float maximum, float minimum, float qvalues);
    	void GetSumGrad();
    	void GetOUT();
    	float FuzzyPIDcontroller(float e_max, float e_min, float ec_max, float ec_min, float kp_max, float kp_min, float erro, float erro_c, float ki_max, float ki_min,float kd_max, float kd_min,float erro_pre, float errp_ppre);
    	const int  num_area = 8; //划分区域个数
    	//float e_max;  //误差做大值
    	//float e_min;  //误差最小值
    	//float ec_max;  //误差变化最大值
    	//float ec_min;  //误差变化最小值
    	//float kp_max, kp_min;
    	float e_membership_values[7] = {-3,-2,-1,0,1,2,3}; //输入e的隶属值
    	float ec_membership_values[7] = { -3,-2,-1,0,1,2,3 };//输入de/dt的隶属值
    	float kp_menbership_values[7] = { -3,-2,-1,0,1,2,3 };//输出增量kp的隶属值
    	float ki_menbership_values[7] = { -3,-2,-1,0,1,2,3 }; //输出增量ki的隶属值
    	float kd_menbership_values[7] = { -3,-2,-1,0,1,2,3 };  //输出增量kd的隶属值
    	float fuzzyoutput_menbership_values[7] = { -3,-2,-1,0,1,2,3 };
    
    	//int menbership_values[7] = {-3,-};
    	float kp;                       //PID参数kp
    	float ki;                       //PID参数ki
    	float kd;                       //PID参数kd
    	float qdetail_kp;               //增量kp对应论域中的值
    	float qdetail_ki;               //增量ki对应论域中的值
    	float qdetail_kd;               //增量kd对应论域中的值
    	float qfuzzy_output;  
    	float detail_kp;                //输出增量kp
    	float detail_ki;                //输出增量ki
    	float detail_kd;                //输出增量kd
    	float fuzzy_output;
    	float qerro;                    //输入e对应论域中的值
    	float qerro_c;                  //输入de/dt对应论域中的值
    	float errosum;                  
    	float e_gradmembership[2];      //输入e的隶属度
    	float ec_gradmembership[2];     //输入de/dt的隶属度
    	int e_grad_index[2];            //输入e隶属度在规则表的索引
    	int ec_grad_index[2];           //输入de/dt隶属度在规则表的索引
    	float gradSums[7] = {0,0,0,0,0,0,0};
    	float KpgradSums[7] = { 0,0,0,0,0,0,0 };   //输出增量kp总的隶属度
    	float KigradSums[7] = { 0,0,0,0,0,0,0 };   //输出增量ki总的隶属度
    	float KdgradSums[7] = { 0,0,0,0,0,0,0 };   //输出增量kd总的隶属度
    	int NB = -3, NM = -2, NS = -1, ZO = 0, PS = 1, PM = 2, PB = 3; //论域隶属值
    
    	int  Kp_rule_list[7][7] = { {PB,PB,PM,PM,PS,ZO,ZO},     //kp规则表
    								{PB,PB,PM,PS,PS,ZO,NS},
    								{PM,PM,PM,PS,ZO,NS,NS},
    								{PM,PM,PS,ZO,NS,NM,NM},
    								{PS,PS,ZO,NS,NS,NM,NM},
    								{PS,ZO,NS,NM,NM,NM,NB},
    		                        {ZO,ZO,NM,NM,NM,NB,NB} };
    
    	int  Ki_rule_list[7][7] = { {NB,NB,NM,NM,NS,ZO,ZO},     //ki规则表
    								{NB,NB,NM,NS,NS,ZO,ZO},
    								{NB,NM,NS,NS,ZO,PS,PS},
    								{NM,NM,NS,ZO,PS,PM,PM},
    								{NM,NS,ZO,PS,PS,PM,PB},
    								{ZO,ZO,PS,PS,PM,PB,PB},
    								{ZO,ZO,PS,PM,PM,PB,PB} };
    
    	int  Kd_rule_list[7][7] = { {PS,NS,NB,NB,NB,NM,PS},    //kd规则表
    								{PS,NS,NB,NM,NM,NS,ZO},
    								{ZO,NS,NM,NM,NS,NS,ZO},
    								{ZO,NS,NS,NS,NS,NS,ZO},
    								{ZO,ZO,ZO,ZO,ZO,ZO,ZO},
    								{PB,NS,PS,PS,PS,PS,PB},
    								{PB,PM,PM,PM,PS,PS,PB} };
    
    	int  Fuzzy_rule_list[7][7] = { {PB,PB,PB,PB,PM,ZO,ZO},  
    								   {PB,PB,PB,PM,PM,ZO,ZO},
    								   {PB,PM,PM,PS,ZO,NS,NM},
    								   {PM,PM,PS,ZO,NS,NM,NM},
    								   {PS,PS,ZO,NM,NM,NM,NB},
    								   {ZO,ZO,ZO,NM,NB,NB,NB},
    								   {ZO,NS,NB,NB,NB,NB,NB}};
    
    
    //private:
    
    };
    #endif

    FuzzyPID.cpp文件

    #include "FuzzyPID.h"
    FuzzyPID::FuzzyPID()  //构造函数
    {
    	kp = 0;
    	ki = 0;
    	kd = 0;
    	fuzzy_output = 0;
    	qdetail_kp = 0;
    	qdetail_ki = 0;
    	qdetail_kd = 0;
    	qfuzzy_output = 0;
    	errosum = 0;
    }
    
    FuzzyPID::~FuzzyPID()//析构函数
    {
    }
    
    //输入e与de/dt隶属度计算函数///
    void FuzzyPID::Get_grad_membership(float erro,float erro_c)   
    {
    	if (erro > e_membership_values[0] && erro < e_membership_values[6])
    	{
    		for (int i = 0; i < num_area - 2; i++)
    		{
    			if (erro >= e_membership_values[i] && erro <= e_membership_values[i + 1])
    			{
    				e_gradmembership[0] = -(erro - e_membership_values[i + 1]) / (e_membership_values[i + 1] - e_membership_values[i]);
    				e_gradmembership[1] = 1+(erro - e_membership_values[i + 1]) / (e_membership_values[i + 1] - e_membership_values[i]);
    				e_grad_index[0] = i;
    				e_grad_index[1] = i + 1;
    				break;
    			}
    		}
    	}
    	else
    	{
    		if (erro <= e_membership_values[0])
    		{
    			e_gradmembership[0] = 1;
    			e_gradmembership[1] = 0;
    			e_grad_index[0] = 0;
    			e_grad_index[1] = -1;
    		}
    		else if (erro >= e_membership_values[6])
    		{
    			e_gradmembership[0] = 1;
    			e_gradmembership[1] = 0;
    			e_grad_index[0] = 6;
    			e_grad_index[1] = -1;
    		}
    	}
    
    	if (erro_c > ec_membership_values[0] && erro_c < ec_membership_values[6])
    	{
    		for (int i = 0; i < num_area - 2; i++)
    		{
    			if (erro_c >= ec_membership_values[i] && erro_c <= ec_membership_values[i + 1])
    			{
    				ec_gradmembership[0] = -(erro_c - ec_membership_values[i + 1]) / (ec_membership_values[i + 1] - ec_membership_values[i]);
    				ec_gradmembership[1] = 1 + (erro_c - ec_membership_values[i + 1]) / (ec_membership_values[i + 1] - ec_membership_values[i]);
    				ec_grad_index[0] = i;
    				ec_grad_index[1] = i + 1;
    				break;
    			}
    		}
    	}
    	else
    	{
    		if (erro_c <= ec_membership_values[0])
    		{
    			ec_gradmembership[0] = 1;
    			ec_gradmembership[1] = 0;
    			ec_grad_index[0] = 0;
    			ec_grad_index[1] = -1;
    		}
    		else if (erro_c >= ec_membership_values[6])
    		{
    			ec_gradmembership[0] = 1;
    			ec_gradmembership[1] = 0;
    			ec_grad_index[0] = 6;
    			ec_grad_index[1] = -1;
    		}
    	}
    
    }
    
    /获取输出增量kp,ki,kd的总隶属度/
    void FuzzyPID::GetSumGrad()
    {
    	for (int i = 0; i <= num_area - 1; i++)
    	{
    		KpgradSums[i] = 0;
    		KigradSums[i] = 0;
        KdgradSums[i] = 0;
    
    	}
      for (int i=0;i<2;i++)
      {
    	  if (e_grad_index[i] == -1)
    	  {
    	   continue;
    	  }
    	  for (int j = 0; j < 2; j++)
    	  {
    		  if (ec_grad_index[j] != -1)
    		  {
    			  int indexKp = Kp_rule_list[e_grad_index[i]][ec_grad_index[j]] + 3;
    			  int indexKi = Ki_rule_list[e_grad_index[i]][ec_grad_index[j]] + 3;
    			  int indexKd = Kd_rule_list[e_grad_index[i]][ec_grad_index[j]] + 3;
    			  //gradSums[index] = gradSums[index] + (e_gradmembership[i] * ec_gradmembership[j])* Kp_rule_list[e_grad_index[i]][ec_grad_index[j]];
    			  KpgradSums[indexKp]= KpgradSums[indexKp] + (e_gradmembership[i] * ec_gradmembership[j]);
    			  KigradSums[indexKi] = KigradSums[indexKi] + (e_gradmembership[i] * ec_gradmembership[j]);
    			  KdgradSums[indexKd] = KdgradSums[indexKd] + (e_gradmembership[i] * ec_gradmembership[j]);
    		  }
    		  else
    		  {
    		    continue;
    		  }
    
    	  }
      }
    
    }
    
    计算输出增量kp,kd,ki对应论域值//
    void FuzzyPID::GetOUT()
    {
    	for (int i = 0; i < num_area - 1; i++)
    	{
    		qdetail_kp += kp_menbership_values[i] * KpgradSums[i];
    		qdetail_ki += ki_menbership_values[i] * KigradSums[i];
    		qdetail_kd+= kd_menbership_values[i] * KdgradSums[i];
    	}
    }
    
    //模糊PID控制实现函数/
    float FuzzyPID::FuzzyPIDcontroller(float e_max, float e_min, float ec_max, float ec_min, float kp_max, float kp_min, float erro, float erro_c,float ki_max,float ki_min,float kd_max,float kd_min,float erro_pre,float errp_ppre)
    {
    	errosum += erro;
    	//Arear_dipart(e_max, e_min, ec_max, ec_min, kp_max, kp_min,ki_max,ki_min,kd_max,kd_min);
    	qerro = Quantization(e_max, e_min, erro);
    	qerro_c = Quantization(ec_max, ec_min, erro_c);
    	Get_grad_membership(qerro, qerro_c);
    	GetSumGrad();
    	GetOUT();
    	detail_kp = Inverse_quantization(kp_max, kp_min, qdetail_kp);
    	detail_ki = Inverse_quantization(ki_max, ki_min, qdetail_ki);
    	detail_kd = Inverse_quantization(kd_max, kd_min, qdetail_kd);
    	qdetail_kd = 0;
    	qdetail_ki = 0;
    	qdetail_kp = 0;
    	/*if (qdetail_kp >= kp_max)
    		qdetail_kp = kp_max;
    	else if (qdetail_kp <= kp_min)
    		qdetail_kp = kp_min;
    	if (qdetail_ki >= ki_max)
    		qdetail_ki = ki_max;
    	else if (qdetail_ki <= ki_min)
    		qdetail_ki = ki_min;
    	if (qdetail_kd >= kd_max)
    		qdetail_kd = kd_max;
    	else if (qdetail_kd <= kd_min)
    		qdetail_kd = kd_min;*/
    	kp = kp + detail_kp;
    	ki = ki + detail_ki;
    	kd = kd + detail_kd;
    	if (kp < 0)
    		kp = 0;
    	if (ki < 0)
    		ki = 0;
    	if (kd < 0)
    		kd = 0;
    	detail_kp = 0;
      detail_ki=0;
      detail_kd=0;
      float output = kp*(erro - erro_pre) + ki * erro + kd * (erro - 2 * erro_pre + errp_ppre);
    	return output;
    }
    
    ///区间映射函数///
    float FuzzyPID::Quantization(float maximum,float minimum,float x)
    {
    	float qvalues= 6.0 *(x-minimum)/(maximum - minimum)-3;
    	//float qvalues=6.0*()
    	return qvalues;
    	
    	//qvalues[1] = 3.0 * ecerro / (maximum - minimum);
    }
    
    //反区间映射函数
    float FuzzyPID::Inverse_quantization(float maximum, float minimum, float qvalues)
    {
    	float x = (maximum - minimum) *(qvalues + 3)/6 + minimum;
    	return x;
    }

    测试模糊PID控制器:

    #include <iostream>
    #include "FuzzyPID.h"
    
    int main()
    {
        FuzzyPID myfuzzypid;
        float Target = 600;
        float actual = 0;
        float e_max =1000;
        float e_min = -1000;
        float ec_max = 800;
        float ec_min = -800;
        float kp_max =100;
        float kp_min = -100;
        float ki_max = 0.1;
        float ki_min = -0.1;
        float kd_max = 0.01;
        float kd_min = -0.01;
        float erro;
        float erro_c;
        float erro_pre = 0;
        float erro_ppre = 0;
        erro =Target - actual;
        erro_c = erro - erro_pre;
        for (int i = 0; i < 100; i++)
        {
            float u;
            u = myfuzzypid.FuzzyPIDcontroller(e_max, e_min, ec_max, ec_min, kp_max, kp_min, erro, erro_c,ki_max,ki_min,kd_max,kd_min,erro_pre,erro_ppre);
            actual +=u;
            erro_ppre = erro_pre;
            erro_pre = erro;
            erro = Target - actual;
            erro_c= erro - erro_pre;
            std::cout << "i:" << i << "\t" << "Target:" << Target << "\t" << "Actual:" << actual  << std::endl;
        }
     }
    
    

    运行结果:

                                                 

    三. Arduino 智能小车直线模糊PID算法

         主要硬件:Arduino Nano,MPU6050,TT马达,L298N电机驱动模块。

        模糊PID控制的目标,输入与输出:

         输入:MPU6050测量小车的转动的角度,角速度。

         输出:控制TT马达的PWM

        目标:小车转动角度为0

         进行无模糊PID控制与有模糊PID控制直线行走的效果

         无模糊PID控制,角度时间图:

                                           

       有上图看到,当相同PWM作用与两个TT马达时,由于两个马达的转速不一样,也由于车子装配精度不够,导致车子前进时一直往一边偏,即角度不断增大。

        有模糊PID控制效果图:

                                       

         由与无模糊PID控制器比较,由比较明显的效果,小车基本是在[-10,10]度之间飘动。

     

    四,结语

         模糊PID比传统的PID算法的省去了参数调节的麻烦,对于对PID参数调节没经验的人模糊PID算法还是比较容易,但是模糊PID算法控制精度可能比较低。

    展开全文
  • 智能车舵机控制PID

    热门讨论 2012-11-20 01:33:10
    增量式pid控制的可以看看运用在智能车的舵机 分享给大家,欢迎交流啊
  • 介绍了基于MC9S12XS128单片机控制智能车系统,该系统以CCD摄像头传感器作为路径识别装置,通过图像识别提取道路黑线信息,计算出反应道路形状的舵机控制量,对舵机进行控制。对智能车寻线舵机控制系统的软件设计...
  • 算法(一):智能小车速度控制PID模糊控制

    千次阅读 多人点赞 2020-03-22 10:42:36
    概览一、前言二、基于PID 的速度控制1.PID控制器2.PID速度控制二、基于模糊控制的速度控制1....在实现智能小车速度的闭环控制时首选简单有效的PID控制算法。 二、基于PID 的速度控制 1.PID控制器 PID(Proportion I...
  • 包含很多模糊控制的文档,介绍了模糊控制基本原理与实现步骤以及在智能小车中的应用,可用模糊控制调节PID参数
  • 这个是PID模糊控制器的设计及在智能车转向控制上的应用,可以指导你如何设计PID模糊控制器算法,应用于智能车转向控制上。
  • PID 飞思卡尔智能车PID控制教程,讲的很详细,也很容易懂 PID 飞思卡尔智能车PID控制教程,讲的很详细,也很容易懂
  • 飞思卡尔智能车——舵机及PID控制

    万次阅读 多人点赞 2016-12-04 11:49:42
    舵机:小车转向的控制机构。也就是控制小车的转向。它的特点是结构紧凑、易安装调试、控制简单、大扭力、成本较低等。舵机的主要性能取决于最大力矩和工作速度(一般是以秒/60°为单位)。它是一种...
  • pid智能车控制算法研究的分享.......................................................................................................................................
  • 智能小车自动寻迹过程中,方向控制与速度控制都存在高度非线性的问题。采用模糊 PID 控制算法,实现...该方案运用于智能车控制系统,克服了传统 PID 控制的不足,通过模糊规则进行推理决策,实现了 PID 参数的实时优化
  • 基于视觉的智能车模糊PID控制算法 ,基于freescale公司的16位HCS12单片机设计一种智能车系统。系统摄像头采集路径信息,通过单片机 的模糊推理机在线整定PID参数,使小车能按照任意给定的黑色引导线平稳地寻迹。
  • 为提高智能车舵机的响应速度,分析了智能车控制系统的特点以及应用常规模糊控制器进行控制的局限性,提出了模糊PI D控制算法.推导出模糊PI D控制器消除稳态误差的原理,并介绍了模糊PI D控制器的设计方法.实验结果表明,...
  • 基于免疫自适应PID的智能车模糊控制,郝帅,潘学军,为了提高智能汽车高速行驶下对目标轨迹的跟踪品质,借鉴生物免疫反馈的调节机理,通过与传统的PID控制器类比,设计了免疫自适应PID
  • 今天我代表历届参加大赛的网友,给大家分享一些有关PID的学习代码、pid算法和研究、PID智能车黑线识别算法及控制策略研究、PID电机调速等等。需要参加智能车大赛的朋友,赶紧充电学习下 PID算法吧。 智能车大赛PID...
  • pid控制器设计代码matlab SmartCarSpeedControl-PI 智能车速度PI控制器 飞思卡尔智能车比赛Matlab仿真速度控制PI的模型 Matlab R2011a 在Matlab下,打开SpeedControl.mdl,运行即可,点击Scope查看仿真结果 C程序部分...
  • 智能车采用PID控制算法,使用CCD线型摄像头作为黑色引导线的检测设备,经LM393比较后供单片机进行数据采集,图像识别,从而可以进行路径识别。电机驱动采用的是PC33886,使用直射型光电传感器来测量速度,并将相关...
  • 基于DG128的PID控制程序,已在code warrior中编译过了!
  • PID 飞思卡尔智能车PID控制教程,讲的很详细,也很容易懂
  • 小车pid控制

    2018-08-18 19:40:04
    使用MDK编写的STM32F103ZET6的智能车下位控制程序,使用串口控制

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 381
精华内容 152
关键字:

智能车pid控制