lazo de control de velocidad para la línea que sigue al Robot

0

Estoy trabajando para controlar la velocidad en mi línea siguiendo el Robot (usando arduino uno), usando la constante proporcional Kp en un circuito cerrado, en mi código calculo las RPM del motor derecho y el motor izquierdo, usé el temporizador2 interrumpa cada 50 ms para calcular la velocidad (RPM) de estos codificadores.

Utilicé el temporizador 0 y el temporizador 1 para generar señales pwm con un ciclo de trabajo VARIEDAD = 75% para controlar la velocidad de los motores de remolque, Medí el RPM para el motor izquierdo usando el tacómetro que es 100 RPM, Cambié la constante de Kp, pero la salida de mi codificador aún me ofrece aproximadamente 80 RPM (sin cambios).

entonces mi pregunta es: ¿hay algún problema en mi código o en la forma en que hago el bucle de control o la comprensión del bucle de control?

Este es el Código:

//encoders variable
volatile bool counting;
volatile unsigned long events0;//the number of pulses from Left Motor in 50 ms;
volatile unsigned long events1;//the number of pulses from Right Motor in 50 ms;
double n1=540;//the number of pulses in one turn for the Right Encoder;
double n2=540;//the number of pulses in one turn for the Left Encoder;
//end of encoders variable

  //PID controller Variable.
 double setpoint=100; // Reference speed;
 const int Kp=10;
 const int Ki=0;
 const int Kd=0;
 double measuredRightRpm_value;//speed in RPM from Right encoder/Motor;
 double measuredLeftRpm_value;//speed in RPM from Left encoder/Motor;
 volatile signed long erorR;//Eror from Right Encoder;
 volatile signed long erorL;//Eror from Left Encoder;
 volatile signed long Eror; 
 //End of PID controller Variable.

 //Timer 2 over flow interrupt
  int x = 0, flag = 0;

  ISR (TIMER2_OVF_vect)
  {
  TCNT2=0x64;//for 10 ms
  x++;
  if(x==5) //to get 50 ms
  { 
  flag = 1;
  x=0;
  }  
   }  // end of ISR

 void eventISR ()
 {
 if (counting)
 events0++;    
 }  // end of eventISR
 void eventISR1 ()
 {
 if (counting)
 events1++;    
 }  // end of eventISR1
void setup ()
{
//setup Timer 0 and Timer 1 to generate Pwm signals
TCCR0A=0xB3;
TCCR0B=0x02; // set Timer 0 to clk/8 HZ ,fast PWM mode,tow signal inverted to each  other.

TCCR1A=0xB1;// set Timer 1 to clk/8 HZ ,fast PWM mode,tow signal inverted to each other.
TCCR1B=0x0A;;

TCCR2A=0x00;//timer 2 overflow interrupt to calculate RPM from Encoder
TCCR2B=0x07;
TCNT2=0x64;

 pinMode(5,OUTPUT);
 pinMode(6,OUTPUT); 
 pinMode(9,OUTPUT);
 pinMode(10,OUTPUT);
 //end of Timers  setup for generating PWM and interrupts.


 //Encoder Setup    
 Serial.begin (9600);
 Serial.println ();
 pinMode (2, INPUT_PULLUP);
 attachInterrupt (0, eventISR, RISING);
 attachInterrupt (1, eventISR1, RISING);
 // end of Encoder setup
 counting = true;
 // Timer/Counter 2 Interrupt(s) initialization
 TIMSK2=0x01;
 interrupts ();
 }  // end of setup

 void showResults ()
 {

 Serial.print ("the speed (RPM) for the Left Motor = ");
 Serial.println ((events0/n1)*(60000/50));
 measuredLeftRpm_value=(events0/n1)*(60000/50);

 //Serial.print ("I counted for the second  Motor  ");
 //Serial.println (events1); 
 Serial.print ("the speed (RPM) for Right Motor = ");
 Serial.println ((events1/n2)*60000/50);

  }  // end of showResults

 void PID()
 {

 measuredRightRpm_value=(events0/n1)*(60000/50);//speed in Rpm from Right/encoder/Motor.
 erorR= setpoint - measuredRightRpm_value;//Erorr From_Right Encoder.

 measuredLeftRpm_value=(events1/n2)*60000/50;////speed in Rpm from Left/encoder/Motor.
 erorL= setpoint - measuredLeftRpm_value;////Erorr From_Left Encoder.


 }

void loop ()
{

counting = true; 
if(flag ==1)
{
  showResults();
  PID();
events0 = 0;
events1 = 0;
erorR=0;
erorL=0;
flag = 0;
}  


OCR0A=192+Kp*erorR; //75% DutyCycle  for Right Motor .
OCR0B=192+Kp*erorR;
OCR1A=-192-Kp*erorL;//75% DutyCycle  for Left Motor.
OCR1B=-192-Kp*erorL; 
}  // end of loop
    
pregunta user119436

1 respuesta

1

He encontrado el Kp en la parte inferior. El problema es que usted calcula erorL, R en PID () presumiblemente en una interrupción temporizada (indicador == 1), pero luego establece todo en cero una vez que se devuelve desde PID (). También necesitará un reajuste en los tipos de números, debe usar matemática de punto flotante para calcular el error, Kp, ... luego para truncar en entero, luego sumar o restar. También se necesita una limitación de valor de salida 0-100%. No soy programador de C o C ++, por lo que el pseudocódigo para el regulador P simple es el siguiente, todos los números son de tipo flotante:

Y_regulator = (Setpoint-ProcessValue) * Kp + Y_static (Setpoint)
// ProcessValue ... su valor medido
// Y_static ... esta es una curva almacenada, en su caso, ha establecido esto en 75%
si Y_regulator > 100.0 entonces
  Y_regulator = 100.0
elseif Y_regulator < 0.0 entonces
  Y_regulator = 0.0
endif

Luego haga noramlización, convierta de 0 a 100% en sus números de registros, multiplicando / dividiendo, redondeando.

Y_Static (Setpoint) se puede omitir, pero necesitará un regulador PI; de todos modos, con un regulador P nunca alcanzará la velocidad exacta, pero lo suficientemente cerca para la aplicación necesaria.

    
respondido por el Marko Buršič

Lea otras preguntas en las etiquetas