串级PID 位置环+速度环

这篇具有很好参考价值的文章主要介绍了串级PID 位置环+速度环。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1位置环和速度环的串级pid,首先要记住,位置环的输出是速度环的输入,最后控制输出为速度环的输出。

速度环的PID控制器 代码如下

float Velocity_KP_A=400,Velocity_KI_A=300; 
int Incremental_PI_A (float Encoder,float Target)
{     
     static float Bias,Pwm,Last_bias;
     Bias=Target-Encoder; //Calculate the deviation //计算偏差
     Pwm+=Velocity_KP_A*(Bias-Last_bias)+Velocity_KI_A*Bias; 
     if(Pwm>7200)Pwm=7200;
     if(Pwm<-7200)Pwm=-7200;
     Last_bias=Bias; //Save the last deviation //保存上一次偏差 
     return Pwm;    
}

速度环只用Kp和Ki控制即可

位置环PID控制器

int Location_pid(float Encoder,float Target)
{
    static float Bias,Speed,Last_bias,Integral_bias;
    Bias=Target-Encoder; //Calculate the deviation //计算偏差
    Integral_bias+=Bias;//求出偏差的积分
    
    Speed+=Location_KP*Bias+Location_KI*Integral_bias+Location_KD*(Bias-Last_bias); 
    
    Last_bias=Bias;//保存上次偏差
    return Speed;
}

位置环用Kp和Kd即可(只用Kp好像也行的)

2如何将位置环和速度环串在一起

对于位置环

目标为行走的距离,需要转向的度数 (可以把距离与度数转化为脉冲数,方便进行PID控制)

反馈为编码器捕获脉冲数的累计数

每次要用位置环时必须先将脉冲累计数清零

距离转化为脉冲的方法

Target_Encoder_sum_A=distence/(PI*WD)*(EncoderMultiples*MD*Hall_13);

//The encoder octave depends on the encoder initialization Settings
//编码器倍频数,取决于编码器初始化设置
#define   EncoderMultiples 4
//Motor_gear_ratio
//电机减速比
#define   MD   20
//Number_of_encoder_lines
//编码器精度
#define      Hall_13           13
//4WD wheel tire diameter series
//四驱车轮胎直径
#define        WD  0.045f
//Encoder data reading frequency
//编码器数据读取频率  
#define CONTROL_FREQUENCY 100
//half wheelspacing //半轮距
#define Half_wheelspacing   0.0644f

//half axlespacing //半轴距
#define Half_axlespacing   0.010f

#define PI 3.1415f  //PI //圆周率

//这里加将位置环的输入直接编程距离(m)的函数所有普通直行都用这个
void Set_Distence_m(uint16_t distence)
{
    PID_flag=1;
    Turn_Finish_flag=7;
        Encoder_A_sum=0;
        Encoder_B_sum=0;
        Encoder_C_sum=0;
        Encoder_D_sum=0;
    Target_Encoder_sum_A=distence/(PI*WD)*(EncoderMultiples*MD*Hall_13);
    Target_Encoder_sum_B=Target_Encoder_sum_A;
    Target_Encoder_sum_C=Target_Encoder_sum_A;
    Target_Encoder_sum_D=Target_Encoder_sum_A;
}

旋转度数转化为脉冲的方法

//转角有左转90,右转90,和转180三种情况。
//左转为90, 右转为-90,转180
void  Set_Turn(int i)
{
    PID_flag=1;
    float Car_Turn_val;
    float spin90_val;
  if(i==180)//原地左转180
    {
        spin90_val=0.25*PI*Half_wheelspacing*2;
        Turn_Finish_flag=1;
        Car_Turn_val=spin90_val/(PI*WD)*(EncoderMultiples*MD*Hall_13)*2;//计算出需要的累计脉冲
        Target_Encoder_sum_A=-Car_Turn_val;
        Target_Encoder_sum_B=-Car_Turn_val;
        Target_Encoder_sum_C=Car_Turn_val;
        Target_Encoder_sum_D=Car_Turn_val;
    }
    else if(i==90)//左转  左轮为负,右轮为正,
    {
        spin90_val=0.25*PI*Half_wheelspacing*2;
        Turn_Finish_flag=2;
        Car_Turn_val=spin90_val/(PI*WD)*(EncoderMultiples*MD*Hall_13);//计算出需要的累计脉冲
        Target_Encoder_sum_A=-Car_Turn_val;
        Target_Encoder_sum_B=-Car_Turn_val;
        Target_Encoder_sum_C=Car_Turn_val;
        Target_Encoder_sum_D=Car_Turn_val;
    }
        Encoder_A_sum=0;
        Encoder_B_sum=0;
        Encoder_C_sum=0;
        Encoder_D_sum=0;    
}

