【Arduino小车实践】PID算法应用之倒立摆

目录

一、PID

1. PID()

2. Compute()

3. SetMode() 

4. SetOutputLimits()

5. SetTunings()

6. SetSampleTime()

7. SetControllerDirection()

8. 显示函数

二、倒立摆例子概述

1. 倒立摆

2. 材料列表

3. 代码


前言

        发现好多小伙伴们知道PID可以用来控制小车直行、精准控制电压输出等,但是不知如何进行运用,本文先介绍了PID库的相关内容,并给出倒立摆的例子进行说明。

一、PID

1. PID()

PID的初始化函数,并设置输入、输出、目标值等参数。具体如下:

PID(&Input, &Output, &Setpoint, Kp, Ki, Kd, Direction)
PID(&Input, &Output, &Setpoint, Kp, Ki, Kd, POn, Direction)

其中,

Input:(double) 输入参数,待控制的量
Output:(double) 输出参数,指经过PID控制系统的输出量
Setpoint:(double) 目标值,希望达到的数值
Kp, Ki, Kd:(double) PID控制的比例、积分、微分系数
Direction:DIRECT 或 REVERSE,指的是当输入与目标值出现偏差时,向哪个方向控制。笔者发现,当设置为REVERSE时,会在初始化时将Kp, Ki, Kd变化为原来的负值。
POn:P_ON_E (默认) 或 P_ON_M,传统PID控制一定会出现超调值,但是P_ON_M可以稍微缓解这一现象,但是会牺牲一些上升时间,对比图如下:
默认(P_ON_E): P_ON_M:

2. Compute()

含PID的控制算法,应该在loop()函数之中反复调用。但是具体的输出和采样时间有关,否则很可能会出现什么也不做,输出为0的情况。此函数无参数,但是有一个返回值。

返回值说明:
True: 输出是经过计算的输出
False: 什么也没做,不输出或输出为0

3. SetMode() 

指定PID算法的运行计算过程是自动(AUTOMATIC)还是手动(MANUAL)。手动就是关闭PID算法的计算功能。调为AUTOMATIC模式时才会初始化PID算法,进行输出。

SetMode(AUTOMATIC);//自动模式

4. SetOutputLimits()

会使得Output输出范围限制在一定的范围之内。若不进行设置,则默认以Arduino的PWM输出模式(0-255)进行输出。最小值和最大值都是double类型。

//SetOutputLimits(min, max);
SetOutputLimits(200, 300);  // 输出在200-300之间

5. SetTunings()

PID()函数中已经对其进行初始化,但是在某些情况下,可能会需要随时调整比例积分微分系数或工作模式(P_ON_E/P_ON_M),此时则可调用此函数进行设置,语法如下:

SetTunings(Kp, Ki, Kd);
SetTunings(Kp, Ki, Kd, POn);

6. SetSampleTime()

用以控制PID算法的采样时间,默认采样时间为200ms。输入的参数类型为int类型的毫秒数。在大多数场合下,这一时间足够快了。在Arduino中文社区的翻译帖中,贴出了常见被控参数的采样周期,这里笔者将其贴在这里以供参考:

被控参数被控参数 备注
流量  1-5s   优先选1-2s
压力  3-10s    优先选6-8s
液位    6-8s    
温度    15-20s  
直流电机   100ms  

7. SetControllerDirection()

如果输入值高于设定值,输出是否增加或减少? 结合现实的情况,PID的控制可能有不同的选择。 用一辆车,输出应该减小,以减速。 对于冰箱来说,情况恰恰相反。 需要增加输出(冷却)以降低温度。 此函数指定PID连接到哪种类型的进程。 此信息也在PID构建时指定。 由于该过程不太可能从直接转换到反向,所以任何人都不会真正使用此功能。

SetControllerDirection(DIRECT);
SetControllerDirection(REVERSE);

8. 显示函数

GetKp();
GetKi();
GetKd();
GetMode();
GetDirection();

double PID::GetKp(){ return  dispKp; }
double PID::GetKi(){ return  dispKi;}
double PID::GetKd(){ return  dispKd;}
int PID::GetMode(){ return  inAuto ? AUTOMATIC : MANUAL;}
int PID::GetDirection(){ return controllerDirection;}

二、倒立摆例子概述

1. 倒立摆

        由于倒立摆自动控制的数学模型是非线性、多阶、多输入的,是用于测试自动控制算法的理想模型。本代码只用到了简单的pid算法,而且直接调用了arduino的pid库。用Arduino nano的2个外部中断采集编码器的数据,通过中断数量计算摆杆角度。摆杆角度与垂直的差值作为pid算法的输入,经过主控计算后通过引脚pwm控制l289驱动直流减速电机转动。

2. 材料列表

主控arduino nano x1,nano扩展板 x1,pcb x1,pcb电机驱动l298 x1,欧姆龙高精度旋转编码器(2000线)x1, 编码器滤波放大电路板x1,直流减速电机 x1,12v直流电源 x1,碳纤维棒,木板,电源线

3. 代码

#include <PID_v1.h>//导入库函数,实现PID控制器的功能
#define pinA 2 //中断0
#define pinB 3 //中断1
#define INA  8 //电机正反
#define PWMA  9 //电机速度

