hzocce 发表于 2025-3-11 16:23

PID 电机调速 问题

本帖最后由 hzocce 于 2025-3-19 16:21 编辑

问大家一个问题,转速通常是RPM, 也就是每分钟的转速,除以60秒便是 RPS ,

电机转动感应霍尔,通过霍尔输出的脉冲来获取电机的转速,采样转速需要一定的时间,比如一秒内数霍尔输出的脉冲来 或得电机的转动速度。

那控制电机转动的时候,通过霍尔的反馈,来调整电机的驱动信号。

那我想知道的是,这个调用周期通常是多少合适?是1S数 一个脉冲,然后下一秒调整输出

还是半秒一次?
时间越密集,那是不是检测的越不准?
那时间长了,那调整的时间是不是变得非常漫长了?

有没有分享一个 调速例程呢? 谢谢~~

hzocce 发表于 2025-3-12 08:28

........

qinlu123 发表于 2025-3-12 10:34

你说的很对,用霍尔测速就是这样

hzocce 发表于 2025-3-12 11:45

qinlu123 发表于 2025-3-12 10:34
你说的很对,用霍尔测速就是这样

这样调节起来不是要好久,很费时间

coody 发表于 2025-3-12 18:11

测周期啊,我都是用一定的时间来测N个周期的时间来计算转速,比如计算周期是100ms,则每隔100ms检测N个脉冲对应的时间t,则周期就是t/N,速度就是N/t,比如某次测得N=10,t=99.8002ms,则转速就是100.2/S。

hzocce 发表于 2025-3-13 15:24

coody 发表于 2025-3-12 18:11
测周期啊,我都是用一定的时间来测N个周期的时间来计算转速,比如计算周期是100ms,则每隔100ms检测N个脉冲 ...

谢谢大佬指点

hzocce 发表于 2025-3-14 09:18

调试起来,好不容易

不知道有没有哪位坛友做过这样的处理

能不能分享 一个例程呢?

hzocce 发表于 2025-3-17 10:26

struct PID
{
        float SetSpeed;//每100ms的转速
        float DriverOut;//为检测到零点之后延时打开可控硅的时间。
        float Err;//当次误差
        float LastErr;//上次误差
        float Kp;
        float Ki;
        float Kd;
        float Integral;
};
void Pid_init(void)
{
        PID.SetSpeed=60;
        PID.DriverOut=0;
        PID.Err=0;
        PID.LastErr=0;
        PID.Kp=2.2;
        PID.Ki=0;
        PID.Kd=0;

}
//定时调用
void AutoReloadCallback(void)
{
        int Actual_Encoder_Hall_Speed = 0;
        int res_pwm = 0;

        Actual_Encoder_Hall_Speed=HallPulseNumber;//
        PID.LastErr = PID.Err;
        PID.Err = PID.SetSpeed -Actual_Encoder_Hall_Speed;
       
        PID.Integral += PID.Err;


//        PID.DriverOut = PID.Kp * PID.Err +
//                                     PID.Ki * PID.Integral +
//                                     PID.Kd * (PID.Err - PID.LastErr);

        PID.DriverOut = PID.Kp * PID.Err ;
        //DriverOut为检测到零点之后延时打开可控硅的时间。
        if(PID.DriverOut>165)PID.DriverOut=165;;
        if(PID.DriverOut<30)PID.DriverOut=30;
}

hzocce 发表于 2025-3-17 10:30

单独调整PID.SetSpeed,固定float Kp;
单独调整float Kp,固定PID.SetSpeed;

固定速度在某个值,有的时候能稳定,多开几次又出现了振动,一到速度时候又上升,然后慢慢下降到设置速度,一到之后又上升,反反复复;


暖心小太阳 发表于 2025-3-18 13:26

在实际应用中,电机的负载变化也会影响调速效果

hzocce 发表于 2025-3-18 16:03

暖心小太阳 发表于 2025-3-18 13:26
在实际应用中,电机的负载变化也会影响调速效果

PID 不就是 让负载变化的时候,能比较稳定在某个转速么?、

hzocce 发表于 2025-3-19 11:19

本帖最后由 hzocce 于 2025-3-19 16:24 编辑

struct PID
{
      float SetSpeed;//每100ms的转速
      float DriverOut;//为检测到零点之后延时打开可控硅的时间。
      float Err;//当次误差
      float LastErr;//上次误差
      float Kp;
      float Ki;
      float Kd;
      float Integral;
};
void Pid_init(void)
{
      PID.SetSpeed=60;
      PID.DriverOut=0;
      PID.Err=0;
      PID.LastErr=0;
      PID.Kp=2.2;
      PID.Ki=0;
      PID.Kd=0;

}

//定时调用
void AutoReloadCallback(void)
{
      int Actual_Encoder_Hall_Speed = 0;
      int res_pwm = 0;

      Actual_Encoder_Hall_Speed=HallPulseNumber;//
      PID.LastErr = PID.Err;
      PID.Err = Actual_Encoder_Hall_Speed-PID.SetSpeed ;//发现这样才行,为什么?      
//PID.Err = PID.SetSpeed -Actual_Encoder_Hall_Speed;
      
      PID.Integral += PID.Err;


      PID.DriverOut = PID.Kp * PID.Err +
                                     PID.Ki * PID.Integral +
                                     PID.Kd * (PID.Err - PID.LastErr);

      //DriverOut为检测到零点之后延时打开可控硅的时间。
      if(PID.DriverOut>165)PID.DriverOut=165;;
      if(PID.DriverOut<30)PID.DriverOut=30;
               
                Out(PID.DriverOut);
}

看到的现象是,屏蔽上面的取值,直接给PID.DriverOut赋值,如下
赋值时得到如下数值:
PID.DriverOut=172;HallPulseNumber=12;
PID.DriverOut=170;HallPulseNumber=20;
PID.DriverOut=165;HallPulseNumber=45;
PID.DriverOut=160;HallPulseNumber=70;
PID.DriverOut=150;HallPulseNumber=100;
PID.DriverOut=140;HallPulseNumber=125;
PID.DriverOut=130;HallPulseNumber=143;

如上AutoReloadCallback有没有那里有问题?

PID.Kp、PID.Ki、PID.Kd大概怎么取值才合适,

hzocce 发表于 2025-3-19 13:11

随意给i为1,d为1
拔掉电机的电极,完全静止的时候上电,空载的时候,能稳定下来转速。
拔掉电机的电极,未停下来的时候上电,发现转速失控了。

hzocce 发表于 2025-3-20 08:32

别别沉了

hzocce 发表于 2025-3-21 08:13

........

mbutterfly 发表于 2025-3-22 16:11

跟着学习下,最近学电机。

hzocce 发表于 2025-3-24 08:11

关注起来~~
页: [1]
查看完整版本: PID 电机调速 问题