C#Micro Framework问题中的PID控制器

时间:2012-02-05 15:09:58

标签: .net-micro-framework

我已经基于TinyCLR.com的.NET Micro Framework板从头开始构建了tricopter。我使用了运行在72 MHz的FEZ Mini。在http://bit.ly/TriRot了解有关我的项目的更多信息。

因此,在进行飞行前检查后,我初始化并测试每个组件,例如校准IMU并旋转每个电机,检查我是否获得接收器数据等,它进入一个永久循环然后调用每个循环上的飞行控制器方法。

我正在尝试使用PID controller调整我的Ziegler-Nichols method,但我总是会越来越大的超调。我最终只能使用proportional control获得[大多数]稳定振荡(设置K i 和K d = 0);使用秒表计算周期K 的平均时间为3.198秒。

我在类似的answer Rex Logan上看到了questionchris12892){{3}}。

我最初使用“持续时间”变量(以毫秒为单位)使得我的直升机非常具有攻击性,显然是因为我在每个循环中将运行的积分器误差乘以数千。然后我把它除以另外一千来把它带到几秒钟,但我仍然在争吵......

雷克斯的答案中我不明白的是:

  1. 他为什么忽略方程的积分和微分部分的时间变量?这是对的还是错字?
  2. 他的意思是什么

      

    在正常的采样系统中,delta项将是一个......

    一个什么?在正常情况下这应该是一秒吗?什么 如果这个值波动?

  3. 我的飞行控制器方法如下:

    private static Single[] FlightController(Single[] imuData, Single[] ReceiverData)
    {
        Int64 TicksPerMillisecond = TimeSpan.TicksPerMillisecond;
        Int64 CurrentTicks = DateTime.Now.Ticks;
        Int64 TickCount = CurrentTicks - PreviousTicks;
        PreviousTicks = CurrentTicks;
        Single Duration = (TickCount / TicksPerMillisecond) / 1000F;
    
        const Single Kp = 0.117F; //Proportional Gain (Instantaneou offset)
        const Single Ki = 0.073170732F; //Integral Gain (Permanent offset)
        const Single Kd = 0.001070122F; //Differential Gain (Change in offset)
    
        Single RollE = 0;
        Single RollPout = 0;
        Single RollIout = 0;
        Single RollDout = 0;
        Single RollOut = 0;
        Single PitchE = 0;
        Single PitchPout = 0;
        Single PitchIout = 0;
        Single PitchDout = 0;
        Single PitchOut = 0;
    
        Single rxThrottle = ReceiverData[(int)Channel.Throttle];
        Single rxRoll = ReceiverData[(int)Channel.Roll];
        Single rxPitch = ReceiverData[(int)Channel.Pitch];
        Single rxYaw = ReceiverData[(int)Channel.Yaw];
    
        Single[] TargetMotorSpeed = new Single[] { rxThrottle, rxThrottle, rxThrottle };
        Single ServoAngle = 0;
    
        if (!FirstRun)
        {
            Single imuRoll = imuData[1] + 7;
            Single imuPitch = imuData[0];
    
            //Roll ----- Start
            RollE = rxRoll - imuRoll;
    
            //Proportional
            RollPout = Kp * RollE;
    
            //Integral
            Single InstanceRollIntegrator = RollE * Duration;
            RollIntegrator += InstanceRollIntegrator;
            RollIout = RollIntegrator * Ki;
    
            //Differential
            RollDout = ((RollE - PreviousRollE) / Duration) * Kd;
    
            //Sum
            RollOut = RollPout + RollIout + RollDout;
            //Roll ----- End
    
            //Pitch ---- Start
            PitchE = rxPitch - imuPitch;
            //Proportional
            PitchPout = Kp * PitchE;
    
            //Integral
            Single InstancePitchIntegrator = PitchE * Duration;
            PitchIntegrator += InstancePitchIntegrator;
            PitchIout = PitchIntegrator * Ki;
    
            //Differential
            PitchDout = ((PitchE - PreviousPitchE) / Duration) * Kd;
    
            //Sum
            PitchOut = PitchPout + PitchIout + PitchDout;
            //Pitch ---- End
    
            TargetMotorSpeed[(int)Motors.Motor.Left] += RollOut;
            TargetMotorSpeed[(int)Motors.Motor.Right] -= RollOut;
    
            TargetMotorSpeed[(int)Motors.Motor.Left] += PitchOut;// / 2;
            TargetMotorSpeed[(int)Motors.Motor.Right] += PitchOut;// / 2;
            TargetMotorSpeed[(int)Motors.Motor.Rear] -= PitchOut;
    
            ServoAngle = rxYaw + 15;
    
            PreviousRollE = imuRoll;
            PreviousPitchE = imuPitch;
        }
        FirstRun = false;
    
        return new Single[] { 
        (Single)TargetMotorSpeed[(int)TriRot.LeftMotor], 
        (Single)TargetMotorSpeed[(int)TriRot.RightMotor], 
        (Single)TargetMotorSpeed[(int)TriRot.RearMotor],
        (Single)ServoAngle
        };
    }
    

    编辑:我发现上面的代码中有两个错误(现在修复)。我正在整合和区分最后的IMU值而不是最后的错误值。完全摆脱了失控的冥想。现在唯一的问题是它看起来有点慢。当我扰乱系统时,它会很快响应并阻止它继续,但是需要很长时间才能回到设定点(0),大约10秒或更长时间。现在这只是调整PID吗?我将在下面给出建议,并告诉您是否有任何改变。

    我遇到的一个问题是: 作为一个.NET板,我不想依赖于任何类型的精确计时,所以我不是试图以我执行该方法的频率计算出来,当然如果我计算实际时间和因子,它应该更好,还是我误解了什么?

0 个答案:

没有答案