int PDAJ = 12; //选择模式
long int angle; //角度
unsigned long time = 0; //时间
long count = 0; //计数值
long num = 0;

double Setpoint, Input, Output, setPoint;
double Kp = 0.040, Ki = 0.0005, Kd =0.0011;//Kp = 0.040, Ki = 0.0005, Kd =0.0011;
PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, REVERSE);//PID库的函数声明

void setup(){
    Serial.begin(9600); //窗口初始化  
    pinMode(pinA, INPUT); //D2脚为输入
    pinMode(pinB, INPUT); //D3脚为输入
    pinMode(PDAJ, INPUT_PULLUP); 将引脚设置为输入模式,并启用上拉电阻。
    attachInterrupt(0, blinkA, FALLING);//注册中断0调用函数blinkA
    attachInterrupt(1, blinkB, FALLING);//注册中断1调用函数blinkB
    time = micros(); //时间初值
    myPID.SetTunings(Kp, Ki, Kd);//调用PID库,设置了PID控制器的参数、输出限制和采样时间
    myPID.SetOutputLimits(-255,255);
    myPID.SetSampleTime(5);
    myPID.SetMode(AUTOMATIC);//调用PID库,将控制器设置为自动模式
}
//主体程序
void loop(){
    int bun=digitalRead(PDAJ);//首先读取PDAJ引脚的状态,判断控制模式
    if (bun==HIGH){//如果处于控制模式
        num = count;
        long int angle = num*18;//则根据旋转编码器的计数值计算得到角度,并进行PID控制
        Serial.print(anlge);
        Serial.print(" ");
        while(anlge>36000){//根据角度的范围(0-36000),将角度换算成180度制
           anlge=anlge-36000;
         }
         while(anlge<0){
            anlge=anlge+36000;
            Serial.println(anlge);
         }
         Input = angle;//并将其作为PID控制器的输入(Input)
         myPID.Compute(); //调用myPID.Compute()函数计算PID控制器的输出(Output)
         int spd;
         Serial.print("output= ");
         SetPoint = 18000;
         Serial.print("jd=  ");
         Serial.print(JD_angle);
         Serial.print("pt=  ");
         Serial.print(PT_angle);
         Serial.print("anlge  ");
         Serial.print(anlge);       
         if (angle>15000&&angle<21000) {//然后根据输出的值调整电机的速度。具体的速度调整规则根据角度是否在一定范围内来确定
              spd = Output;     
         }
         Serial.print(" spd=");
         Serial.println(spd);
         motor(spd);//最后,通过motor()函数控制电机的转动
         }else{//如果处于非控制模式,则按照一定的顺序以不同的速度逐渐调整电机的转动,然后停止一段时间。这部分代码可能是用于调试或其他辅助功能
         motor(20); delay(40);
         motor(30); delay(40);
         motor(50); delay(40); 
         motor(100); delay(40); 
         motor(150); delay(40);
         motor(0); delay(200);
         motor(-20); delay(40);
         motor(-30); delay(40);
         motor(-50); delay(40);
         motor(-100); delay(40);
         motor(-150); delay(40);
         motor(0); delay(200);
  }                     
}
//中断0调用函数,用于读取旋转编码器的脉冲计数。这里使用了软件去抖动处理,避免干扰导致计数错误
void blinkA(){
    if ((micros() - time) > 15)    count ++;
    time = micros();
}

//中断1调用函数,用于读取旋转编码器的脉冲计数。这里使用了软件去抖动处理,避免干扰导致计数错误
void blinkB(){
    if ((micros() - time) > 15)    count --;
    time = micros();
}
void motor(int sp1){//用于控制电机的转动方向和速度。根据输入速度的正负值,设置电机的正反转,并通过PWM方式控制电机的速度大小
    if(sp1>0)    digitalWrite(INA, HIGH);
    else    digitalWrite(INA, LOW);
    analogWrite(PWMA, abs(sp1));
}

  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PID倒立摆小车GUI是一种可视化控制系统,通过图形用户界面来控制倒立摆小车。PID控制器是一种用于控制对象的反馈控制器,它能够根据系统的实时状态进行调整,并能够快速地对系统偏差进行修正。基于PID倒立摆小车GUI,用户可以通过调整PID参数,监控倒立摆小车的运动状态,观察系统响应和控制效果。 该系统的实现需要倒立摆小车硬件设备和相应的控制程序。倒立摆小车通常由两个电机驱动,通过旋转车轮来控制小车的移动。用户可以通过GUI界面上的图形输入控制指令来控制小车的方向和速度。控制程序会根据指令控制电机驱动小车的运动,同时系统会利用PID算法实时调整控制参数,实现倒立摆小车的稳定控制。 在GUI界面上,用户可以通过实时监控小车的状态来评估控制效果。用户可以观察小车的位置、速度、角度以及控制参数等信息,并根据监控结果对PID参数进行调整,以进一步提高控制效果和系统的稳定性。同时,该系统还可以支持记录数据、保存图形界面输出等功能,方便用户对系统实验数据和控制进程进行分析和处理。 基于PID倒立摆小车GUI的设计,不仅可以提高控制过程的可视化和交互性,还可以提高用户对系统控制的理解和实验经验的积累。这种控制方式还可以应用于自动导航车、无人机等领域,具有广泛的应用前景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值