Ребята. Мучаюсь уже месяц. Помогите
Взял за основу гуляющий по инету код ПИД алгоритма и вот не могу добиться точного положения. Либо вообще не позиционируется. Смыкает во все стороны ни как не может попсать в точку. Есть энкодер. По прерыванию снимаем импульсы. Но вот добиться точного положения не могу. Перерыл кучу литературы по ПИД - ужас. Может есть решение проще?
Вот куски кода.
// spinMotor(),
int pinMotor1 = 8;
int pinMotor2 = 9;
int pinMotorSpeed = 10;
// pid ()
float kP = 2.25;
float kI = .5;
float kD = 1;
int iMax = 100;
int iMin = 0;
int error = 0;
int lastError = 0;
int sumError = 0;
int minSpeed = 100;
int maxSpeed = 255;
// loop()
int potVal = 0; // значение потенциометра
int inTimeStep = 0;
// encoder()
int interruptPin = 2;
int buttonDir = 3;
volatile int steping = 0;
void setup() {
Serial.begin(9600);
// motor
pinMode(pinMotor1, OUTPUT);
pinMode(pinMotor2, OUTPUT);
pinMode(pinMotorSpeed, OUTPUT);
// encoder
pinMode(interruptPin, INPUT);
pinMode(buttonDir, INPUT);
digitalWrite(interruptPin, HIGH);
digitalWrite(buttonDir, HIGH);
attachInterrupt(0, encoder, RISING);
}
void loop() {
if (Serial.available()>0) potVal = readPotSerial();
inTimeStep = pid(potVal);
spinMotor (inTimeStep);
}
// speedR - скорость вращения от 0 до 255 (положительное значение вращаем в одну сторону, отрицательное - в другую)
void spinMotor (int speedR) {
if (speedR > 0)
{
digitalWrite(pinMotor1,HIGH);
digitalWrite(pinMotor2,LOW);
}
else if (speedR < 0)
{
digitalWrite(pinMotor1,LOW);
digitalWrite(pinMotor2,HIGH);
speedR = speedR * -1;
}
int motorSpeed = map(speedR, 0, 1024, minSpeed, maxSpeed);
if (steping == potVal ) {
digitalWrite(pinMotor1,LOW);
digitalWrite(pinMotor2,LOW);
}
analogWrite(pinMotorSpeed, motorSpeed);
}
// основной алгоритм подсчета
// расчет скорости и направления движения двигателя (ПИД алгоритм)
int pid(int target) {
int error = steping - target;
int correct = kP * error + kD * (error - lastError) + kI * (sumError);
lastError = error;
sumError += error;
if(sumError > iMax){
sumError = iMax;
}
else if(sumError < iMin){
sumError = iMin;
}
return correct;
}
// читает значение с энкодера через прерывание и инкрементирует или декрементирует значение steping
void encoder() {
if (digitalRead(interruptPin) == digitalRead(buttonDir)) {
steping ++;
}
else {
steping --;
}
}
int minSpeed = 100; взята потому, что на меньших значениях появляется писк и не хватает усилия провернуть мотор
Поделитесь идеями, что не так?