在上一篇文章中,我们看到了如何通过牺牲一些速度和/或准确性来提高开/关控制的稳定性。如果我们不想放弃这么多目标,另一种改进控制的方法是尝试不同的算法。我们的开/关控制算法可能不是我们正在做的事情的最佳选择,比如定位一个物体相对于另一个物体的位置。例如,想象一下,你会使用开/关控制算法来定位你的汽车相对于红绿灯的任务。你会怎么做:让你的汽车以恒定速度驶向红绿灯,然后当你到达红绿灯时突然猛踩刹车。你实际上不能立即停下来,所以当你最终在十字路口停下来时,你会把车挂上倒挡,猛踩油门,你倒车全速直到你的车再次到达红绿灯,这时你再次猛踩刹车。你再次超过红绿灯,所以你再次换到前进挡,再次猛踩油门。你继续这样做,直到灯光最终变绿,然后你前往下一个红绿灯重复这个过程。如果你真的这样做了,你可能会伤害到某人,你肯定会毁了你的车。好的司机实际上做的与此非常不同,他们看到前方的红绿灯,估计他们的车和交通灯之间的距离,并在到达之前开始减速。离交通灯越近,开得越慢。通过这种方式,他们可以在不倒车的情况下平稳地停在交通灯处。这种控制算法通常被称为线性控制。与使用单一速度(要么开启要么关闭)不同,速度会根据两个物体之间的相对位置进行调整。
最简单的线性控制类型称为比例控制。在这个算法中,速度被计算为一个常数(称为增益Gain)乘以误差(error),即物体所在位置与我们想要的位置之间的差异。让我们在我们的代码中尝试这个。要为我们的电机使用比例控制,我们需要根据电机位置的误差来改变电机的速度。所以我们在代码中要做的第一件事是创建一个变量来计算误差,这个常数在方程中表示为Kp。我们将这个设置为浮点值,现在将其设置为0.5。稍后在本视频中,我们将看看改变这个常数值的效果。
// Define the proportional constant (Kp) to tune the responsiveness
float Kp = 0.5; // Adjust this value to tune the proportional control
在我们得到计数之后,我们可以计算误差。误差是我们想要的位置和我们实际所在的位置之间的差异。
// Read the current encoder position
currentPosition = myEncoder.read();
// Calculate the error between the target and current position
long error = targetPosition - currentPosition;
现在,如果误差大于0,我们希望电机向前移动,否则如果误差小于或等于零,我们希望向反方向转动。当误差等于零时,我们无论如何都会关闭电机,因为我们正在计算与误差成比例的速度。
// Control motor direction and speed
if (error > 0) {
// Rotate forward
digitalWrite(IN1, HIGH); // Forward direction
digitalWrite(IN2, LOW);
analogWrite(ENABLE1, motorSpeed); // Proportional speed
} else {
// Rotate backward
digitalWrite(IN1, LOW); // Backward direction
digitalWrite(IN2, HIGH);
analogWrite(ENABLE1, motorSpeed); // Proportional speed
}
现在我们希望根据误差计算速度,而不是像这里一样是一个恒定值。让我们为速度创建一个变量。让我们将其设置为整数。
// Calculate the motor speed using proportional control
// Speed is proportional to the error (bigger error = higher speed)
int motorSpeed = abs(error) * Kp;
好的,现在如果误差大于零,我们可以计算速度为我们的常数Kp乘以误差,因为误差是正的,我们会得到一个正的速度。然而,我们不希望速度超过255,因为那是我们可以写入我们的PWM比较器的最大值。所以如果速度大于255,我们将将其设置为255。然后我们将速度值写入比较器。否则,即如果误差小于或等于零,我们需要计算速度为负Kp乘以误差。那是因为我们的速度值是我们写入比较器的,比较器值永远不能是负的。所以如果速度大于255,我们将速度设置为255,
// Cap the motor speed between 0 and 255 (PWM range)
motorSpeed = constrain(motorSpeed, 0, 2550);
全部代码如下:
#include <Encoder.h> // Include Encoder library
// Define motor control pins
int IN1 = 8;
int IN2 = 9;
int ENABLE1 = 10; // PWM for speed
// Define encoder pins and create Encoder object
Encoder myEncoder(2, 3); // Channel A = pin 2, Channel B = pin 3
long targetPosition = 250; // 1/4 cycle, assuming 1000 pulses for a full cycle
long currentPosition = 0; // Current position from the encoder
// Define the proportional constant (Kp) to tune the responsiveness
float Kp = 0.5; // Adjust this value to tune the proportional control
void setup() {
// Set motor control pins as outputs
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(ENABLE1, OUTPUT);
// Initialize serial communication for debugging
Serial.begin(9600);
// Reset encoder position to 0 at start
myEncoder.write(0);
}
void loop() {
// Read the current encoder position
currentPosition = myEncoder.read();
// Calculate the error between the target and current position
long error = targetPosition - currentPosition;
// Calculate the motor speed using proportional control
// Speed is proportional to the error (bigger error = higher speed)
int motorSpeed = abs(error) * Kp;
// Cap the motor speed between 0 and 255 (PWM range)
motorSpeed = constrain(motorSpeed, 0, 2550);
// Print positions and speed for debugging
Serial.print("Current Position: ");
Serial.print(currentPosition);
Serial.print(" | Target Position: ");
Serial.print(targetPosition);
Serial.print(" | Error: ");
Serial.print(error);
Serial.print(" | Motor Speed: ");
Serial.println(motorSpeed);
// Control motor direction and speed
if (error > 0) {
// Rotate forward
digitalWrite(IN1, HIGH); // Forward direction
digitalWrite(IN2, LOW);
analogWrite(ENABLE1, motorSpeed); // Proportional speed
} else {
// Rotate backward
digitalWrite(IN1, LOW); // Backward direction
digitalWrite(IN2, HIGH);
analogWrite(ENABLE1, motorSpeed); // Proportional speed
}
delay(50); // Small delay for stability (can be adjusted or removed)
}
运行结果:

Kp=0.5
让我们回到代码并改变Kp的值,将Kp的值设置为0.8我们应该看到不稳定性增加了一点,我们现在的超调比KP为0.5时更多,但运动仍然稳定。

Kp=0.8
让我们尝试将KP更改为1,看看会发生什么。当KP等于1时,系统变得不稳定。

Kp=1
通常,当你增加Kp时,你会有更少的稳定性,更少的误差和更大的速度。但如果Kp太大,系统会变得不稳定。