Problemas con el ajuste PID de Arduino en el motor de CC

4

Estoy utilizando un codificador de eje conectado a un motor de CC para medir RPM, un L293D IC para impulsar el motor y una placa Arduino. Mi objetivo es controlar la velocidad del motor de CC a aproximadamente 200 RPM, y estoy tratando de usar la biblioteca PID del arduino para lograr esto. Mi problema, ahora mismo, es con la afinación. El sistema oscila mucho, y he intentado varios métodos, pero nada parece funcionar. He intentado poner Kd y Ki en cero y ajustar Kp hasta que obtenga una oscilación constante, sin éxito. Además, ajustar Kd no está haciendo amortiguamiento. He intentado usar un programa Python simple para trazar el RPM en función del tiempo y esto es lo que estoy obteniendo:

AcontinuaciónsemuestraelcódigoArduinoqueestoyusando:

#include<PID_v1.h>#defineSpeedSetPoint200doubleInput,Output,Setpoint;//PIDVariablesintpotKp=2;intpotKd=3;intpotKi=4;floatKp=0,Kd=0,Ki=0;PIDmyPid(&Input,&Output,&Setpoint,0,0,0,DIRECT);//RPMCounterunsignedlongstart;constbyteencoderPinA=2;//Apin->interruptpin0constbyteencoderPinB=4;//Bpin->digitalpin4volatilelongpulse;volatileboolpinB,pinA,dir;constbyteppr=25,upDatesPerSec=2;constintfin=1000/upDatesPerSec;constfloatkonstant=60.0*upDatesPerSec/(ppr*2);intrpm=0;intoutputValue=0;//DCMotorPinsintpwm=5;intmotorA1=10;intmotorA2=9;voidsetup(){Serial.begin(19200);Input=25;Setpoint=SpeedSetPoint;myPid.SetMode(AUTOMATIC);attachInterrupt(0,readEncoder,CHANGE);pinMode(encoderPinA,INPUT_PULLUP);pinMode(encoderPinB,INPUT_PULLUP);pinMode(pwm,OUTPUT);pinMode(motorA1,OUTPUT);pinMode(motorA2,OUTPUT);//StartDCMotordigitalWrite(pwm,HIGH);digitalWrite(motorA1,HIGH);digitalWrite(motorA2,LOW);}voidloop(){Kp=analogRead(potKp)/100.0;Ki=analogRead(potKi)/1000.0;Kd=analogRead(potKd)/1000.0;myPid.SetTunings(Kp,Ki,Kd);if(millis()-start>fin){start=millis();rpm=pulse*konstant;rpm=abs(rpm);Serial.println(rpm);pulse=0;}//EndRPMreadingInput=rpm;myPid.Compute();outputValue=Output;//outputValue=map(outputValue,0,400,180,255);analogWrite(pwm,outputValue);Serial.print("RPM = ");
  Serial.print(rpm);
  Serial.print("\t");
  Serial.print("Kp = ");
  Serial.print(Kp);
  Serial.print("\t");
  Serial.print("Ki = ");
  Serial.print(Ki);
  Serial.print("\t");
  Serial.print("Kd = ");
  Serial.println(Kd);
}

void readEncoder()
{
  pinA = bitRead(PIND,encoderPinA);
  pinB = bitRead(PIND,encoderPinB);
  dir = pinA ^ pinB;          // if pinA & pinB are the same
  dir ? --pulse : ++pulse;    // dir is CW, else CCW
}

¿Algún consejo?

    
pregunta Vinicius

2 respuestas

1

Lo primero que salta de tu trama son las variaciones grandes y un tanto aleatorias en iteraciones sucesivas. Eso significa que no estás ejecutando el bucle PID lo suficientemente rápido. Para algo como un motor, cada 5 a 10 ms (100-200 Hz) es probablemente bueno, pero por supuesto eso depende del motor. Normalmente, se desean 20 a 50 iteraciones dentro de la primera constante de tiempo principal del sistema.

Solo después de que el bucle se ejecute lo suficientemente rápido, la sintonización tiene algún sentido.

Comience con solo el término P, manteniendo I y D en 0. Suba el nivel de P hasta justo debajo de donde se produce el timbre. Ahora levante lentamente el término I Esto causará oscilaciones cuando sea demasiado alto. Encuentra un valor que funcione de cierto modo y vuelve a ajustar el término P, etc. Encuentra un conjunto de valores P, I que funcionen.

A menudo se detiene allí, ya que el uso del término D hace que el sistema sea muy susceptible al ruido. Si su señal de retroalimentación está limpia, comience con los buenos valores P e I, y aumente lentamente D. En algunos sistemas, D es realmente negativo para ser útil. Mire detenidamente los cálculos matemáticos de su implementación para ver qué polaridad utilizar.

Piense en la lógica del término D como "Ya nos estamos dirigiendo en la dirección correcta, así que retroceda un poco la unidad" . Esto puede ser útil para amortiguar las cosas para que los otros términos se puedan establecer de forma más agresiva y, por lo tanto, obtenga una respuesta de pasos general más rápida dentro de algún error.

    
respondido por el Olin Lathrop
0

Has omitido las cosas importantes, como tu algoritmo de bucle.

Comience con poco. Salida una constante PWM. ¿Es tu RPM constante? Si no es así, arréglalo.

Juega con tu PWM hasta que obtengas un RPM estable de aproximadamente 200.

Ahora deja que tu Kp aumente. Auméntalo hasta que comiences a oscilar y luego retrocede. ¿Tienes una forma de cargar dinámicamente el motor? Si es así, hazlo y comprueba cuál es el error. Si una carga razonable produce un nivel de error aceptable, deténgase allí. No necesitas un PID.

    
respondido por el WhatRoughBeast

Lea otras preguntas en las etiquetas