A una semana del Cosmobot y con poco tiempo para
más aquí se han quedado los coches para presentar
este año al concurso de velocistas, no he tenido tiempo de
hacer todo lo que quería hacer, por lo que falta mucho para
ser competitivo pero lo bueno es que ya tengo trabajo con ellos hasta
el Cosmobot del año que viene, para el que espero
tenerlos listos con todas sus posibilidades...
Empezamos evaluando las distintas opciones de coches rc de escala 1:28
(cuanto más pequeños mejor ya que menor
será su radio mínimo de giro) y tras probar
varios modelos yo me he decidido por empezar a construir dos MiniZ AWD
(tracción a las 4 ruedas) para presentar a medio camino este
año y trabajar en ellos para el que viene junto a un Dnano
escala 1:43 para el Cosmobot 2010 (si algún dios quiere). Me
gusta el AWD ya que en una superficie con poco agarre como el sintasol
de los concursos necesitamos toda la tracción posible,
versiones del MR02 tienen menos distancia entre ejes por lo que
también son una buena elección montados en rear
motor. Otra de las ventajas del AWD es que cuando frenamos bloqueamos
las 4 ruedas, pero a eso este año aún no llego...
(por lo que con un MR02 o MR015 como el año anterior puede
que fuese más rápido).
El coche se ha quedado en un control proporcional y derivativo del
error, con el que hemos conseguido una buena estabilidad en recta que
era el primer aspecto a implementar y mejorar respecto al
año pasado en estos coches, ha faltado añadir dos
enconders al eje trasero para medir y hacer un control de la
velocidad y ésto es fundamental, ya que sin ello no podemos
acelerar ni frenar y simplemente vamos a ciegas con unos valores de
velocidad constantes, es como salir de un semáforo pisando
un poco el acelerador y coger velocidad poco a poco en lugar de pisar
fuerte y levantar una vez alcanzada la velocidad deseada, pues lo mismo
un montón de segundos que se podrían ganar
implementado los encoders y el control de velocidad que
mejoraría mucho los resultados. Además de tener
una referencia de velocidad para saber si debemos frenar, y cuando
hemos alcanzado la velocidad deseada para dejar de usar el freno que
llevan estos coches, sin implementar el control de velocidad muchos de
los upgrades disponibles para estos coches son inútiles.
Eje trasero para construir dos encoders y montar unos discos blanco y
negro sobre las ruedas.
Otra cosa que falta es añadir un módulo de
comunicaciones (BT) para recibir resultados en tiempo real en el pc
mientras se prueba el coche (en el concurso no puede haber
comunicación externa), de esta forma se podría
visualizar como afectan los diferentes ajustes en el coche de las
constantes de los reguladores y de la velocidad, y lo que puede
funcionar es implemetar el freno en función de la velocidad
y de la derivada del error, y para medir esto último es
necesario poder visualizar los datos en el pc. Por lo que sobre el eje
delantero hay un buen espacio para añadir uno de estos
módulos, que junto a lo anterior será lo que se
intentará hacer para el año que viene..
más el coche 1:43.
De momento subo las electrónicas finales y programa para
este año, programa que aún falta de probar y
ajustar algún día más que podamos
sacar en nuestra pista ya que a una semana del Cosmobot no se ha
facilitado la pista del concurso que se iba a dar y con la que yo
contaba para testear, pero ya no hay tiempo para montarla ni para
probar en ella, por lo que no veo que sentido tiene decir que se va a
dar la pista si a una semana del concurso no está
disponible, con los 110-120 cm/s a los que irán estos coches
ahora mismo andan muy lejos de ser competitivos pero si se
hubierá facilitado la pista a su tiempo yo almenos me
hubierá molestado en montarla para hacerlo lo mejor
posible..
La electrónica final que añadimos al coche consta
de dos placas, una con un microcontrolador (18f452) que se encarga de
recibir las salidas de la segunda placa de sensores y generar la
señal de control en función de éstas
para el microcontrolador de la electrónica interna del coche.
PCBs vista superior.
Placa de sensores vista inferior.
Los valores de los componentes son los que se aprecian en las
fotos pinchando sobre ellas para ir al tamaño
original, 22pF y 16MHz en el cristal. Los valores de las resistencias
de las placas de sensores son de 120 Ohms y 15K Ohms, en principio sin
luz solar no debería haber ningún problema
llevandolas directamente a los puertos de los pics con trigger Schmitt
internos. Con luz solar o tapamos muy bien las placas o los sensores
acaban cegados, aquí lo mejor puede ser ir pensando en leer
en analógico. Para modificar la electrónica del
coche sólo hay que levantar la tapa superior y cortar la
pista que va del receptor de radio al microcontrolador del coche: modificar electrónica.
En este coche la pista se encuentra en la cara que se ve nada
más levantar la tapa superior del chásis, la
electrónica de 27 MHz es la misma que en el MR02,
actualmente estas electrónicas y coches están
siendo sustituidos por los nuevos modelos de 2.4 GHz, como la que ya se
encuentre en el Dnano.
Esquemas y los fotolitos de las placas, placa de microcontrolador:
Al final se usan 12 CNY que se corresponden con el espacio necesario
para el giro máximo del coche.
El programa sigue el esqueleto de timer2,
una interrupción cada 16 ms que se encarga de calcular los
valores necesarios para generar la señales necesarioas
requeridas para el control del coche a través de su
microcontrolador interno. Los reguladores son los mismos de Progrmación1
y Programación2
ajustados y añadiendo un par de funciones para saber en que
posición se encuentra el coche respecto a los dos carriles
(una especie de máquina de estados) y otra
función para establecer distintos parámetros en
función del estado anterior.
El programa que nos queda es más o menos una cosa
así, falta por ajustar los tipos de variables aunque tenemos
ram para malgastar y organizar y repasar el código con calma
ya que es lo primero que ha salido...
//////////////////////////////////////////////////////////////////////////
// Programa para el AWD
// www.jmnlab.com
// Marzo 2009
// Control proporcional derivativo. 16 MHz.
//////////////////////////////////////////////////////////////////////////
//***************************** Hardware micro
*************************************
void inicializar (void)
{
TRISA =
0b11111111; //
Configuración de los puertos
TRISB =
0b11101111; //
TRISC =
0b11111111; //
TRISD =
0b11111111; //
TRISE =
0b00000100; // Puerto
E como salidas.
ADCON1 =
0b00001111; // Todo puerto A
como digitales.
PORTB = 0;
PORTE = 0;
OpenTimer2 (TIMER_INT_ON &
T2_PS_1_16 & T2_POST_1_16); //TMR2IF=0 TMR2IE=1 TMR2ON=1 TMR2=0
RCONbits.IPEN = 0;
INTCONbits.GIE = 1;
INTCONbits.PEIE = 1;
PR2 = 250;
}
Inicio del programa,
declaraciones, defines y configuraciones del hardware del micro. En el
main() solamente leemos algunos sensores para capturar el paso de la
línea por ciertas zonas de la placa, ya que si leemos cada
16 ms podríamos saltar alguna de estas condiciones, aunque a
la velocidad que vamos es tiempo de sobra... El nop=2 es
sólo para perder tiempo y evitar el read-write-modify de los
pics dando tiempo al pin a establecer su valor a 1 antes de modificar
otro pin del puerto que machacaría al anterior ya que no ha
alcanzado su valor a 1 antes de modificar otro pin del mismo puerto y
leer todos los pines del puerto.
Funciones:
void inicializar (void);
Inicializa el hardware del pic
según lo deseado, configura y habilita la
interrupción del timer2 a 16 ms. void timer2_isr
(void);
Interrupción que
se produce cada 16 ms y se encarga de llamar a las distintas funciones
y mandar la señal al micro interno. void
obtener_error(void);
Obtenermos el error proporcional de la
placa de sensores. void
obtener_errord(void);
Obtenemos el error derivativo de la placa de sensores. void
obtener_posicion(void); Cálculo de la
posición que debemos mandar al servomotor en
función del error de la placa de sensores y su derivada. void
obtener_velocidad(void); Asignar velocidad y modificar
variables en función de la situación del coche
respecto a los carriles. void
determinar_estado(void); Determinar
posición del coche respecto a los carriles. void reseteo
(void);
Parpadeos
de leds al inicio del programa para detectar posibles reseteos del
microcontrolador, no usada durante el concurso por razones de tiempo... //****************************
Señal de mando******************************************
#pragma interrupt timer2_isr save=DelayCounter1 //
interrupción, salvamos la variable de los delays
void timer2_isr ( void) // 24 44 64 //60 110 160
{
PIR1bits.TMR2IF = 0; //Limpia el flag de
interrupción del timer2
Esta
función se encarga de llamar a las funciones necesarias para
calcular los tiempos que hay que pasar al microcontrolador interno, se
deben hacer en ese mismo orden ya que cada función modifica
variables globales necesarias para los cálculos de las
restantes funciones. Una vez hecho esto se genera la señal
de 3 pulsos de tiempo variable que va a parar al pin del micro interno. //***********************************
Proporcional*********************************
void obtener_error(void)
{
errors=0;
contador=0;
//Asignar error, 3 sensores consecutivos, máximo activados,
valores para obtener siempre entero en la división.
Se leen los sensores
y se obtiene un error proporcional a la distancia de la
línea al centro de sensores, más sobre
ésto en programación1. //******************************
Derivada **************************************
void obtener_errord(void) //Comprobar si ha cambiado el error y su
derivada.V: errors
{
if
(errors_pasado==errors)
{
tic--;
if
(tic<0)
tic=0;
errord=0;
}
else
if(errors_pasado != errors)
{
errord=(errors_pasado-errors)*tic;
tic=9; //9
}
errors_pasado=errors;
}
Se obtiene la derivada
del error, más sobre ésto en programación2. //**********************************
Determinar estado ***********************************
void determinar_estado(void)
{
//estado inicial interior, sentido: parte derecha en el interior coche
avanza. Variables de entrada velocidad, errors y errorp.
//estado anterior.
case 3: //carril exterior cambia carril
interior o sigue en el exterior
{
LED1=1;
nop=2;
LED2=1;
if(centro==1)
{
if(ultimosensor==1)
estado=1;
//carril interior
else if(ultimosensor==0)
estado=2;
//carril exterior
}
if(errors<0)
errors=errors*(-1);
}break;
case 4: //carril interior cambia a
carril exterior o sigue en el interior
{
LED1=1;
nop=2;
LED2=1;
if(centro==1) //Ponerlo en el main() para evitar saltarlo en 16 ms
{
if(ultimosensor==1)
estado=1;
else if(ultimosensor==0)
estado=2;
}
if(errors>0)
errors=errors*(-1);
}break;
Esta función
sirve para determinar donde se encuentra el coche respecto a las 4
líneas (2 negras y 2 rojas) que forman la pista, es decir si
estamos en el carril interior, en el carril exterior, entre los dos
carriles saliendo del interior, entre los dos carriles saliendo del
exterior y entre una línea negra y una línea
roja. A primera vista estos son los cinco posibles casos que nos pueden
interesar. Para ello debemos saber el sentido en el que se recorre la
pista ya que nos fijamos en los últimos sensores
leídos cuando el coche pierde línea para saber
donde estamos.
Por ejemplo: suponemos que el sentido de desplazamiento es tal que la
parte del coche derecha esta en el interior del circuito y la parte
izquierda hacía el exterior (no hay puentes en el circuito),
decimos que nuestro coche va a empezar en el carril exterior, estamos
en el estado dos. Luego desde este estado si perdemos línea
podemos pasar al estado 3 o al estado 5, si el último sensor
leído está en la parte de la izquierda, el coche
estará desplazandose desde el exterior hacía el
interior, luego nos encontramos en el estado 3 (case 3) el coche entre
las dos líneas negras desplazandose del carril exterior al
interior. Si por el contrario el último sensores
leído está en la parte derecha (yo voy sentado en
el asiento del conductor) nos encontraremos en el estado 5 (case 5) en
el que el coche se encuentra entre una línea negra y una
línea roja.
Es decir del estado 2 podemos pasar al estado 3, al estado 5 o volver
al estado dos. Para pasar del estado 2 al estado 3 nos fijamos en la
variable centro que es nuestra condición. La variable centro
se pone a 1 cada vez que los sensores centrales están bajo
la línea y cuando estamos en el carril interior o exterior
(estado 1 ó 2) y salimos de alguno la ponemos a cero, por lo
que cuando valga uno significará que el coche
está sobre un carril por lo que mirando si el
último sensor activo antes de llegar al centro
está a la izquierda o a la derecha podemos deducir si hemos
cambiado de carril o vuelto al inicial. Para ello usamos la variables
ultimosensor y centro que leemos continuamente en el búcle
del main().
Y por qué nos importa saber donde estamos?. Imaginemos que
estamos en el mismo caso anterior, el coche va por el exterior viene
una curva en la que debemos girar a la izquierda y el coche se desplaza
hacía el carril interior. Si no detectamos que estamos entre
los dos carriles y al pisar el carril interior el sensor que se activa
es el del otro extremo por donde hemos salido, que le diría
a nuestro regulador tenemos que ir hacía la derecha en una
curva a izquierdas, lo que nos haría girar la
dirección en el sentido contrario al deseado de forma
repentina con todas las de acabar fuera de la pista.
Por eso debemos detectar esta situación y evitar ese
volantazo, para evitarlo algo tan simple como anular los sensores del
lado derecho del coche que pisaría el carril interior o
modificar su giro que es lo que a mi me gusta hacer ya que evitamos
movimientos bruscos de la dirección, para ello:
si nos encontramos en el estado anterior (el case 3), hemos salido por
la izquierda valor de error positivo y piasamos los sensores de la
derecha valor de error negativo, pues nada más
fácil que cambiar el signo del error.
if(errors<0)
errors=errors*(-1);
De esta forma
según nos vamos metiendo encima del carril interior vamos
modificando la dirección poco a poco de izquierda
hacía el centro, los sensores de la derecha tienen el mismo
efecto sobre la dirección que los sensores de la izquierda
lo que nos evita dar volantazos o movimientos bruscos.
Para el caso de pasar el carril interior al exterior cuando nos
encontramos en el centro de los dos carriles pues igual a la inversa:
if(errors>0)
errors=errors*(-1);
Si estamos en el
estado 5 entre una línea negra y roja, pues del estado 5
sólo se puede volver al carril del que se ha salido, por lo
que miramos la variable contador que es la que nos dice si se ha
activado algún sensor y viendo si es un 1 ó un 0
(valores que toma el último sensor está a la
derecha o a la izquierda) pues sabemos si entramos al carril exterior o
interior.
Con esta especie de máquina de estados sabemos en todo
momento cuál es la posición de nuestro coche
respecto a las línea, pudiendo actuar en función
de ello como más nos interese.
Para poder implementar esto debemos saber el sentido de desplazamiento
en el circuito (que es conocido) y decidir cual va a ser nuestro carril
de comienzo, de todas formas la placa del microcontrolador lleva
interruptores para poder seleccionar las distintas opciones en el caso
de que ésto no fuese conocido. El coche acaba en el carril
hacía donde nos eche la curva si vamos a la velocidad
suficiente para desplazarnos, conocido el circuito podemos implementar
cambios intencionados para ir por ejemplo por el carril interior o
exterior según nos interese, aunque en la mayoría
de los casos nos va a interesar ir por el interior por lo que
ésto falta de hacer aquí, si lleva X ms en el
exterior forzar un cambio al interior, si tuvieramos el circuito....
En esta función estoy corrigiendo directamente dentro de los
estados pero lo suyo sería crear otra función que
haga la corrección y que esta función
sólo detecte el estado presente para estrucutar el
código, así que ésto hay que cambiarlo. //***********************************
Ajuste de velocidad *******************************
void obtener_velocidad(void) //Ajuste de velocidad, Freno, Carril.
{
if((estado==1)||(estado==2))
{
velocidad=100;
if((errors<=5)&&(errors>=(-5)))
kp=1;
else
kp=2;
}
else if((estado==3)||(estado==4))
{
velocidad=100;
kp=2;
}
else if(estado==5)
{
velocidad=101;
//
kp=3; en este estado giro
máximo siempre del servo
}
} Aquí es
mas o menos donde me quede escribiendo el código,
según la posición del coche correr mas o menos,
en principio sin un regulador de velocidad ni encoders pues
sólo podemos dar valores constantes. Si estamos sobre un
carril nos interesa tener una velocidad mayor que cuando nos estamos
cambiando de carril o estamos entre la línea negra y roja en
donde deberíamos disminuir bastante o incluso frenar.
También juego un poco con los ajustes de la variable
proporcional, dando distintos valores en función de las
situación y sobre todo de la velocidad. Si estamos en los
estados entre carriles podemos decir que el coche gire menos para
facilitar el cambio, etc... lo que nos interese, pero ésto
tengo que meterlo en la función que tenía que
crear anteriormente para no mezclar, y el tema de frenar pues
algún día.. //************************************
Regulador *********************************
if (servo>160)
servo=160;
if (servo<60)
servo=60;
}
else if (contador==0)
{
if
((ultimosensor==1)&&(estado==5))
servo=160;
else
if((ultimosensor==0)&&(estado==5))
servo=60;
}
}
Con los errores
calculados, la situación del coche determinada,
sólo queda corregir la dirección del coche y
mandar la posición del servo, implementamos el regulador ya
explicado en programación2. Comentar
que podemos meter un "offset" a nuestro coche sobre la
línea, es decir si queremos que el centro del coche vaya
sobre la línea vaya el extremo izquierdo o el detecho, pues
en lugar de 110 poner 103 ó 117 (valores de ejemplo), de
esta forma podremos ir aún más por el interior o
exterior en función del circuito que nos den puede interesar. Bueno pues por
aquí se encuentra el miniZ de este año para el
Cosmobot muy lejos de ser competitivo pero yo estoy contento con el
resultado ya que lo veo bastante estable y sobretodo con mucho trabajo
futuro por hacer con el que mejorar. Falta repasar el código
que es lo primero que ha salido, corregir los posibles errores que
tengamos que alguno habrá y crear otra función
con las posibles modificaciones de la Kp y del errors al cambiar de
carril. Si alguien está realizando un miniZ de estos
cualquier idea o cosa que se nos haya podido escapar es bienvenida.
Y por último una buena noticia, parece que se
está creando una liguilla de robótica en la
cuál se suman puntos según la posición
durante varios concursos a lo largo del año y que por
supuesto intentaremos participar... Leyendo la normativa encontramos lo
siguiente:
3.
Puntos adicionales concedidos
Adicionalmente se concederán:
-
150 puntos al equipo que haya desarrollado la campaña por
Internet
más efectiva en la promoción de su Escuderia para
el año 2010 (desde
Marzo hasta Noviembre de 2009). La decisión sobre el ganador
se
realizará por sondeo de los directores de las Escuderias
inscritas en
la LNRC.
- 60 puntos al equipo que
pueda demostrar que ha realizado la busqueda más activa de
patrocinadores mediante un documento de un folio DIN-A4 que explique
las iniciativas desarrolladas (desde Marzo hasta Noviembre de 2009). La
concesión dependerá del criterio del Comite de la
LNRC y dicho documento se hará llegar a todos los directores
de Escuderia.
Así que
nosotros ya empezamos a hacer campaña :D, que lo de los
puntos por quedar primero están difíciles de
conseguir.. Aquí iremos subiendo todos los robots que
hagamos, esquemas, ideas, código.. Aunque nos salga un robot
de 3 m/s (0.00004% de éxito) aquí
estará, que lo nuestro no es ir a ganar concursos si no
aprender y disfrutar con ésto. Hacer un robot lleva mucho
tiempo y documentarlo para que pueda servir al resto una pocas horas,
¿ por qué nadie lo hace?. Ya sé que
nosotros somos muy malos, llevamos 3 días en esto de los
robots.. pero no tenemos ningún problema en demostrar lo
malos que somos XD.
Una noticia como esta en principio parece muy buena, lo que temo es que
se multipliquen las hordas de cazatesoros que no compartan y van a
ganar a toda costa como puede que ya suceda con tales premios,
desanimando a todo el que quiera empezar desde cero, ya que los
recursos y la gente que sabe y comparte por aquí son
bastantes limitados.
Y también hay que ir a por esos 60 puntos, así
que si algún patrocinador está interesado
pic16f690@hotmail.com . Evidentemente tendremos que decir que no a todo
patrocinador interesado, que si lo encontramos se acaba la
búsqueda y no podemos llevarnos esos 60 puntos!
Bueno unos videos de los miniZ funcionando en los que aún
nos queda mucho trabajo que hacer durante esta semana y el
próximo año. Aunque en teoría los dos
coches son iguales, he metido el programa del amarillo en el azul, y
por lo visto hace falta tocar la posición del servo o
algunas variables porque no va tan fino como el otro.