miércoles, 30 de noviembre de 2016

Robot Velocista QTR8A (Parte III - Programacion del Robot)

Programación del Robot


Algoritmo PID

Este sera el encargado de regular el comportamienito del robot y corregir su marcha en el recorrido de la pista, recibe datos entrada (sensores) , las procesa, (PID) y envia la señal de correccion hacia los motores (salida de control) y nuevamente repite el proceso coparando la salida con la entrada (retroalimentacion) sin entrar en mas teoría se puede resumir de manera esquematica este controlador
  • Entrada de mando: Vendría a ser el punto de referencia en donde queremos fijar al robot "Set point", nuestro objetivo es que el robot no se salga de la linea, por lo tanto lo deseado es que siempre se mantenga centrado en el medio, como se vio anteriormente el centro de los sensores arrojaba un valor de posición relativa de 3500, este sera nuestra referencia o "set point" (donde queremos que el robot se mantenga siempre.
  • Controlador :  En este caso el controlador es el encargado de corregir y mantener en marcha al robot, su objetivo es que no se salga del punto de referencia o que almenos logre tenerlo dentro de los rangos permitidos. lo ideal es que mantenga al robot fijado en el centro, pero en la realidad ocurrirá que el mundo externo provoque muchas  perturbaciones haciendo que el robot oscile o se salga del punto de referencia por lo que tendrá que corregir continuamente la marcha. Si este controlador es el "PID"... Que para nuestro caso sera un algoritmo programado en arduino.
  • Planta: La planta esta relacionada con las condiciones físicas del robot, peso, longitud, traccion de los motores, velocidad, rozamiento, inercia, etc.  Como se ve el diagrama de bloques, el controlador modifica el comportamiento de la planta, osea el comportamiento del robot.
  • Salida o señal de control: Es la respuesta producida por el control aplicado en el robot, en este caso la salida  de control se envia al driver de motor y luego a los motores para que puedan corregir la marcha constantemente. la medición de esta salida es jutamente la señal es la posicion actual del robot medido .
  • Realimentacion: Esta compuesta de la adquisición de datos, osea la de los sensores del robot, que va leer la posición relativa actual del robot la procesa y manda nuevamente a comparararse con la referencia que es el "set point"  , esta comparación traerá un resultado llamado error que nuevamente es entregado al controlador para que pueda procesarla y enviar una señal de correccion, la realimentacion es la comparación de la salida con respecto a la entrada, 
Todo esto en gran parte sera el algoritmo de control del robot: Se que es muy abstracto todo lo que concierne con PID, pero con la practica algunos de estos conceptos estaran claros.

En este post ya tramos acerca de cada una de las acciones del PID,  de las constantes y el procedimiento para sintonizar, por lo que ya no seré tan redundante explicando nuevamente. : http://aprendiendofacilelectronica.blogspot.pe/2014/12/robot-velocista-de-competencia_4.html


Circuito del Robot Velocista


Programa Completo

/////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////

#include <QTRSensors.h>

  //entradas
#define btn1      0
#define btn2      1
  //salidas
#define led1      13

#define led_on    9   //~
#define mi1       3
#define mi2       4
#define pwmi      6   //~
#define md1       8
#define md2       7
#define pwmd      5   //~
  

#define NUM_SENSORS             8  // number of sensors used
#define NUM_SAMPLES_PER_SENSOR  1 // average 4 analog samples per sensor reading
#define EMITTER_PIN             9   // emitter is controlled by digital pin 2

QTRSensorsAnalog qtra((unsigned char[]) {7, 6, 5, 4, 3, 2,1,0},NUM_SENSORS, NUM_SAMPLES_PER_SENSOR, EMITTER_PIN);
unsigned int sensorValues[NUM_SENSORS];
int proporcional=0;
int derivativo=0;
int integral=0;
int salida_pwm=0;
int proporcional_pasado=0;
int position=0;

////////////////////Parametros PID/////////////////////////////////
int velocidad=120;
//float KP=0.15, KD=2.2, KI=0.006; //reaccion rapida
float KP=0.01, KD=0.15 , KI=0.0001; //reaccion rapida
///////////////////////////////////////////////////////

/////////////////parametros de sensado/////////////////////////////
int linea=0; //0 linea negra, 1 para linea blanca
int flanco_color=  0 ;
int en_linea=  500 ;
int ruido= 30;
/////////////////////////////////////////////////////////
int boton1=7;
int boton2=7;

void setup()
{
    pinMode(led1,OUTPUT);
    pinMode(led_on,OUTPUT);
    pinMode(mi1,OUTPUT);
    pinMode(mi2,OUTPUT);
    pinMode(pwmi,OUTPUT);
    pinMode(md1,OUTPUT);
    pinMode(md2,OUTPUT);
    pinMode(pwmd,OUTPUT);

digitalWrite(led1,HIGH);
delay(200);
digitalWrite(led1,LOW);
delay(200);

digitalWrite(led1, HIGH);    // turn on Arduino's LED to indicate we are in calibration mode
  for (int i = 0; i < 200; i++)  // make the calibration take about 10 seconds
  {
    qtra.calibrate();       // reads all sensors 10 times at 2.5 ms per six sensors (i.e. ~25 ms per call)
  }
  digitalWrite(led1, LOW);     // turn off Arduino's LED to indicate we are through with calibration
 //Serial.begin(115200);
   //Serial.println();

   while(true)
   {
      botones();
      if(boton2==0) 
      {
        delay(20);
        digitalWrite(led1,HIGH);
        delay(100);
        digitalWrite(led1,LOW);
        delay(100);
        break;
      }
   }
  
Serial.begin(115200);
//bt.println("Hello, world?");

}

void loop()
{
  pid(1,velocidad,KP,KI,KD);
  frenos_contorno(600);

 Serial.println(position);
 delay(2);
}

void pid(int linea, int velocidad, float Kp, float Ki, float Kd)
{
   
   position = qtra.readLine(sensorValues,QTR_EMITTERS_ON, linea, flanco_color, en_linea, ruido);
  //0 linea negra, 1 para linea blanca
  
      //  Serial.println(position);
  proporcional = (position) - 3500; // set point es 3500, asi obtenemos el error
  integral=integral + proporcional_pasado; //obteniendo integral
  derivativo = (proporcional - proporcional_pasado); //obteniedo el derivativo
  int ITerm=integral*KI;
  if(ITerm>=255) ITerm=255;
  if(ITerm<=-255) ITerm=-255;
  
  salida_pwm =( proporcional * KP ) + ( derivativo * KD )+(ITerm);
  
  if (  salida_pwm >velocidad )  salida_pwm = velocidad; //limitamos la salida de pwm
  if ( salida_pwm  <-velocidad )  salida_pwm = -velocidad;
  
  if (salida_pwm < 0)
 {
    int der=velocidad-salida_pwm; //(+)
    int izq=velocidad+salida_pwm;  //(-)
    if(der>=255)der=255;
    if(izq<=0)izq=0;
    motores(izq, der);
 }
 if (salida_pwm >0)
 {
  int der=velocidad-salida_pwm; //(-)
  int izq=velocidad+salida_pwm; //(+)
  
  if(izq >= 255) izq=255;
  if(der <= 0) der=0;
  motores(izq ,der );
 }

 proporcional_pasado = proporcional;  
}


void frenos_contorno(int flanco_comparacion)
{
    if (position <=10) //si se salio por la parte derecha de la linea
    {
      while(true)
      { 
        digitalWrite(led1,HIGH);
        motores(-125,60);
        qtra.read(sensorValues); //lectura en bruto de sensor
        if ( sensorValues[0]<flanco_comparacion || sensorValues[1]<flanco_comparacion || sensorValues[2]<flanco_comparacion || sensorValues[3]<flanco_comparacion || sensorValues[4]<flanco_comparacion || sensorValues[5]<flanco_comparacion || sensorValues[6]<flanco_comparacion || sensorValues[7]<flanco_comparacion)
        {
          break;
        }
        
      }
    }

    if (position>=6990) //si se salio por la parte izquierda de la linea
    {
      while(true)
      {
        digitalWrite(led1,HIGH);
        motores(60,-125); 
        qtra.read(sensorValues);
        if (sensorValues[7]<flanco_comparacion || sensorValues[6]<flanco_comparacion|| sensorValues[5]<flanco_comparacion || sensorValues[4]<flanco_comparacion || sensorValues[3]<flanco_comparacion || sensorValues[2]<flanco_comparacion || sensorValues[1]<flanco_comparacion|| sensorValues[0]<flanco_comparacion)
        {
          break;
        }
      }
  }
  digitalWrite(led1,LOW);
}


void motores(int motor_izq, int motor_der)
{
  if ( motor_izq >= 0 )  
  {
    digitalWrite(mi1,LOW);
    digitalWrite(mi2,HIGH); 
    analogWrite(pwmi,motor_izq); 
  }
  else
  {
    digitalWrite(mi1,HIGH); 
    digitalWrite(mi2,LOW);
    motor_izq = motor_izq*(-1); 
    analogWrite(pwmi,motor_izq);
  }

  if ( motor_der >= 0 ) //motor derecho
  {
    digitalWrite(md1,LOW);
    digitalWrite(md2,HIGH);
    analogWrite(pwmd,motor_der);
  }
  else
  {
    digitalWrite(md1,HIGH);
    digitalWrite(md2,LOW);
    motor_der= motor_der*(-1);
    analogWrite(pwmd,motor_der);
  }
}

void botones()
{
    boton1=digitalRead(btn2);
    boton2=digitalRead(btn1); ///boton izquierdo, derecho
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Nota: este programa esta utilizando la libreria modificada de este post Modificacion de libreria QTR, si estas usando la libreria sin modificar, que de hecho no funcionara con este codigo tendrás que descargarlo desde este link: https://mega.nz/#!CkMkiZhA!FMK4eJQVmOGZK9GZzfqSKRgEPOijTSkMmbNDUwbf5C0 en instalarlo nuevamente. 

Instalacion de Libreria QTR SENSORS:


Esquematicos de FK-BOT:

Ya que me estuvieron pidiendo esquemáticos por mucho tiempo, pues aqui las libero.
 He pasado muy buenos días diseñando este robot, que fue considerado en su momento como el más rapido, ya ha pasado los años y cumplio su mision ...

La mejor forma de agradecerme es que le des clic a los anuncios de la parte superior del blog (cosa que no te costara nada hacerlo) , asi me ayudaras mucho! Saludos amigos robotero!!!  😊😎🙌



Cifrado: !tBRwDXi3MO-D9U3xMqgBTw

Driver Sparkfun-Compatible(rojo): https://mega.nz/#F!Ok1jULzb!DFAwhpyvyMLxdrc3C_xedw
Cifrado: !DFAwhpyvyMLxdrc3C_xedw


PRUEBAS FINALES: 





Post Anterior  << Manejando sensores QTR8A y Driver

32 comentarios:

Este comentario ha sido eliminado por el autor.

uhmm, bueno lo volvere a subir.

MUY BUENAS AMIGO LO FELICITO POR SU TRABAJO Y DE ANTEMANO LE PIDO POR FAVOR ME AHYUDE
CON EL CIRCUITO PCB Y DIMENSIONES DE LA ESTRUCTURA...DESDE YA LE DOY MIS SINCEROS AGRADECIMIENTOS Y LE DESEO EL MAYOR DE LOS ÉXITOS EN SUS PROYECTOS SIGUIENTES....
GRACIAS......
SALUDOS......

Este comentario ha sido eliminado por el autor.

Muy util. Graciiias por el connteniddo!

Bacan un favor, cual es la funcion de los pulsadores? despues de tener listo todo, como se activa para que prenda los motores?

q pasa con los botones para q son cada uno

Hola buenas noches
Copie el programa y lo compile pero me envia varios errores:

sketch_apr22a:102: error: no matching function for call to 'QTRSensorsAnalog::readLine(unsigned int [8], int, int&, int&, int&, int&)'

position = qtra.readLine(sensorValues,QTR_EMITTERS_ON, linea, flanco_color, en_linea, ruido);


int readLine(unsigned int *sensor_values, unsigned char readMode = QTR_EMITTERS_ON, unsigned char white_line = 0);

^

C:\Program Files (x86)\Arduino\libraries\QTRSensors/QTRSensors.h:110:9: note: candidate expects 3 arguments, 6 provided

Utilizando biblioteca QTRSensors en carpeta: C:\Program Files (x86)\Arduino\libraries\QTRSensors (legacy)
exit status 1
no matching function for call to 'QTRSensorsAnalog::readLine(unsigned int [8], int, int&, int&, int&, int&)'

Parece que la mayoría tiene problemas al instalar la librería, estos días estaré subiendo un pequeño video

bro ya pase copie el codigo y compile y quedo super (Y)
una pregunta en cuanto a al parte física del circuito
estoy usando un arduino uno, y en los pines analogicos estan conectados 6 de los sensores
en el codigo los definí como 19 18 17 16 15 14 si esta bien?

Tengo una inquietud sobre el circuito en esas lineas rojas que va, ¿un regulador o es la salida del voltaje?

Este comentario ha sido eliminado por el autor.

Amigo el codigo completo esta configurado con los qtr8a o el c ?
Gracias por el aporte

Bien ,gracias por el aporte , con usted si se aprende ,pero y el codigo SIN la libreria Modificada,en donde esta.

para que sirven los botones?

en_linea A QUE SE REFIERE?

haha
en diseño del seguidor hay pines para el modulo bluethoo pero en el codigo no esta declarado los pines para poder controlarlo

donde puedo conseguir el pcb para imprimirlo o como me comunico con usted para comprarlo?


favor tu ayuda con esto mi seguidor no coje bien la curba derecha como hago para que coja bien la curba


if (position <=10) //si se salio por la parte derecha de la linea
{
while(true)
{
digitalWrite(led1,HIGH);
motores(-125,60);
qtra.read(sensorValues); //lectura en bruto de sensor
if ( sensorValues[0]=6990) //si se salio por la parte izquierda de la linea
{
while(true)
{
digitalWrite(led1,HIGH);
motores(60,-125);
qtra.read(sensorValues);
if (sensorValues[7]<flanco_comparacion || sensorValues[6]<flanco_comparacion|| sensorValues[5]<flanco_comparacion || sensorValues[4]<flanco_comparacion || sensorValues[3]<flanco_comparacion || sensorValues[2]<flanco_comparacion || sensorValues[1]<flanco_comparacion|| sensorValues[0]<flanco_comparacion)
{

No podrías subir el archivo del programa porfa

Hola, me podrias indicar como seleccionaste los valores de KI,KP y KD, gracias

buen dia
pregunta en un esquema realizado antes usas conexiones para el qtr 6n analogos y dos digitales y en otro esquema usas todas las conexiones análogas cual es la diferencia y en que se altera???

Hola amigo, una duda, para que sirven los 2 botones en Tx y Rx

Los botones funcionan para arranque del seguidor. Lo que yo hice fue declarar otro pin por comodidad
const int BTN = 10;
Dentro de Void setup coloque lo siguiente para arrancar el seguidor despues de haber calibrado.

while (true) {
delay(100);
if (digitalRead(BTN) == HIGH) { //si se presiona boton
delay(20);
digitalWrite(LED,HIGH);
delay(100);
digitalWrite(LED, LOW); //indicamos que se presiono boton
//HABILITAMOS EL PUENTE H PARA EL FUNCIONAMIENTO DEL MISMO
//INICIAMOS EL ARRANQUE
digitalWrite(STANDBY, HIGH);
break; //saltamos hacia el bucle principal
}
}

HOla, tengo una duda en la sintaxis del código, ummm es en la parte de la librería, para ser más exacto, declarando las variables, proporcional, integral y lo demás, otra duda es, a que te refieres el ruido?

Como se que ya esta calibrado?

hola buen dia tengo un problema con el codigo me marca error

Arduino:1.8.18 (Windows 10), Tarjeta:"Arduino Uno"





















corredor__LINEAS_PID:22:106: error: no matching function for call to 'QTRSensors::QTRSensors(unsigned char [8], int, int, int)'

QTRSensors qtra((unsigned char[]) {7, 6, 5, 4, 3, 2,1,0},NUM_SENSORS, NUM_SAMPLES_PER_SENSOR, EMITTER_PIN);

^

In file included from C:\Users\Angy\Desktop\LineaNegra8S\corredor__LINEAS_PID\corredor__LINEAS_PID.ino:1:0:

C:\Program Files\arduino-1.8.18\libraries\QTRSensors-4.0.0/QTRSensors.h:85:5: note: candidate: constexpr QTRSensors::QTRSensors()

QTRSensors() = default;

^~~~~~~~~~

C:\Program Files\arduino-1.8.18\libraries\QTRSensors-4.0.0/QTRSensors.h:85:5: note: candidate expects 0 arguments, 4 provided

C:\Program Files\arduino-1.8.18\libraries\QTRSensors-4.0.0/QTRSensors.h:81:7: note: candidate: constexpr QTRSensors::QTRSensors(const QTRSensors&)

class QTRSensors

^~~~~~~~~~

C:\Program Files\arduino-1.8.18\libraries\QTRSensors-4.0.0/QTRSensors.h:81:7: note: candidate expects 1 argument, 4 provided

C:\Users\Angy\Desktop\LineaNegra8S\corredor__LINEAS_PID\corredor__LINEAS_PID.ino: In function 'void pid(int, int, float, float, float)':

corredor__LINEAS_PID:102:20: error: 'class QTRSensors' has no member named 'readLine'; did you mean 'read'?

position = qtra.readLine(sensorValues,QTR_EMITTERS_ON, linea, flanco_color, en_linea, ruido);

^~~~~~~~

read

corredor__LINEAS_PID:102:42: error: 'QTR_EMITTERS_ON' was not declared in this scope

position = qtra.readLine(sensorValues,QTR_EMITTERS_ON, linea, flanco_color, en_linea, ruido);

^~~~~~~~~~~~~~~

C:\Users\Angy\Desktop\LineaNegra8S\corredor__LINEAS_PID\corredor__LINEAS_PID.ino:102:42: note: suggested alternative: 'EMITTER_PIN'

position = qtra.readLine(sensorValues,QTR_EMITTERS_ON, linea, flanco_color, en_linea, ruido);

^~~~~~~~~~~~~~~

EMITTER_PIN

exit status 1

no matching function for call to 'QTRSensors::QTRSensors(unsigned char [8], int, int, int)'



Este informe podría contener más información con
"Mostrar salida detallada durante la compilación"
opción habilitada en Archivo -> Preferencias.

Publicar un comentario