简体   繁体   English

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

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

Sorry if my question is too stupid, but I can't figure out how to solve my problem.对不起,如果我的问题太愚蠢,但我不知道如何解决我的问题。 I have a motor with a gearbox and I also have an absolute encoder mounted on the gearbox shaft.我有一个带变速箱的电机,我还有一个安装在变速箱轴上的绝对编码器。 I need to make the output shaft rotate in a range from -90 to +90 and it is centered in 0°.我需要使 output 轴在 -90 到 +90 的范围内旋转,并且以 0° 为中心。 Now, when the shaft is in 0°, then the encoder outputs 1010, when it is at -90°, the encoder outputs 1120 and when it is in +90° it outputs 900.现在,当轴在0°时,编码器输出1010,当它在-90°时,编码器输出1120,当它在+90°时输出900。 在此处输入图像描述

When the shaft is in 0° and has to reach +90°, the motor must rotate clockwise and when it needs to reach -90°, it needs to rotate counterclockwise.当轴处于0°,必须达到+90°时,电机必须顺时针旋转,当需要达到-90°时,电机需要逆时针旋转。

I would like to command the motor by only giving it the position in degree.我想通过只给它 position 度数来控制电机。 For example, I'd like to have a function like:例如,我想要一个 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
}

I think that a PID controller would be a smart solution, but I really do not know how to implement it in C++, sorry, I'm not a developer.我认为 PID controller 将是一个聪明的解决方案,但我真的不知道如何在 C++ 中实现它,对不起,我不是开发人员。 Or do you suggest just to use if/else statements?还是您建议只使用 if/else 语句?

EDIT:编辑:

In order to make the motor move, I use this function:为了使电机移动,我使用这个 function:

void move_motor(motor_id, direction)

and it makes the motor spin in counterclockwise or clockwise depending on the second parameter To stop the motors:它使电机根据第二个参数逆时针或顺时针旋转停止电机:

void stop_motor(motor_id, 0)无效 stop_motor(motor_id, 0)

and this other function:还有这个 function:

int get_enc(encoder1)

returns an integer depending on the encoder1 readings.根据编码器 1 的读数返回 integer。

So for example, to reach the desired position it should be:因此,例如,要达到所需的 position 它应该是:

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

but the direction should be handled, too.但是方向也应该处理。

Here's how I've understood it:以下是我的理解:

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

Then this function would do that:然后这个 function 会这样做:

#include <algorithm>

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

std::clamp is used to limit the output between 900 and 1120 . std::clamp用于将 output 限制在9001120之间。

Here you go:这里是 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);
   }
}

Note that the motor_id might be a different type which you'll have to slightly adjust.请注意,motor_id 可能是不同的类型,您需要稍微调整一下。 And perhaps the get_enc requires a different argument, but this is the idea.也许get_enc需要不同的参数,但这就是想法。

Credit goes to @TedLyngmo who provided the angle2pid function.归功于@TedLyngmo,他提供了angle2pid function。

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

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