viernes, 26 de diciembre de 2014

Bootloader usb para Microcontroladores PIC 18f2550, 18f4550

Bootoader usb para uC 18f2550 y  18f4550



Un bootloader es un programa que reside dentro de la memoria del microcontrolador en el cual nos permitira reprogramar el microcontrolador sin necesidad de utilizar un grabador externo. 
Para esto, es necesario programar el microcontrolador por los medios convencionales ( utilizando un programador externo),  cargandole el hexagesimal del bootloader.
Una  ves hecho esto, nuestro microcontrolador esta listo para ser utilizado si necesidad  de utilizar un programador externo. 
Pero antes de todo esto se preguntaran. Como cargo entonces mis programas al microcontrolador?
Pues es necesario utilizar un medio como comunicacion con el pc, y  nuestro microcontrolador cuenta con ese medio, que es el USB.  
El bootloader ya esta esta programado  para trabajar con ese modulo USB de nuestro PIC,  lo unico que nos quedaria es realizar nuestro circuito para  que nuestro microcontrolador pueda funcionar correctamente


 

En la imagen se puede apreciar que existen 2 botones, 1 que es para el reset y el otro para el entrar al modo bootloader.Para entrar al modo bootloader, es necesario reiniciar el microcontrolador y seguidamente presionar el boton "boot mode" hecho esto, el microcontrolador esta listo para ser programado.

Como la arquitectura del pic 18f4550 es igual al del 18f2550, salvo que el 18f4550 tiene mas pines, este bootloader es funcional para estos 2 tipos de microcontroladores.
La ventaja de este bootloader, es que se puede integrar  con el CCS C compiler, de esta manera se nos hara mucho mas facil la carga de nuestros programas.



Dejo el link de Descarga con los archivos y las instrucciones de instalacion, Saludos!!

Algorirmo para manejar "motores dc" en ARDUINO , PIC, etc

Algoritmo para manejar Motores  DC


En este post les traigo una manera facil y sencilla de manejar motores dc con tan solo llamar una funcion. Podemos manejar desde un solo  motor hasta el numero de motores que queramos, utilizando   solo un parametro con su respectivo signo, esto para darle el  set duty del pwm, para asi variar su  respectiva velocidad y tambien la direccion. 

Esto nos permitira manejar con una mayor eficiencia los motores, y claro esta tambien ahorranos muchas lineas de codigo. Es importante destacar que sea cual sea el microcontrolador que usemos, este tiene que contar con los suficentes pines de pwm, es decir, si  vamos a manejar 2 motores, el micro que usemos debe disponer de 2  pines pwm, ademas del driver de motor que utilicemos  este debera contar con los suficientes canales . 

empezaremos por crear nuestra funcion para el manejo de un solo motor, luego extenderemos para la cantidad de motores que querramos

Crearemos la funcion en el que se le dara un paramatro que contendra signo, el signo nos servira para controlar la direccion ( positivo hacia adelante,  negativo hacia atras), por defecto utilizaremo un pwm de 8 bits, arduino y pic utilizan esta resolucion (0-255) 
Para una manera didactica  haremos un seudo codigo, esto para entender la logica, luego implementaremos un algoritmo funcional.


void motores( float pwm)  //funcion con parametro  tipo float llamado pwm, no devuelve valor  
{
  int v1                              / / crearemos y utilizaremos  variable auxiliare  para menejar signos
 si ( pwm >=  0)                     //si el signo del positivo, entonces el motor ira hacia adelante 
   {
      motores_hacia_adelante  //activamos los pines  de driver para mandar motor  haciaadelante
        v1  =  pwm                        //  asignamos el valor de pwm a la variable auxiliar
    }

  si( pwm < 0 )                 //si  el valor  negativo  entonces  mandaremos el motor hacia atras
   {
       motores_hacia_atras     // activaremos pines de driver para mandar motores hacia atras
        v1 = pwm * (-1)        //cambiamos el signo de variable  para asi dar la salida  pwm correcta
    }
microcontrolador_pin_pwm1(v1);//damos el valor de  salida pwm correspondientealmicrocontrolador
}

y si lo llamamos en un bucle quedaria algo asi:

bucle
{
       motores( 100)    // entonces el motor ira hacia adelante con un valor de pwm de 100
       retardo(1000)  // hacemos u retardo de un segundo
       motores( -120)    // entonces el motor ira hacia atras con un valor de pwm de 120
      retardo(1000)   // hacemos u retardo de un segundo
}

Es asi que de una manera practica y facil  podemos manejar el  motor, lo que comunmente era la programacion de muchas lineas de codigopara cada movimieno y direccion, ahora nos basta con crear una funcion  que sera reutilizado en cualquier linea de nuestra programacion

Ahora Crearemos  un ejemplo funcional en arduino, bueno ya que la logica de control esta clara, ahora nos preocuparemos por los pines que utilizaremos del arduino

#define motor_1_a    3
#define motor_1_r    4
#define motor_2_a    5
#define motor_2_r    6
#define pin_pwm1     9
#define pin_pwm2     10
void setup()
{
  delay(500);
  pinMode(motor_1_a,  OUTPUT); 
  pinMode(motor_1_r,  OUTPUT);
  pinMode(motor_2_a,  OUTPUT);
  pinMode(motor_2_r,  OUTPUT);
  pinMode(pin_pwm1,  OUTPUT);
  pinMode(pin_pwm2,  OUTPUT);
}

void loop()

{
 motores (150, 150);
 delay(1000);
 motores(-140, -140);
 delay(1000);
 motores(130, -200);
 delay(1000);
 motores(-255, 0);
 delay(1000);
}

void motores(float pwm1,  float pwm2)

{
   int v1, v2;
   if(pwm1 >= 0) //para el motor 1
   {
     digitalWrite(motor_1_a, HIGH);
     digitalWrite(motor_1_r, LOW);
     v1 = pwm1;
   }
   else if(pwm1 < 0)
   {  
     digitalWrite(motor_1_a, LOW);
     digitalWrite(motor_1_r, HIGH);
     v1 = pwm1 * (-1);
   }

   //para el motor 2

   if(pwm2 >= 0)
   {
     digitalWrite(motor_2_a, HIGH);
     digitalWrite(motor_2_r, LOW);
     v2 = pwm2;
   }
   else if(pwm2<0)
   {
     digitalWrite(motor_2_a, LOW);
     digitalWrite(motor_2_r, HIGH);
     v2 = pwm2 * (-1);
   }
analogWrite(pin_pwm1, v1);
analogWrite(pin_pwm2, v2);
}

Ahora un ejemplo para PIC utilizando  el compilador CCS C vamos a utilizar el pic 16f877a, en si este ejemplo es valido para todas las familias de PIC de gama media y alta, asi que si deseamos utilizar el codigo con otro pic, pues solamente cambiamos los encabezados de configuracion, fuses, y claro esta los pines que diponemos para el pic.  

#include <16F877a.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP,PUT,NOBROWNOUT
#use delay(clock=20000000)
#use standard_io(B)

#define motor_1_a  pin_b0

#define motor_1_r  pin_b1
#define motor_2_a  pin_b2
#define motor_2_r  pin_b3
#define pin_pwm1   pin_c1
#define pin_pwm2   pin_c2

//prototipo para funcion motor

void motores(signed int16 izquierdo,signed int16 derecho); 

void main()

{
   //configuracion del pwm
   setup_ccp1 (CCP_PWM);
   setup_ccp2 (CCP_PWM);
   setup_timer_2 (T2_DIV_BY_1, 255, 1);
   set_pwm1_duty (0);
   set_pwm2_duty (0);
   
   while(true)
   {
      motores(100,100);
   }

}


void motores(signed int16 izquierdo, signed int16 derecho)

{
   int v1=0,v2=0; //variable auxiliar 
   if(derecho >0)
   {
      output_high(motor_1_a);
      output_low(motor_1_r);
      v2=derecho;
   }
    if(derecho <0)
   {
      output_low(motor_1_a);
      output_high(motor_1_r);
      v2=derecho*-1;
   }
     if(derecho==0)
   {
      output_high(motor_1_a);
      output_high(motor_1_r);
      v2=0;
   }
   
   
     if(izquierdo >0)
   {
      output_high(motor_2_a);
      output_low(motor_2_r);
      v1=izquierdo;
   }
   if(izquierdo <0)
   {
      output_low(motor_2_a);
      output_high(motor_2_r);
      v1=izquierdo*-1;
   }
    if(izquierdo==0)
   {
      output_high(motor_2_a);
      output_high(motor_2_r);
       v1=0;
   }
   set_pwm1_duty (v1);
   set_pwm2_duty (v2);
}

jueves, 11 de diciembre de 2014

Rastreo "PID" en seguidor de lineas con microcontrolador PIC utilizando "Sensores digitales"










Muchas veces creemos que para lograr implementar un algoritmo pid para un robot seguidor de lineas es necesario contar con sensores  que nos den valores analogicos. En realidad esta afirmacion es del todo cierta,  pues obteniendo valores analogicos se puede ver las pequeñas variaciones que logran  percibir estos  sensores (es posible apreciar que tan oscura es una superficie) esto con respecto a sensores cny, tcr5000 o qrd114.
Pero tambien es posible  implementar un algoritmo pid con valores discretos (0 y 1), a lo que voy es que al pid solo le interesa saber el grado de error, para asi aplicar una accion correctora, ya sea utilizando valores analogicos o discretos.
Las ventajas de utilizar valores discretos es que tendriamos mayor inmunidad al ruido, que generalmente se presenta en los modos analogicos, ademas de un mayor manejo de los valores sensados pues solo tenemos 0 y 1, a comparacion de lo analogico, que van desde valores de 0 a 1024 ( en caso utilzarlos con un modulo adc de 10 bits en un uC)
La mayor desventaja al utilizar los sensores como digitales , es que previamente utilizariamos una etapa de acondicionamiento de señales (se pueden utilizar op amp como comparadores) para obtener valores discretos. Tambien es la cuestion de resolucion, no se lograria percibir los pequeños cambios o variaciones que si lo logran hacer los sensores en modo analogico, aca solo veriamos negro o blanco.


En la imagen anterior podemos visualizar mucho mejor la idea de sensado digital. Es posible hacer  una ponderacion de todos los valores de los sensores para asi obtener un valor de pocicion relativa, estos es usualmente utilizado con un sensado en modo analogico. Pero a mi parecer la manera mas practica de obtener esa posicion  es con simples "if", Pero en este caso lo vamos a ver desde el punto de vista del pid (nos interesa el error).