3运用pid将所需的脉冲计算出来,然后把单位同意换算为速度 m/s 方便传入速度环,这里会以最大限幅去执行

/**************************************************************************
位置环输出速度
**************************************************************************/
void Drive_Motor()
{
        static float amplitude=1,Turn_amplitude=0.5; //Wheel target speed limit //车轮目标速度限幅
        float A_Target,B_Target,C_Target,D_Target;
        //这里是脉冲算的 要传入速度环还需将位置环计算出来的脉冲转换为速度
        A_Target=Location_pid(-Encoder_A_sum,Target_Encoder_sum_A);
        B_Target=Location_pid(-Encoder_B_sum,Target_Encoder_sum_B);
        C_Target=Location_pid(-Encoder_C_sum,Target_Encoder_sum_C);
        D_Target=Location_pid(-Encoder_D_sum,Target_Encoder_sum_D);
        
        MOTOR_A.Target=A_Target*CONTROL_FREQUENCY*(WD*PI)/(EncoderMultiples*MD*Hall_13);
        MOTOR_B.Target=B_Target*CONTROL_FREQUENCY*(WD*PI)/(EncoderMultiples*MD*Hall_13);
        MOTOR_C.Target=C_Target*CONTROL_FREQUENCY*(WD*PI)/(EncoderMultiples*MD*Hall_13);
        MOTOR_D.Target=D_Target*CONTROL_FREQUENCY*(WD*PI)/(EncoderMultiples*MD*Hall_13);
        if(Turn_Finish_flag==2)//左90
        {
            MOTOR_A.Target=-float_abs(MOTOR_A.Target);
            MOTOR_B.Target=-float_abs(MOTOR_B.Target);
            MOTOR_C.Target=float_abs(MOTOR_C.Target);
            MOTOR_D.Target=float_abs(MOTOR_D.Target);
        }
        else if(Turn_Finish_flag==3)//右90
        {
            MOTOR_A.Target=float_abs(MOTOR_A.Target);
            MOTOR_B.Target=float_abs(MOTOR_B.Target);
            MOTOR_C.Target=-float_abs(MOTOR_C.Target);
            MOTOR_D.Target=-float_abs(MOTOR_D.Target);
        }
        if(Turn_Finish_flag==7)
        {
              //直线速度限幅
        MOTOR_A.Target=target_limit_float(MOTOR_A.Target,-amplitude,amplitude); 
      MOTOR_B.Target=target_limit_float(MOTOR_B.Target,-amplitude,amplitude);
        MOTOR_C.Target=target_limit_float(MOTOR_C.Target,-amplitude,amplitude);
      MOTOR_D.Target=target_limit_float(MOTOR_D.Target,-amplitude,amplitude);
        }
        else if(Turn_Finish_flag==1||Turn_Finish_flag==2||Turn_Finish_flag==3||Turn_Finish_flag==4||Turn_Finish_flag==5||Turn_Finish_flag==6)
        {
                //转向速度限幅
        MOTOR_A.Target=target_limit_float(MOTOR_A.Target,-Turn_amplitude,Turn_amplitude); 
      MOTOR_B.Target=target_limit_float(MOTOR_B.Target,-Turn_amplitude,Turn_amplitude);
        MOTOR_C.Target=target_limit_float(MOTOR_C.Target,-Turn_amplitude,Turn_amplitude);
      MOTOR_D.Target=target_limit_float(MOTOR_D.Target,-Turn_amplitude,Turn_amplitude);
        }


}

4将计算出来呢的素的MOTOR_A.Target传入速度环当作目标速度,最后判断位置环是否执行完成,及判断捕获的脉冲累计数与我们计算的是否相同,相同及完成位置环的控制,如果不用位置环了,就需要清除位置环

void Finish_Turn()
{
        static float A,B,C,D,E,F,G,H;
        A=float_abs(Encoder_A_sum);
        B=float_abs(Encoder_B_sum);
        C=float_abs(Encoder_C_sum);
        D=float_abs(Encoder_D_sum);
        E=float_abs(Target_Encoder_sum_A);
        F=float_abs(Target_Encoder_sum_B);
        G=float_abs(Target_Encoder_sum_C);
        H=float_abs(Target_Encoder_sum_D);
        if(Turn_Finish_flag==2||Turn_Finish_flag==3||Turn_Finish_flag==4||Turn_Finish_flag==5||Turn_Finish_flag==6)
        {
            if(A>(E*0.99)&&B>(F*0.99)&&C>(G*0.99)&&D>(H*0.99))//90度转弯需要的大概脉冲 *0.99作为补偿 理想为1
            {
                Turn_Finish_flag=0;
            }
        }
        else if(Turn_Finish_flag==1)
        {
            if(A>(E*1.7)&&B>(F*1.7)&&C>(G*1.7)&&D>(H*1.7))//180度转弯需要的大概脉冲 *1.7作为补偿 理想为2
            {
                Turn_Finish_flag=0;              
            }
        }

}

