我已经成功地使用PD控制器控制了电机的位置。然而,我有一些编程相关的问题。
下面是我的代码:#define encoder0PinA_M1 2
#define encoder0PinB_M1 22
int EnablePin = 8;
int PWMPin1 = 3;
int PWMPin2 = 11;
volatile signed int encoder0Pos = 0;
unsigned long LastTime;
signed int Input;
signed int Scaled_PID;
float PID_Output, Scaled_PID1;
signed int ErrorSum,ErrorDiff,Error,LastError;
float kp=6;
float ki=0;
float kd=1;
int SampleTime = 10;
int TimeChange;
unsigned long Now;
void setup()
{
pinMode(encoder0PinA_M1, INPUT);
//digitalWrite(encoder0PinA_M1, HIGH);
pinMode(encoder0PinB_M1, INPUT);
pinMode(EnablePin, OUTPUT);
pinMode(PWMPin1, OUTPUT);
pinMode(PWMPin2, OUTPUT);
//digitalWrite(encoder0PinB_M1, HIGH);
attachInterrupt(0, doEncoder, CHANGE);
Serial.begin (9600);
Serial.println("start");
}
void PID()
{
Now = millis();
TimeChange = Now - LastTime;
if(TimeChange >= SampleTime)
{
Error = Input - encoder0Pos;
ErrorSum = ErrorSum + Error;
ErrorDiff = Error - LastError;
PID_Output = kp * Error + ki * ErrorSum + kd * ErrorDiff;
LastError = Error;
LastTime = Now;
}
}
void speedlimitforward()
{
if (PID_Output >= 15)
{
PID_Output= 15;
}
if(PID_Output <= -15)
{
PID_Output=-15;
}
Scaled_PID = PID_Output+15;
digitalWrite(EnablePin, HIGH);
analogWrite(PWMPin1,Scaled_PID);
}
void speedlimitbackward()
{
if (PID_Output >= 20)
{
PID_Output= -20;
}
if(PID_Output <= -20)
{
PID_Output= 20;
}
Scaled_PID = PID_Output+20;
digitalWrite(EnablePin, HIGH);
analogWrite(PWMPin2,Scaled_PID);
}
void loop()
{
Input=50;
PID();
speedlimitforward();
}
void doEncoder()
{
if (digitalRead(encoder0PinA_M1) == digitalRead(encoder0PinB_M1))
{
encoder0Pos++;
} else {
encoder0Pos--;
}
}
如果你看一下我的代码,我已经将Input声明为全局变量,并且在loop()中我给Input一个值(在此代码中计数为50)。此代码工作良好,电机停止在接近50编码器计数。
但是当我将上面代码中的循环更改为下面给出的代码时,我的电机不移动。我想让它移动到50 count等待一段时间,然后回到0 count:
void loop()
{
Input=50;
PID();
speedlimitforward();
delay(2000);
Input=0;
PID();
speedlimitbackward();
delay(2000);
Input=-100;
PID();
speedlimitbackward();
}
-
如果你在其他地方问了同样的问题并得到了答案,我认为你应该回到这里回答你自己的问题并标记为已回答,否则人们会花时间在上面。
-
问题显然是
delay(2000)
,如果你看一下代码,你就会明白为什么。当你只有一个指令时,发生的事情是循环开始,检查时间,看看电机是否必须移动,基于经过的时间。因此,如果您设置延迟,下一次循环运行时,时间将完全用于等待,电机将不会移动。 -
你能做的就是跟踪电机正在做什么,并据此移动它。例如,保留一个名为
movement_completed
的变量,并为其分配一个值,当它们完成移动时,该值将由移动函数返回。只有在该变量设置之后,才能继续进行下一组动作。
我认为这里的主要问题是,你必须记住,loop()
是不断被调用,它不是只运行一次的东西。你需要清楚地了解为什么你的马达会在第一个代码停止(然后你就会明白为什么它不会在第二个代码中移动)。