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
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
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.
Post Anterior << Manejando sensores QTR8A y Driver
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!!! 😊😎🙌
Driver Pololu :https://mega.nz/#F!GkckwITB!tBRwDXi3MO-D9U3xMqgBTw
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:
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......
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?
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
Y la lista de materiales ?
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?
Oi eu sou a sopa de macaco
es a doble cara la pista?
a alguien le funciono
ola amor te amo
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