有关两种PID调参的经验分享——位置式与增量式

PID是一种用于精确控制的控制算法,通过对比例P,积分I,微分D参数调整以达到最佳的控制效果。
需要注意的是,并不是每一次都三个参数一起出场,有时只需要其中一个或两个就可以达到很好的控制效果。
PID分为位置式与增量式,各有优点,稍后将分别介绍,此处先分别展示,两种PID的公式:

  • 位置式
    位置式PID
    outk 表示 k 时刻的输出值;
    ek 表示 k 时刻偏差量;
    ej 表示 j 时刻的偏差量,这一部分表示自系统开始运行后的误差的累积;
    ek-1显然表示 k 时刻上一时刻的误差。

  • 增量式
    增量式PID
    此处的ek-2表示上上时刻的误差量

位置式PID

参数说明

首先来说 P,他带给系统一个基础的运行能力,使得系统可以往预期的方向发展;这个参数需要适中,如果过大,则会超出目标,并且来回震荡。
积分 I 则起到了补足 P 的作用,他对小幅度的偏差具有明显的调节作用;如果 I 过小则系统存在小幅度偏差时不能回中,过大则会超出目标,且系统表现迟钝。
微分 D 主要起到了限制作用,阻止系统超出预期;过小时会超出目标,过大时则会高频抖动,并且对误差敏感。

调试方法

先调整比例 P,给予系统基础的运行能力,当调整到开始震荡时,减小一点,然后调整积分 I。

积分 I 应当限制他的幅度,这个幅度选定需要根据系统的回复能力决定,可以先自行带入一个设置的阈值,计算后与代表系统回复能力的数值比较,然后得出一个适中的 I,在此基础上进行调整,有时这个值调整完成后就可以发现系统已经可以达到预期,此时可以在根据需要调整微分 D。

微分 D 一般调整到震荡后在减小一些唯宜。

当然,对于 I 与 D 的调整顺序并不是固定的,也可以使 P 过冲,然后调整 D 来限制,之后微调 I 来补足。

当 I 充足后可适当减小P,D 充足后可适当增加 P,此处的增加与减小都不是大踏步行进,而是细微调整。

代码与案例展示

s16 palstance_i_max = 100;      // 角速度环积分限幅
float fly_dt = 0.003;           // 时间

void roll_palstance_c(float target_p_roll, float gyroX)
{
    static float last_offset_rp = 0;                // 上一次的偏差量
    static s16 palstance_i_rp = 0;                  // 积分
    float palstance_offset = gyroX + target_p_roll; // 偏差量

    palstance_i_rp += palstance_offset * fly_dt;

    if (palstance_i_rp > palstance_i_max)
    {
        palstance_i_rp = palstance_i_max;
    }
    else if (palstance_i_rp < -palstance_i_max)
    {
        palstance_i_rp = -palstance_i_max;
    }

    roll_pid_out = (palstance_offset * p_p + palstance_i_rp * p_i + (palstance_offset - last_offset_rp) * p_d / fly_dt);
    // roll_pid_out = limit(roll_pid_out, 200, -200);

    last_offset_rp = palstance_offset;
}

这是一个四轴无人机上角速度环调整的例子,

  • palstance_offset 即为误差,palstance_i_rp 是误差的积分
  • 我为积分限幅为100,因为我发现当达到这个值时就有比较强的回复力
  • 公式中的 fly_dt 表示每 3ms 调整一次,实际并不需要加这个 fly_dt,只有在每次进入计算的时间不等时才需要,此处是为了公式的完整性

增量式PID

参数说明

从公式中增量式的 P 对应着位置式的 D,而 I 又对应着 P。

此处 P 过大会引起系统敏感,高频震荡,过小又不能达到目标。

I 则起到了补足的作用。

调试方法

首先调整 I,给定一个参数后观察是否会收敛,之后尝试增大参数,观察收敛速度,速度加快则增大,速度减慢则减小,当调整到有收敛趋势,且收敛速度适中时,加入参数 P。
P 的作用是一直震荡,给定一个参数后观察震荡幅度是否减小,同理,减小增大,增大减小。
需要注意的是,此处的 I 与 P 不是一劳永逸的,想要或好的效果需要不断调整两个参数,例如当观察到调整 P 的效果不明显时,可以适当减小 I 之后再次调整 P。

  • 对于增量式PID中的 D 来讲,我个人调试时发现作用不大,不管设置的多么不合理的值都不会产生明显的变化。

