繁体   English   中英

在 C++ 中为带绝对编码器的电机实施 PID 控制

[英]Implement a PID control in C++ for a motor with absolute encoder

对不起,如果我的问题太愚蠢,但我不知道如何解决我的问题。 我有一个带变速箱的电机,我还有一个安装在变速箱轴上的绝对编码器。 我需要使 output 轴在 -90 到 +90 的范围内旋转,并且以 0° 为中心。 现在,当轴在0°时,编码器输出1010,当它在-90°时,编码器输出1120,当它在+90°时输出900。 在此处输入图像描述

当轴处于0°,必须达到+90°时,电机必须顺时针旋转,当需要达到-90°时,电机需要逆时针旋转。

我想通过只给它 position 度数来控制电机。 例如,我想要一个 function 像:

move_motor(1, 45°)

int move_motor(id_motor, pos){
 read current motor position
 // motor is at 0°
 make motor #1 spins clockwise until encoder returns 955
}

我认为 PID controller 将是一个聪明的解决方案,但我真的不知道如何在 C++ 中实现它,对不起,我不是开发人员。 还是您建议只使用 if/else 语句?

编辑:

为了使电机移动,我使用这个 function:

void move_motor(motor_id, direction)

它使电机根据第二个参数逆时针或顺时针旋转停止电机:

无效 stop_motor(motor_id, 0)

还有这个 function:

int get_enc(encoder1)

根据编码器 1 的读数返回 integer。

因此,例如,要达到所需的 position 它应该是:

while (get_enc != desired_position){
move_motor(motor_id, direction)
}

但是方向也应该处理。

以下是我的理解:

  input   output
----------------
<= -90°    1120
   -45°    1065
     0°    1010
   +45°     955
>= +90°     900

然后这个 function 会这样做:

#include <algorithm>

unsigned angle2pid(float angle_in_degrees) {
    return std::clamp(1010 - angle_in_degrees * 55 / 45, 900.f, 1120.f);
}

std::clamp用于将 output 限制在9001120之间。

这里是 go:


unsigned angle2pid(double angle_in_degrees) 
{
    return 1010 - angle_in_degrees * 55 / 45;
}

void move_motor(int motor_id, double angle)
{
   static const int CLOSE_ENOUGH = 10;
   int currentPosition = get_enc(motor_id);
   int desiredPosition = angle2pid(angle);
   
   // IF WE ARE CLOSE ENOUGH, DO NOTHING...
   if(std::abs(currentPosition - desiredPosition) <= CLOSE_ENOUGH)
   {
       return;
   }
   
   if(desiredPosition > currentPosition)
   {
       move_motor(motor_id, CLOCKWISE);
       while(desiredPosition > currentPosition)
       {
           currentPosition = get_enc(motor_id);
       }
       stop_motor(motor_id);

   }
   else if(desiredPosition < currentPosition)
   {
       move_motor(motor_id, COUNTER_CLOCKWISE);
       while(desiredPosition < currentPosition)
       {
           currentPosition = get_enc(motor_id);
       }
       stop_motor(motor_id, 0);
   }
}

请注意,motor_id 可能是不同的类型,您需要稍微调整一下。 也许get_enc需要不同的参数,但这就是想法。

归功于@TedLyngmo,他提供了angle2pid function。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM