[英]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 限制在900
和1120
之间。
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.