代码与案例展示

void servo_horizontal_trun(uint16 target_h, uint16 h_x)
{
    error_h = h_x - target_h;					//本次误差
    static sint16 last_error_h = 0;				//上一次的误差
    static sint16 last_last_error_h = 0;		//上上次的误差
    static float last_duty_h = SERVO_MID_H;		//上一次的输出
    static float temp_h = SERVO_MID_H;			//这里是将期望值设为初值

    if (h_x != 0)
    {
        offset_intergral_h += error_h;

        if (offset_intergral_h > horizontal_intergral_max)
        {
            offset_intergral_h = horizontal_intergral_max;
        }
        else if (offset_intergral_h < -horizontal_intergral_max)
        {
            offset_intergral_h = -horizontal_intergral_max;
        }

        temp_h -= (p_h * (error_h - last_error_h) + i_h * error_h + d_h * (error_h - 2 * last_error_h + last_last_error_h));
    }
    else
    {
        temp_h = SERVO_MID_H;
    }
	
	//这部分与pid无关,只是对结果的进一步处理
	//===================================================
    if (abs(error_h) <= 3)
    {
        offset_intergral_h = 0;
    }

    if (temp_h > SERVO_H_MAX)
    {
        temp_h = SERVO_H_MAX;
    }
    else if (temp_h < SERVO_H_MIN)
    {
        temp_h = SERVO_H_MIN;
    }
    //===================================================

    last_duty_h = temp_h;
    duty_h = temp_h;
    pwm_set_duty(servoP_H, duty_h);
    last_last_error_h = last_error_h;
    last_error_h = error_h;
}

后记

设置参数与变量时,数据类型很重要,使用浮点型可以保留更多精度,最好在计算时都使用浮点型,我曾因为想当然的认为输出是整型,而错误的使用整型存储变量,导致丢失的精度,从而做了一整天的无用功。

### 关于面包板电源模块 MB102 的 USB 供电规格及兼容性 #### 1. **MB102 基本功能** 面包板电源模块 MB102 是一种常见的实验工具,主要用于为基于面包板的小型电子项目提供稳定的电压输出。它通常具有两路独立的稳压输出:一路为 5V 和另一路可调电压(一般范围为 3V 至 12V)。这种设计使得它可以满足多种芯片和传感器的不同工作电压需求。 #### 2. **USB 供电方式** MB102 支持通过 USB 接口供电,输入电压通常是标准的 5V DC[^1]。由于其内部集成了 LM7805 稳压器以及可调节电位器控制的直流-直流变换电路,因此即使输入来自电脑或其他低功率 USB 设备,也能稳定地向负载供应电力。不过需要注意的是,如果项目的功耗较高,则可能超出某些 USB 端口的最大电流能力(一般是 500mA),从而引起不稳定现象或者保护机制启动断开连接的情况发生。 #### 3. **兼容性分析** 该型号广泛适用于各种微控制器单元 (MCU),特别是那些像 Wemos D1 R32 这样可以通过杜邦线轻松接入并共享相同逻辑级别的系统[^2]。另外,在提到 Arduino Uno 板时也表明了良好的互操作性,因为两者均采用相似的标准接口定义电气特性参数设置[^4]: - 对于需要 3.3V 工作环境下的组件来说,只需调整好对应跳线帽位置即可实现精准匹配; - 当涉及到更多外围扩展应用场合下,例如带有多重模拟信号采集任务的情形里,利用 MB102 提供干净无干扰的基础能源供给就显得尤为重要了[^3]。 综上所述,对于打算构建以单片机为核心的原型验证平台而言,选用具备良好声誉记录且易于获取配件支持服务链路上下游资源丰富的品牌产品——如这里讨论过的这款特定类型的配电装置不失为明智之举之一。 ```python # 示例 Python 代码展示如何检测硬件状态 import machine pin = machine.Pin(2, machine.Pin.IN) if pin.value() == 1: print("Power supply is stable.") else: print("Check your connections and power source.") ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值