5位置环的输出作为速度环的输入文章来源地址https://www.toymoban.com/news/detail-449233.html

void Balance_task()
{ 
            //Get the encoder data, that is, the real time wheel speed, 
            //and convert to transposition international units
            //获取编码器数据,即车轮实时速度,并转换位国际单位
            Get_Velocity_Form_Encoder();    
            if(PID_flag==1)//速度环+位置环控制计算各电机PWM值,PWM代表车轮实际转速
            {        
                 Drive_Motor();//位置环输出速度
                 Finish_Turn();
                if(Turn_Finish_flag==1||Turn_Finish_flag==2||Turn_Finish_flag==3||Turn_Finish_flag==4||Turn_Finish_flag==5||Turn_Finish_flag==6||Turn_Finish_flag==7)
                {
                     Location_PID_Finish_flag=1;
                     MOTOR_A.Motor_Pwm=Incremental_PI_A(MOTOR_A.Encoder, MOTOR_A.Target);
                     MOTOR_B.Motor_Pwm=Incremental_PI_B(MOTOR_B.Encoder, MOTOR_B.Target);
                     MOTOR_C.Motor_Pwm=Incremental_PI_C(MOTOR_C.Encoder, MOTOR_C.Target);
                     MOTOR_D.Motor_Pwm=Incremental_PI_D(MOTOR_D.Encoder, MOTOR_D.Target);    
                    Set_Pwm( MOTOR_A.Motor_Pwm, MOTOR_B.Motor_Pwm, MOTOR_C.Motor_Pwm, MOTOR_D.Motor_Pwm);  //MD36电机系列
                }
                else if(Turn_Finish_flag==0)
                {
                      PID_flag=2;
                        Location_PID_Finish_flag=0;
                        Encoder_A_sum=0;
                        Encoder_B_sum=0;
                        Encoder_C_sum=0;
                        Encoder_D_sum=0;    
                        Set_Pwm(0,0,0,0);  //MD36电机系列
        
                }                            
            }
            else if(PID_flag==0)//速度闭环控制计算各电机PWM值,PWM代表车轮实际转速
            {
                //单独速度环限幅
                Speed_A=target_limit_float(Speed_A,-3.5,3.5); 
                Speed_B=target_limit_float(Speed_B,-3.5,3.5);
                Speed_C=target_limit_float(Speed_C,-3.5,3.5);
                Speed_D=target_limit_float(Speed_D,-3.5,3.5);
//                MPU6050_pwm=MPU6050_pid(yaw/70,0.2);
//                printf("Speed=%lf,yaw=%lf,MPU6050_pwm=%d\r\n",MOTOR_A.Encoder,yaw,MPU6050_pwm);
//                MOTOR_A.Motor_Pwm=Incremental_PI_A(MOTOR_A.Encoder, Speed_A)-Xunji_Pwm;
//              MOTOR_B.Motor_Pwm=Incremental_PI_B(MOTOR_B.Encoder, Speed_B)-Xunji_Pwm;
//                MOTOR_C.Motor_Pwm=Incremental_PI_C(MOTOR_C.Encoder, Speed_C)+Xunji_Pwm;
//              MOTOR_D.Motor_Pwm=Incremental_PI_D(MOTOR_D.Encoder, Speed_D)+Xunji_Pwm;
                MOTOR_A.Motor_Pwm=Incremental_PI_A(MOTOR_A.Encoder, Speed_A)-Xunji_Pwm;
              MOTOR_B.Motor_Pwm=Incremental_PI_B(MOTOR_B.Encoder, Speed_B)-Xunji_Pwm;
                MOTOR_C.Motor_Pwm=Incremental_PI_C(MOTOR_C.Encoder, Speed_C)+Xunji_Pwm;
              MOTOR_D.Motor_Pwm=Incremental_PI_D(MOTOR_D.Encoder, Speed_D)+Xunji_Pwm;
                Set_Pwm( MOTOR_A.Motor_Pwm, MOTOR_B.Motor_Pwm, MOTOR_C.Motor_Pwm, MOTOR_D.Motor_Pwm);  //MD36电机系列
                Encoder_A_sum=0;
                Encoder_B_sum=0;
                Encoder_C_sum=0;
                Encoder_D_sum=0;    
            }
}

到了这里,关于串级PID 位置环+速度环的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • PID超详细教程——PID原理+串级PID+C代码+在线仿真调参

    目录 前言 仿真调参环境 案例引入——小球位置控制 抛开案例——更专业地理解PID 由虚到实——代码编写 最后一步——PID参数调整 总结——使用PID的步骤 更进一步——串级PID 很多人应该都听说过PID,它的运算过程简单,并能在大多情况下实现较好的控制效果,因此它是工

    2024年02月02日
    浏览(65)
  • 单级和串级pid原理分析以及pid应用与小车的技巧

    这篇文章主要是帮助理解和使用pid,不会讲复杂的代码公式。 重点在最后,一定要看到最后    pid可以看作是一种控制器,用来控制某个变量达到你想要的地步。 单级pid 这里我举个例子来理解一下: 假设有一个水缸,最终的控制目的是要保证水缸里的水位永远的维持在1米

    2024年02月14日
    浏览(52)
  • 【平衡小车】【串级PID参数整定】【详细版】根据现象手动调整平衡小车的PID

    简介:二轮平衡小车的控制分为平衡环(又称为直立环,保持稳定角度)、速度环(用来保持稳定时速度为零)以及转向环(用来无转向命令时调整走直线),下面详细介绍各环PID参数的整定 硬件准备:平衡小车之家的小车底盘,STM32F1,电机驱动模块,MPU6050等 软件准备:简

    2024年02月03日
    浏览(66)
  • 智能车PID控制详细介绍(普通PID、串级PID、改进PID)——适用于四轮车、三轮车、平衡车

    声明:该文是本人原创,后续将参与智能车相关书籍的写作,为了防止侵权只能先发图片版还请谅解,如有问题,敬请指出,欢迎讨论~~~~ 1 舵机组成及其工作原理 2 舵机PID控制策略 1 直流电机调速系统组成及其工作原理 2 电机PID控制策略 一、四轮电机控制 二、两轮平衡车与

    2023年04月23日
    浏览(44)
  • STM32应用(十)经典控制算法PID(单级和串级)原理与代码实现

    PID是什么,P,I,D的分别功能 你和PID调参大神之间,就差这篇文章! P(比例): 简单来说,P就是凉了加热水,热了加凉水。 比目标值小 ,我就 增加 一点, 比目标值大 ,我就 减小 一点。 (现在) P可能出现的问题: 1.P太小,达到目标值需要花费很长的时间,而且会有

    2024年02月03日
    浏览(45)
  • 提升稳定性与动态响应,深入探究PID串级多闭环控制的应用价值

    引言: PID(比例-积分-微分)控制作为自动控制系统中常用的控制算法,可以通过对系统的反馈进行调整,实现目标状态的稳定控制。而PID串级多闭环控制是在基本PID控制的基础上,引入多个PID控制器,形成层次化的控制结构,以进一步提高系统的稳定性和性能。本文将详细

    2024年02月14日
    浏览(49)
  • 位置式PID与增量式PID

    位置式与增量式PID 位置式PID与增量式PID的介绍和代码实现 增量式pid和位置式pid 增量式pid和位置式pid相比各有什么优缺点? * PID*调参的实用方法和经验有哪些? 在设计PID控制器时,什么时候用增量式PID,什么时候用位置式PID 位置式PID 因为有误差积分 ∑e(i),一直累加,也就

    2024年02月01日
    浏览(49)
  • 【程序】【必须】PID速度环控制,代码+调参

    主控:STM32F103C8T6 在进行速度控制之前,我们首先需要进行速度采样,这里参见 ​ 这里不细说电机驱动模块的选型和使用,而是说一个常见的误区。我们驱动电机要使用两路PWM,一般是一路给PWM信号,一路是纯低电平。但这其实是不好的,正确的做法是一路给PWM,另一路给纯

    2023年04月21日
    浏览(39)
  • PID算法(位置式pid算法和增量式pid算法)

    PID 算法是闭环控制系统中常用的算法,PID 分别是 Proportion(比例)、Integral(积分)、 Differential(微分)的首字母缩写。它是一种结合比例、积分和微分三个环节于一体的闭环控 制算法,具体的控制流程如图 8.2.1 所示: u = Kp * e u ----- 输出 Kp ----- 比例系数 e ----- 偏差 以温度

    2024年02月16日
    浏览(58)
  • 位置式PID

            位置闭环控制就是根据编码器的脉冲累加测量电机的位置信息,并于目标值进行比较分析,的到控制偏差,然后通过对偏差的比例、积分、微分进行控制,使偏差趋向0的过程。         上图中的目标位置一般我们可以通过按键或者开关等方式编程实现改变目标值,

    2024年02月17日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包