我正在使用带有蜗轮蜗杆变速箱的直流电动机来控制摆的角度位置。从机械上讲,蜗轮无法反向驱动。

在带有常规直流电动机(无蜗轮)的摆系统上使用PID控制器,积分器将帮助电动机找到适当的恒定功率设置来克服重力使摆锤可以保持任意位置。然而,对于蜗轮,一旦达到期望的位置,就不需要向电动机施加恒定的动力。可以切断电动机的电源,蜗轮蜗杆将抵抗重力的作用,从而将钟摆反向驱动到最低的重力势。

在我看来,PID算法的积分器会导致一旦达到所需位置,将产生较大的过冲。我希望积分器最初帮助将钟摆控制到所需位置。但是一旦达到位置,我就需要关闭积分器。

我唯一能想到的解决方案是在PID算法中测试特殊条件,以检查位置是否具有达到角速度很小,然后立即将积分器重置为零。

**编辑*

当我最初说我的问题时,我主要只是对PID回路中反向驱动电阻的理论方法。但是,如果我解释一下我正在构建的实际机制,那将会有所帮助。该设备是在车窗玻璃上旋转的机械臂。它还有时会在臂的末端捡起和放下小砝码。电动机的制造差异性以及拾取小重量时驱动转矩的差异导致我考虑使用PID回路。

评论

您的反馈是什么?您的系统到底是什么样的?您是否可以反向驱动系统都无关紧要,即不会影响您的过冲。可能重要的是存在的反冲(这又与反向驱动无关)。您所谈论的是过度阻尼与欠阻尼。

我正在使用霍尔效应旋转传感器进行反馈。我还编辑了问题以描述系统的外观。

是的,反冲是我要解决的问题。我希望设计一个充分阻尼的控制系统,以防止摆锤突然减速时由于齿轮倾斜而导致摆锤过冲。

#1 楼

这是我自己的类PID调节器的图片,其形式为:

out = feed + MaxMin(DiffMax, DiffMin, // limit the difference, add feed (can be removed)
  + P*(E=setp-feed)                   // proportional factor, error calculation
  + (A = MaxMin(AccuMax, AccuMin, A   // limit for accumulator
  + I*E - D*(feed-prev)))             // joined integrator and derivator


与常规PID调节器的最大区别在于,对于两个I和D-有点类似于ryan0270提到的泄漏积分器(我也在尝试类似的东西)。派生器将减少累加器(也可以限制累加器,以防止在设定值发生较大变化时出现饱和和较大的值)。



blue =输出/控制信号(力,输入锅炉)
白色=反馈(调节值,实际温度)
绿色/黄色=设定点(期望值)
红色=蓄能器的状态(中心位于+ 50%)
我已经为温度调节设计了它,但是它似乎同样可以解决您的问题。我的系统衰减因子是模拟等温调节器的温度耗散/误差。您的重力和可变的小重量似乎与我相似。积分器可以对此进行补偿,但通常会过冲并引起振荡。应用于共享累加器的微分器可防止-通过进行更改来减少累积的误差。

比例在开始时最强(启动加速),积分器紧随其后(纠错加速度),并且微分器将使其缓慢减速(就像制动器一样-通过减少累加器来防止过冲)。

调节器步骤:

//  regulator step
    float diff = setp - feed
    float accu = 0
    if pA && !isnan(diff)
    //  integrator
        accu = *pA + I*diff
    //  derivator
        if pV
            accu += D*(*pV - feed)
            *pV = feed
    //  accu limits
        if accu > aMax; accu = aMax
        if accu < aMin; accu = aMin
    //  store back
        *pA = accu
//  proportional
    diff = P*diff + accu
//  diff limits
    if diff > dMax; diff = dMax
    if diff < dMin; diff = dMin


完整代码:

#include <math.h>
#include "mem/config.h"
#include "device/analog.h"

__packed struct PID
    byte    type
    char    name[9]
    word    period
    Timer   tmr
    byte    feed, setp
    word    flags
    ANALOG  output
    float   vals[9]

enum
    fP          = 1<<0
    fI          = 1<<1
    fD          = 1<<2
    fDiffMax    = 1<<4
    fDiffMin    = 1<<5
    fAccuMax    = 1<<6
    fAccuMin    = 1<<7

void devPid()
    PID *pid = (PID *)xpointer(DevAddr)
    if !pid->tmr.reached(pid->period*10u)
        return
    pid->tmr.start()

//  inputs
    float feed = 0.0f
    float setp = 0.0f
    if pid->feed < ainCount
        feed = getxf(ains[pid->feed] + AIN_value)
    if pid->setp < ainCount
        setp = getxf(ains[pid->setp] + AIN_value)

//  PID factors (multiplicators)
    float P = 0.0f
    float I = 0.0f
    float D = 0.0f
//  difference limits (output-feedback)
    float dMax = INFINITY
    float dMin = -INFINITY
//  accumulator limits (anti-windup)
    float aMax = INFINITY
    float aMin = -INFINITY

//  flags and pointers
    word flags = pid->flags
    float __packed* pf = pid->vals
    float __packed* pA = null   // accumulator
    float __packed* pV = null   // previous feed

//  parse variable object part
    if flags & fP
        P = *pf++
    if flags & fI
        I = *pf++
        pA = pf++
        if flags & fD
            D = *pf++
            pV = pf++
    if flags & fDiffMax
        dMin = -(dMax = *pf++)
        if flags & fDiffMin
            dMin = *pf++
    if flags & fAccuMax
        aMin = -(aMax = *pf++)
        if flags &fAccuMin
            aMin = *pf++

//  regulator step
    float diff = setp - feed
    float accu = 0
    if pA && !isnan(diff)
    //  integrator
        accu = *pA + I*diff
    //  derivator
        if pV
            accu += D*(*pV - feed)
            *pV = feed
    //  accu limits
        if accu > aMax; accu = aMax
        if accu < aMin; accu = aMin
    //  store back
        *pA = accu
//  proportional
    diff = P*diff + accu
//  diff limits
    if diff > dMax; diff = dMax
    if diff < dMin; diff = dMin

//  final output
    ainSet(DevAddr + offsetof(PID,output),
      feed + diff)


您可以对其进行一些调整,并使用误差,累加器和反馈变化来检测稳态以将其关闭。


附件

我已经进行了更多的实验-将调节器与错误的主调节(基本转换在高值时表现很差)一起使用了带有错误的非线性7位DAC(由很少的电阻器和光电晶体管定制)的调节器(好的ADC被用作反馈)。调节器的性能非常好,并很快以1位振荡结束(这是不可避免的)。我借助所获得的知识进一步增强了我的仿真,这是图片:



#2 楼

我会发现诸如泄漏的积分器之类的东西。主要组件将积分误差,但还有另一个组件将始终随着时间逐渐衰减积分值。

#3 楼

听起来您根本不需要PID控制器。您正在尝试移动蜗轮直到达到给定的设定点,然后将其关闭-比例控制听起来像您所需要的。

评论


$ \ begingroup $
我在上面编辑了我的问题,以进行澄清。我最担心的是电动机的可变性(如果我制造的不止一个),以及拾取重量时所需驱动转矩的差异。
$ \ endgroup $
–丹·拉克斯(Dan Laks)
2014年7月1日在7:30

$ \ begingroup $
在这种情况下,PI控制器可能更适合您。积分项应补偿所需的任何额外扭矩。 (当您提到电动机的可变性时,我假设您是在谈论扭矩,对吗?)
$ \ endgroup $
–伊恩
2014年7月1日在17:06

$ \ begingroup $
是的,这是正确的。积分仍然让我有些困惑。我想象当手臂接近设定点时,积分器会加速运转。当位置误差接近零时,来自P的力分量将接近零。通常,然后,来自I的力分量将有助于抵抗重力和其他恒定力,以将臂保持在设定点。但是由于蜗轮蜗杆的特性,这些力都不起作用。由于假脱机处理,我不会抗拒任何东西,但是它仍然具有非零值,这会不会导致过冲跳跃?
$ \ endgroup $
–丹·拉克斯(Dan Laks)
2014年7月2日在17:44



$ \ begingroup $
也许我仍在误解您的问题(否则您将试图同时解决这两个问题)。如果需要更多扭矩来增加重量-恒定力-那么I项是实现这一目标的唯一方法。请记住,随着接近设定点,P项将减小,而I项保持不变。在这种情况下,您不应超出目标。我认为ryan0270的答案可能是您想要的答案。
$ \ endgroup $
–伊恩
2014年7月2日23:37

#4 楼

为什么不只有死区呢? (当位置足够接近目标时,停止控制电动机。)