domingo, 7 de diciembre de 2014

INTRODUCCION A LA ELECTRONICA BASICA Y DIGITAL

2.- INTRODUCCION A LA ELECTRONICA BASICA Y DIGITAL


-> TIPOS DE CORRIENTE

Corriente Alterna (CA - AC):
Es aquella corriente que varia continuamente  el sentido y la magnitud ciclicamente (no tiene polarida). Es utilizadp en las redes electricas domesticas generalmente de 220 Volts a 60 Hz (60 variaciones por segundo)..



Corriente Continua (CC-DC):

Es aquella corriente que va en un solo sentido de polo "negativo" al "positivo",  Es la que produce las pilas y baterias recargables.


-> TIPOS DE SEÑALES ELECTRÓNICAS

Señal Cuadrada o Digital 
Es una onda alterna que varia en entre dos valores extremos, sin pasar por los valores intermedios, al contrario de la señal triangular o senoidal. Es muy utilzada en la electronica digital pues puede ser interpretada como "1" o "0" , "Verdadero" o "Falso" , "High" o "LOW"


Señal Analogica
Es aquella señal que varia con el tiempo y presenta multiples valores, esta presente en la naturaleza, como el sonido, latido corazon,  luz, ondas de radio, etc.



-> LEY DE OHM 
Establece la relacion entre el Voltaje  (diferencia de potencial en "Volts".),  Intensidad (Coulomb por segundo en "Amps" y Resistencia (en "Ohms") en un circuito electrico
                                 
                                               V = I x R   ;     I = V / R    ;    R = V / I
Mas claro, ni  el agua !!


-> POTENCIA ELECRICA

Potencia es la velocidad a la que se consume la energía (energia es la capacidad que tiene un mecanismo para realizar  trabajo). Si la energía fuese un líquido.  La potencia se mide en joule por segundo (J/seg) y se representa con la letra “P”.

Un J/seg equivale a 1 watt (W), por tanto, cuando se consume 1 joule de potencia en un segundo, estamos gastando o consumiendo 1 watt de energía eléctrica.

La unidad de medida de la potencia eléctrica “P” es el “watt”, y se representa con la letra “W”.

                                        P= V x I      ;     P =  (I^2)  x  R     ;    P = (V^2) / R
                                                      

-> DISPOSITIVOS ELECTRONICOS BASICOS

Resistencia



Diodo
Dispositvo electronico que conduce corriente electrica en un solo sentido. Si se le aplica un voltaje inverso, este se comportara como un circuito abierto.

Diodo Led 
Es un diodo que emite luz.
Capacitores o Condensadores
Dispositivo electronico que almacena energia en forma de campo electrico


Potenciometro 
Resistencia que puede variar su valor, se puede utilizar como divisor de voltaje o resistencia variable.

              VD= (V x R2) /  (R2 + R1)

Transistor
Es un dispositivo electrónico semiconductor utilizado para producir una señal de salida en respuesta a otra señal de entrada. Cumple funciones de amplificador, oscilador , conmutador o rectificador
Relay

Es un dispositivo electromecánico. Funciona como un interruptor controlado por un circuito eléctrico en el que, por medio de una bobina y un electroimán , se acciona un juego de uno o varios contactos que permiten abrir o cerrar otros .
El relé es capaz de controlar un circuito de salida de mayor potencia que el de entrada.

Puente H:
es un circuito electrónico que permite a un motor eléctrico DC girar en ambos sentidos, avance y retroceso.
L293B o l293D
Es un circuito integrado que contiene un doble puente H, muy utilizado en conjunto a un microntrolador para poder manejar motores suministra hasta 1,5 amperios de corriete continua .
Opam LM358
Se trata de un dispositivo electrónico (normalmente se presenta como circuito integrado) que tiene dos entradas y una salida. La salida es la diferencia de las dos entradas multiplicada por un factor (G) (ganancia): Vout = G·(V+ − V−)

Opam lm358 Modo comparador: convierte las señales analógicas a digitales, y se puede variar el flaco de comparacion.
Regulador de voltaje 7805: 
Se trata de un dispositivo que conviete voltajes desde 7 a 30 voltios a 5 voltios regulados de corriente continua, generalmente utilizado en fuente de poder.




sábado, 6 de diciembre de 2014

CURSO BASICO PIC EN C


CURSO DE PROGRAMACION PIC






                                                                        
                                                                          AVISO!

Este curso  esta dirigido para todos  aquellos que recién se estan adentrando  a este mundo fascinante que es la de "programacion de microcontroladores pics" . Es por eso que  prepare este material pensando  en el aprendiz,   tratando    hacer el curso  lo mas amenamente posible   entendible, sin muchas cosas engorrosas, pero  bueno, llendo al grano...si algunos termino o conceptos se  hacen difícil de comprender no te compliques, tomate el tiempo necesario para entender. Puedes preguntarme, yo encantado responderé tus dudas, o  derrepente puedes  darme algunas sugerencias ,  las tomare en cuenta. Al fin y al acabo el objetivo de este Sitio es aprender tanto tu como yo...

Bueno a todo esto les digo que si estan decididos a aprender por si solos "autodidactas" y estan buscando informacion de internet, foros, etc. Les digo que yo también pase por lo mismo  y en sintesis de todo eso he hecho este material reuniendo toda esa valiosa informacion en este espacio, asique saquenle todo el provecho... como alguna ves un profesor de la universidad me dijo: <<No le mendigues a nadie conocimientos, saca tu tus propias conclusiones, y si no sabes alguna cosa es mejor que las investigues tu por tu propia cuenta, y si las encontraste, pues vale chico (el profesor  era de cuba) enseñalas a todos>>  

El lenguaje en el que vamos a aprender sera el "C", con el compilador CCS C COMPILER o mas conocido como PIC C , trabajaremos con el microcontrolador PIC16F628A  dado que es un pic muy versatil y economico,  al manejar a este pic tambien  seremos capacaes de manejar otras familias de pics como los 12fxxx y los de gama alta 18fxxx, esto lo veremos mas adelante durante el transcurso del curso.  Tambien vamos a utilizar el simulador ISIS PROTEUS. Si todovia no manejas este simulador pues te sugiero  que le des una mirada a el turorial de isis en el link:


viernes, 5 de diciembre de 2014

Robot Velocista de competencia - Parte III : Algoritmo Pid - Programacion Robot velocista

Algoritmo Pid - Programacion Robot velocista


->PID

El PID (control proporcional, integral y derivativo) es un mecanismo de control por realimentacion que calcula la desviacion o error entre un valor medido y el valor que se quiere obtener (set point, target position  o punto de consigna), para aplicar una acción correctora que ajuste el proceso.

En el caso del robot velocista, el controlador PID ,(que es una rutina basada matematicamente), procesara los datos del sensor, y lo utiliza para controlar la dirección (velocidad de cada motor), para de esta forma  mantenerlo  en curso.






- Error - Llamamos a la diferencia entre la posición objetivo y la posición medida del error. (que tan lejos del punto de consigna se encuentra el sensor, en nuestro caso el objetivo es tener  los sensores centrados)




-Set point o Target Position - Cuando el error es  0 (cero). En el caso del robot velocista es 3500, la idea es siempre mantenerlo en la la linea, o lo que es el caso de los sensores,  mantenerlo centrado y asi no  se llegue a salir de la linea.
->PARAMETROS:

-Proporcional: Es la respuesta  al error que se tiene que entregar de manera inmediata, es decir, si nos encontramos en el centro de la linea, los motores , tendran en respuesta una velocidad de igual  valor, si nos alejamos del centro, uno de los motores reducira su velocidad y el otro aumentara.
                                       Proporcional=(posición) -punto_consigna 

-Integral: La integral es la sumatoria de los errores acumulados, tiene como propósito el disminuir y eliminar el error en estado estacionario provocado por el modo proporcional, en otras palabras, si el robot velocista se encuentra mucho tiempo alejado del centro (ocurre muchas veces cuando se encuentra en curvas), la accion integral se ira acumulando e ira disminuyendo el error hasta llegar al punto de consigna,
                                     Integral=Integral + proporcional_pasado

-Derivativo: Es la derivada del error, su funcion es mantener el error al minimo, corrigiendolo proporcionalmente con la mismo velocidad que se produce, de esta manera evita que el error se incremente, en otra palabra, anticipara la accion evitando asi las oscilaciones excesivas.
                                    Derivativo=proporcional-proporcional_pasado

->CONSTANTES: 

Factor (Kp) - Es un valor constante utilizado para aumentar o reducir el impacto de Proporcional. Si el valor es excesivo, el robot tendera responder inestablemente, oscilando  excesivamente. Si el valor es muy pequeño, el robot respondera muy lentamente,  tendiendo a salirse de las curvas

Factor (Ki) - Es un valor constante utilizado para aumentar o reducir el impacto de la Integral, El valor excesivo de este provocara oscilaciones excesivas, Un valor demasiado bajo no causara impacto alguno.

Factor (Kd) - Es un valor constante utilizado para aumentar o reducir el impacto de la Derivada. Un valor excesivo provocara  una sobre amortiguacion.  provocando inestabilidad.

                     Salida_pwm = ( proporcional * Kp ) + ( derivativo * Kd ) + (integral*Ki);


->SINTONIZACION PID

Aqui viene el reto, la sintonizacion pid, es aqui donde se tendra que buscar las constantes que correspondan a las caracteristicas fisicas del robot, la forma mas facil de hacerlo es por ensayo y error, hasta obtener el valor deseado. Aqui hay unos pasos que ayudaran mucho a buscar esas constantes:
  1. Comience con Kp, Ki y Kd igualando 0 y trabajar con Kp primero. Pruebe  establecer Kp a un valor de 1 y observar el robot. El objetivo es conseguir que el robot siga la línea, incluso si es muy inestable. Si el robot llega más allá y pierde la línea, reducir el valor de Kp. Si el robot no puede navegar por una vez, o parece lenta, aumente el valor Kp.
  2. Una vez que el robot es capaz de seguir un poco la línea, asignar un valor de 1 a Kd .Intente aumentar este valor hasta que vea menos oscilaciones.
  3. Una vez que el robot es bastante estable en la línea siguiente, asigne un valor de 0,5 a 1,0 a Ki. Si el valor de Ki es demasiado alta, el robot se sacudirá izquierda y derecha rápidamente. Si es demasiado baja, no se vera ninguna diferencia perceptible. El Integral es acumulativo por lo tanto  el valor Ki tiene un impacto significativo.  puede terminar  ajustando por 0,01 incrementos.
  4. Una vez que el robot está siguiendo la línea con una buena precisión, se puede aumentar la velocidad y ver si todavía es capaz de seguir la línea. La velocidad afecta el controlador PID y requerirá resintonizar como los cambios de velocidad.
->ALGORITMO EN ARDUINO


#include <QTRSensors.h>
/////////////////////////////////////////////////////////////////////////////////////
//*************  Programa realizado por MARCO A. CABALLERO MORENO***************   //
// Solo para fines educativos   
// robot velocista mini FK BOT  V 2.0                                            //
// micro motores pololu MP 10:1, sensores qtr 8rc, driver drv8833, arduino nano    //
//                                     05/12/2014                  
// ACTUALIZADO 29/3/2015            
/////////////////////////////////////////////////////////////////////////////////////

#define NUM_SENSORS   8     //numero de sensores usados
#define TIMEOUT       2000  // tiempo de espera para dar resultado en uS
#define EMITTER_PIN   6     //pin led on
///////////////pines arduino a utilizar/////////////////////
#define led1          13 
#define led2          4  
#define mot_i         7
#define mot_d         8
#define sensores      6
#define boton_1       2  //pin para boton
#define pin_pwm_i     9
#define pin_pwm_d     10

QTRSensorsRC qtrrc((unsigned char[]) {19, 18, 17, 16,15,14,11,12}
,NUM_SENSORS, TIMEOUT, EMITTER_PIN);

//variables para almacenar valores de sensores y posicion
unsigned int sensorValues[NUM_SENSORS];
unsigned int position=0;

/// variables para el pid
int  derivativo=0, proporcional=0, integral=0; //parametros
int  salida_pwm=0, proporcional_pasado=0;

///////////////AQUI CAMBIEREMOS LOS PARAMETROS DE NUESTRO ROBOT!!!!!!!!!!!!!!!
int velocidad=120;              //variable para la velocidad, el maximo es 255
float Kp=0.18, Kd=4, Ki=0.001;  //constantes
//variable para escoger el tipo de linea
int linea=0;                    //  0 para lineas negra, 1 para lineas blancas

void setup()
{
 delay(800);
 pinMode(mot_i, OUTPUT);//pin de direccion motor izquierdo
 pinMode(mot_d, OUTPUT);//pin de direccion motor derecho
 pinMode(led1, OUTPUT); //led1
 pinMode(led2, OUTPUT); //led2
 pinMode(boton_1, INPUT); //boton 1 como pull up
        
 for (int i = 0; i <40; i++)  //calibracion durante 2.5 segundos,
 {                                 //para calibrar es necesario colocar los sensores sobre la superficie negra y luego 
  digitalWrite(led1, HIGH);  //la blanca
  delay(20);
  qtrrc.calibrate();    //funcion para calibrar sensores   
  digitalWrite(led1, LOW);  
  delay(20);
 }
digitalWrite(led1, LOW); //apagar sensores para indicar fin de calibracion 
delay(400); 
digitalWrite(led2,HIGH); //encender led 2 para indicar la
while(true)
{
    int x=digitalRead(boton_1); //leemos y guardamos el valor
                                      // del boton en variable x
    delay(100);
    if(x==0) //si se presiona boton 
    {
        digitalWrite(led2,LOW); //indicamos que se presiono boton
        digitalWrite(led1,HIGH); //encendiendo led 1
        delay(100);
        break; //saltamos hacia el bucle principal
    }
}
}       


void loop()
{

 //pid(0, 120, 0.18, 0.001, 4 );
  pid(linea,velocidad,Kp,Ki,Kd); //funcion para algoritmo pid 
                                 //primer parametro: 0 para lineas negras, tipo 1 para lineas blancas
                                 //segundo parametro: velocidad pwm de 0 a 255
                                 //tercer parametro: constante para accion proporcional
                                 //cuarto parametro: constante para accion integral
                                 //quinto parametro: constante para accion derivativa
  //frenos_contorno(0,700);
  frenos_contorno(linea,700); //funcion para frenado en curvas tipo 
                              //primer parametro :0 para lineas negras, tipo 1 para lineas blancas
                              //segundo parametro:flanco de comparación va desde 0 hasta 1000 , esto para ver 
}

////////funciones para el control del robot////
 void pid(int linea, int velocidad, float Kp, float Ki, float Kd)
{
  position = qtrrc.readLine(sensorValues, QTR_EMITTERS_ON, linea); //0 para linea negra, 1 para linea blanca
  proporcional = (position) - 3500; // set point es 3500, asi obtenemos el error
  integral=integral + proporcional_pasado; //obteniendo integral
  derivativo = (proporcional - proporcional_pasado); //obteniedo el derivativo
  if (integral>1000) integral=1000; //limitamos la integral para no causar problemas
  if (integral<-1000) integral=-1000;
  salida_pwm =( proporcional * Kp ) + ( derivativo * Kd )+(integral*Ki);
  
  if (  salida_pwm > velocidad )  salida_pwm = velocidad; //limitamos la salida de pwm
  if ( salida_pwm < -velocidad )  salida_pwm = -velocidad;
  
  if (salida_pwm < 0)
 {
  motores(velocidad+salida_pwm, velocidad);
 }
 if (salida_pwm >0)
 {
  motores(velocidad, velocidad-salida_pwm);
 }

 proporcional_pasado = proporcional;  
}

//funcion para control de motores
void motores(int motor_izq, int motor_der)
{
  if ( motor_izq >= 0 )  //motor izquierdo
 {
  digitalWrite(mot_i,HIGH); // con high avanza
  analogWrite(pin_pwm_i,255-motor_izq); //se controla de manera
                                        //inversa para mayor control
 }
 else
 {
  digitalWrite(mot_i,LOW); //con low retrocede
  motor_izq = motor_izq*(-1); //cambio de signo
  analogWrite(pin_pwm_i,motor_izq); 
 }

  if ( motor_der >= 0 ) //motor derecho
 {
  digitalWrite(mot_d,HIGH);
  analogWrite(pin_pwm_d,255-motor_der);
 }
 else
 {
  digitalWrite(mot_d,LOW);
  motor_der= motor_der*(-1);
  analogWrite(pin_pwm_d,motor_der);
 }

  
}

void frenos_contorno(int tipo,int flanco_comparacion)
{
  
if(tipo==0)
{
  if(position<=50) //si se salio por la parte derecha de la linea
 {
  motores(-80,90); //debido a la inercia, el motor 
                                  //tendera a seguri girando
                                  //por eso le damos para atras , para que frene
                                 // lo mas rapido posible 
  while(true)  
  {
   qtrrc.read(sensorValues); //lectura en bruto de sensor   
   if( sensorValues[0]>flanco_comparacion || sensorValues[1]>flanco_comparacion ) 
   //asegurar que esta en linea
   {
    break;
   } 
  }
 }

 if (position>=6550) //si se salio por la parte izquierda de la linea
 { 
  motores(90,-80);
  while(true)
  {
   qtrrc.read(sensorValues);
   if(sensorValues[7]>flanco_comparacion || sensorValues[6]>flanco_comparacion )
   {
    break;
   }  
  }
 }
}

if(tipo==1) //para linea blanca con fondo negro
{
 if(position<=50) //si se salio por la parte derecha de la linea
 {
  motores(-80,90); //debido a la inercia el motor 
                   //tendera a seguri girando
                   //por eso le damos para atras  
                   //para que frene lo mas rapido posible 
  while(true)  
  {
   qtrrc.read(sensorValues); //lectura en bruto de sensor
   if(sensorValues[0]<flanco_comparacion || sensorValues[1]<flanco_comparacion )   //asegurar que esta en linea
   {
    break;
   }
  }
 }

 if(position>=6550) //si se salio por la parte izquierda de la linea
 { 
  motores(90,-80);
  while(true)
  {
   qtrrc.read(sensorValues);
   if(sensorValues[7]<flanco_comparacion || sensorValues[6]<flanco_comparacion)
   {
    break;
   }  
  }
 }
}
}


ESQUEMA ROBOT VELOCISTA:





Esquemáticos PCB Mini FK-BOT 1.0:

Ya que me estuvieron pidiendo esquemáticos por mucho tiempo, pues aqui las libero.
He pasado muy buenos días diseñando este robot (la primera versión Mini FK-BOT 1.0), que fue considerado en su momento como el más rápido y que con el he ganado los concursos mas importantes del pais, 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!!!  😊😎🙌



Clave Cifrado: !ErZkc0Pn38XY4eUiP7X7Dw









Video por ADKITS-PERU





Siguiente Post>> MODIFICACION LIBRERIA "QTR SENSORS" PARA MEJOR SENSADO - I Parte

Anterior post<< Robot Velocista de competencia: Utilizando la libreria QTR SENSORS



miércoles, 3 de diciembre de 2014

Robot Velocista de Competencia - Parte II: Utilizando la libreria de sensores QTR SENSORS

Utilizando la librería "QTRSensors"




Como les mencione en el post anterior ("Materiales"), los sensores QTR8RC necesitan de  lineas de E/S digitales para su funcionamiento. No es necesario usarlos exclusivamente con  con pines analógicos, aunque la mayoría de los pines analógicos de un microcontrolador también pueden ser configurados como digitales, en comparación  con los QTR8A, que si utilizan entradas exclusivamente analógicas (Esa es la ventaja  de los QTR8RC de poder ser  usados en pines digitales).

Hay que tener en cuenta que los QTR8RC no funcionan de manera analógica, tampoco de manera completamente digital como se piensa a primer momento (no te va dar "1" y "0" si los utilizas de manera directa), su funcionamiento se puede decir que es una combinación de analógico y digital. Juega con la carga y descarga de el condensador ubicado en el colector del foto-transistor de cada sensor, de esta manera se puede hacer una medición del tiempo de carga, y pues para tal tarea  no es necesario  un pin analógico, solo basta con uno digital y la librería hará el trabajo de obtener esos tiempos y convertirlos en una medición cuasi analógica. si quieres ahondar mas en su funcionamiento puedes visitar este link: https://www.pololu.com/docs/0J13/all

Si quizás no puedes comprar este modulo directamente de  Pololu, pues siempre esta la opción de diseñar nuestro propio circuito  del sensor , varios amigos mios me comentaron que se han diseñado sus propios sensores basandose en el esquema de sensor pololu, los sensores pueden variar, pueden ser desde utilizar un cny70 o tcr5000, no necesariamente el que  usa en el modulos qtr8rc (que son los qrd1114), asi que no existen excusas!!

 El transistor mosfet , puede ser facilmente remplazado por un transistor 2n2222a, que es untransistor npn muy común y facil de encontrar.
Los diodos emisores del sensor estan de 2 en 2 con una resitencia de 47 y seguido de otros 2 dos resistores en paralelos de 47 ohms ( usados para el bypass, pero se puede eliminar esta etapa, con tan solo colocar una resistencia de 100 ohms ). y claro cada diodo emisor esta con su respectivo fototransistor (8 en total).


La secuencia tipica  estandar para la lectura de un sensor con estas características es la siguiente:

1. Encender los LEDs IR (opcional).
2. Establecer Un pin  como  salida y hacer un HIGH o "1" logico
3. Deje por lo menos 10us que el condensador se cargue.
4. Hacer el pin  como entrada (alta impedancia).
5. Mida el tiempo de la descomposición de la tension en el pin hasta que sea 0
6. Apague LEDs IR (opcional).
Estos pasos normalmente se pueden ejecutar en paralelo en varias líneas de E / S.
Esto lo hace de manera automatica la libreria <QTRSensors.h>

- >Instalando La biblioteca

Link para descargar la biblioteca:
QTRsensors

Ya descargada la libreria, lo que ahora hay que hacer es descomprimir el archivo y copiar la carpeta "QTRSensors". Luego ir Al directorio donde esta la carpeta del programa   "Arduino " :
arduino-1.0.5 / libraries ... luego pegar ahi la Carpeta "QTRSensors", y eso seria todo , ahora si tenemos disponible la libreria de los sensores
o si tienes problemas  puedes seguir este tutorial: http://www.prometec.net/librerias/

-> Disposición de los pines a 
utilizar:

GND: tierra "-"
Vcc: Alimentacion de 5 volts "+"
Led on: es un "Switch" que enciende y apaga los leds infrarojos de cada uno de los sensores, de manera predeterminada esta encendido "High" , para apagar se necesita dar un estado  digital "Low"
pines 1,2...7,8:   Son los respectivos pines de para la lectura de cada sensor.
3.3v Bypass: Utilizar si es que se requiere alimentar con 3.3v. los sensores, por defecto se alimenta con 5 v. Es mejor no utilizarlo.

Previamente es necesario soldar los espadines para una correcta manipulación de los sensores.


->Primeros pasos para utilización de los sensores
Abrimos  el Ide de Arduino y comprobamos que este disponible la librería



Para Comprobar el funcionamiento de nuestros sensores,  vamos a  abrir un ejemplo que nos trae la libreria, seleccionamos "QTRRCExample"

*Mi robot velocista utiliza estos pines  de arduino para los sensores:
A5, A4, A3, A2, A2, A1, A0, D11, D12, que en valor numérico serian 19, 18, 17, 16, 15, 14, 11, 12.

#define NUM_SENSORS   8  //uso el pin D8
#define TIMEOUT       2500  // tiempo de espera para dar resultado en uS
#define EMITTER_PIN   6    //uso el pin D6

por lo que quedaria definido asi:

Las conexiones físicas son estas:


A continuación muestro el código completo para empezar con la utilización de los sensores:
#include <QTRSensors.h>
#define NUM_SENSORS   8     // numero de sensores usados
#define TIMEOUT       2500  // esperar 2.5 ms para tener una respuesta del sensado
#define EMITTER_PIN   6     // este pin controla el led on del los sensores (enciende y apaga)
 
//aqui se pone el numero de los pines conectados a los sensores
QTRSensorsRC qtrrc((unsigned char[]) {19, 18, 17, 16, 15, 14, 11, 12},
  NUM_SENSORS, TIMEOUT, EMITTER_PIN); 
unsigned int sensorValues[NUM_SENSORS];
 
 
void setup()
{
  delay(500);
  pinMode(13, OUTPUT);        
  digitalWrite(13, HIGH);    //este led encendido indica que comienza la calibracion
  for (int i = 0; i < 200; i++)  // la calibracion se lleva a cabo por 5 segundos 
  {
    qtrrc.calibrate();       // funcion para calibrar los sensores
  }
  digitalWrite(13, LOW);     // se paga el led para que indique que termino la calibracion
 
  // imprime la calibracion minima de los sensores
  Serial.begin(9600);
  for (int i = 0; i < NUM_SENSORS; i++)
  {
    Serial.print(qtrrc.calibratedMinimumOn[i]);
    Serial.print(' ');
  }
  Serial.println();
   
  // imprime la calibracion maxima de los sensores
  for (int i = 0; i < NUM_SENSORS; i++)
  {
    Serial.print(qtrrc.calibratedMaximumOn[i]);
    Serial.print(' ');
  }
  Serial.println();
  Serial.println();
  delay(1000);
}
 
 
void loop()
{
  // read calibrated sensor values and obtain a measure of the line position from 0 to 5000
  // To get raw sensor values, call:
  //  qtrrc.read(sensorValues); instead of unsigned int position = qtrrc.readLine(sensorValues);
  unsigned int position = qtrrc.readLine(sensorValues);
 
  // print the sensor values as numbers from 0 to 1000, where 0 means maximum reflectance and
  // 1000 means minimum reflectance, followed by the line position
  for (unsigned char i = 0; i < NUM_SENSORS; i++)
  {
    Serial.print(sensorValues[i]);
    Serial.print('\t');
  }
  //Serial.println(); // uncomment this line if you are using raw values
  Serial.println(position); // comment this line out if you are using raw values
   
  delay(50);
}


-> Visualizando los  valores obtenidos con los sensores

Hecho toda la conexión respectiva, cargar el programa al arduino, luego abrir el "monitor serial" del ide arduino. Luego, en una superficie blanca con una linea negra, se puede utilizar un  cinta aislante negra, recorrer los  sensores  por la parte negra, y por la parte blanca (hacer estas pasadas reiteradas veces y procurar que la distancia con respecto a la superficie sea constante), de esta manera estaremos calibrando los sensores. 
Abrir el monitor serial, si la calibración se hizo de forma correcta se mostraran estos resultados en el monitor serial:
(ojo, para un correcto sensado lo ideal es que la distancia entre la superficie  y los sensores se mantenga  constante, a una distancia de 3 mm a 10mm. )




Los valores que nos arroja el monitor serial, son los valores obtenidos de la lectura  de cada sensor. Cuando se esta en una superficie blanca el mínimo valor de reflactancia es "0", y cuando esta se esta sobre una superficie negra, el máximo valor obtenido es "1000". También van existir partes donde los sensores estén sobre una parte blanca y un parte oscura. un valor que arrojaría seria un "500" o "600".
De esta manera se puede hacer un ponderado de cada sensor ,  obteniendo así valores relativos de posición (esto la librería ya lo hace) y se logra visualizar en la ultima columna a la derecha.
 Estos  valores de posición nos dirán que tan alejados de la linea están los sensores con respecto al centro, Esto nos sera de mucha utilidad para  el "Algoritmo Pid" que utilizaremos para  nuestro robot.
los valores de posición comprenden desde "0" hasta "7000"

Para visualizar el funcionamiento de los sensores solo sera posible con una cámara de celular, o cámara digital, algunos celulares traen un filtro y la visualizacion de los  se ve atenuada y hasta nula, por eso recomendaría usar camaras antigua. Directamente nosotros no somos capaces de ver la luz infrarroja.



->Entendiendo algunas definiciones de la libreria

#include <QTRSensors.h>  // Es siempre necesario la inclusión de la libreria de los qtr antes de 
                                          //utlizar sus funciones

Hay que reconocer  definciones que se usan para los sensores:
#define NUM_SENSORS   8       // aqui definimos cuantos sensores estamos utilizando , en este                                                         //caso el arreglo es de  8 sensores

#define TIMEOUT           2500    //este sera el tiempo que esperaremos para que  se de los                                                                  //resultados de lectura de los sensores. 
                                                    // el tiempo optimo esta entre los 1500 us a 2500 us
.
#define EMITTER_PIN    6        // este es el pin del "led on" es necesario especificar en que pin se                                                    // utilizara, en este caso es el D6

*Objeto para  sensor qtr 8rc:
  //aqui van los pines a utilizar para las lecturas
QTRSensorsRC qtrrc((unsigned char[]) {19, 18, 17, 16, 15, 14, 11, 12},
  NUM_SENSORS, TIMEOUT, EMITTER_PIN); 

unsigned int sensorValues[NUM_SENSORS];  // es necesario la creación de un array , esto para el                                                                           //almacenamiento de los valores de reflactancia de                                                                           //los sensores


->Funciones Importantes:

qtrrc.calibrate();       
calibracion de sensores es necesario  antes de utilizar los sensores, esta funcion no devuelve valor alguno

qtrrc.readLine(sensorValues, QTR_EMITTERS_ON, 0);  
Realiza la lectura de los sensores, y devuelve el valor de posición estimada de los sensores, la estimación se hace con un promedio ponderado de cada sensor. El tercer parámetro es para indicar si se requiere leer una superficie blanca con un linea negra ,este valor sera de "0". Si  se quiere leer una superficie negra con una linea Blanca,  se tiene que cambiar el valor a "1". para usarlo es necesario almacenarlo en una variable entera por ejemplo
int posicion=qtrrc.readLine(sensorValues, QTR_EMITTERS_ON, 0);  
         
qtrrc.read(sensorValues);
Realiza  Lecturas en bruto de cada sensor, para obtener estos valores es necesario leer  el  indice de array donde se guarda los valores de cada sensor . Por ejemplo si queremos saber el valor de reflactancia que tiene el sensor numero 1 tenemos que crear una variable y asignar el valor del array que contiene el valor del sensor:
int sensor_1=sensorValues[0];
int sensor_2=sensorValues[1];

Para mas informacion Puedes descargar la Nota de aplicación de Pololu, esta en ingles,  nunca esta de mas dar un vistazo
link: QTR_arduino_library.pdf
Pagina Pololu: https://www.pololu.com/product/961

"Si te sirvió de algo la informacion de la pagina, podrías invitarme un café y ayudarme a seguir manteniendo  en pie este sitio. Solo cuesta  $1 USD y me ayudarías  enormemente a seguir publicando estos contenidos". 




Siguiente post>> algoritmo pid robot velocista