MiniZ. Cosmobot 2009.    


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:





Fotolito anterior para insolar, creado mediante impresora a pdf. Hay 3 puentes a realizar, los dos que se ven a los Mosfets de los diodos leds y el que está junto a C3 y R13. El footprint es el del 16f877 que es compatible pin a pin con el del 18f452.

Placa de sensores:





Fotolito de la placa de sensores.


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.
//////////////////////////////////////////////////////////////////////////

#include <p18f452.h>
#include <delays.h>
#include <timers.h>

#pragma config WDT=OFF, LVP=OFF, OSC=HS, OSCS=OFF, PWRT=ON, BOR=OFF, STVR=ON

void inicializar (void);
void timer2_isr (void);
void obtener_error(void);
void obtener_errord(void);
void obtener_posicion(void);
void obtener_velocidad(void);
void determinar_estado(void);
void reseteo (void);

#pragma code high_vector=0x08 // high interrupt vector en 0008h
void interrupt (void)
{
    _asm GOTO timer2_isr _endasm // Salta a la ISR
}
#pragma code


#define LED1 PORTEbits.RE0 
#define LED2 PORTEbits.RE1 

#define MINIZ PORTBbits.RB4 // Control miniz


#define    R5 PORTCbits.RC2
#define    R4 PORTCbits.RC3
#define    R3 PORTDbits.RD0
#define    R2 PORTDbits.RD1
#define    R1 PORTDbits.RD2
#define    R0 PORTDbits.RD3 // Centrales
#define    L0 PORTCbits.RC4 //
#define    L1 PORTCbits.RC5
#define    L2 PORTCbits.RC6
#define    L3 PORTCbits.RC7
#define    L4 PORTDbits.RD4
#define    L5 PORTDbits.RD5


//Variables
unsigned char DelayCounter1;
int servo = 110, velocidad = 110;
int errors=0;
int kp=1;
int errors_pasado=0;
int errord=0;
int tic=0;
char estado=2;
char tac=0;
char tic_freno=0;
char freno=0;
char ultimosensor=3;
char contador=0;
char centro=0;
char nop=1;


//Programa principal

void main (void)
    {
        inicializar();
//        reseteo();
        LED2=1;
        nop=2;    //read-write-modify
        LED1=1;
        estado=2; //carril externo, parte derecha interior.
        tic=9;

        while(1)
        {
            if((R0==1)||(L0==1)) //Para cambiar estados.
                centro=1;

            if((R5==1)||(R4==1)||(R3==1))
                ultimosensor=1;
            else if((L5==1)||(L4==1)||(L3==1))
                ultimosensor=0;
        }
    }

//******************************FUNCIONES*******************************************

//***************************** 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

   obtener_error();
   obtener_errord();
   determinar_estado();
   obtener_velocidad();
   obtener_posicion();


   MINIZ = 1;
   Delay100TCYx(16);      // 400 uS
   MINIZ = 0;
   Delay10TCYx(servo);
   Delay10TCYx(servo);
   Delay10TCYx(servo);
   Delay10TCYx(servo);
   MINIZ = 1;
   Delay100TCYx(16);      //400 uS
   MINIZ = 0;
   Delay10TCYx(velocidad);
   Delay10TCYx(velocidad);
   Delay10TCYx(velocidad);
   Delay10TCYx(velocidad); 
   MINIZ = 1;
   Delay100TCYx(16);  
   MINIZ = 0;  
}


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.

        if((R0==1)&&(contador<4))
            {
            errors+=(-1);
            contador= contador+1;
            }
        if((L0==1)&&(contador<4))
            {
            errors+=1;
            contador= contador+1;
            }
        if((R1==1)&&(contador<4))
            {
            errors+=(-3);
            contador= contador+1;
            }
        if((L1==1)&&(contador<4))
            {
            errors+=3;
            contador= contador+1;
            }
        if((R2==1)&&(contador<4))
            {
            errors+=(-5);
            contador= contador+1;
            }
        if((L2==1)&&(contador<4))
            {
            errors+=5;
            contador= contador+1;
            }
        if((R3==1)&&(contador<4))
            {
            errors+=(-7);
            contador= contador+1;
            }
        if((L3==1)&&(contador<4))
            {
            errors+=7;
            contador= contador+1;
            }
        if((R4==1)&&(contador<4))
            {
            errors+=(-9);
            contador= contador+1;
            }
        if((L4==1)&&(contador<4))
            {
            errors+=9;
            contador= contador+1;
            }
        if((R5==1)&&(contador<4))
            {
            errors+=(-11);
            contador= contador+1;
            }
        if((L5==1)&&(contador<4))
            {
            errors+=11;
            contador= contador+1;
            }
       
        if(contador!=0)
            errors=errors/contador;
/*        else if(contador==0)
        {
            if(ultimosensor==0)
                errors=-13;
            else
                errors=13;
        }*/
}

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 ***********************************

//1 interior, 2 exterior, 3 exterior cambio, 4 interior cambio, 5 freno.

void determinar_estado(void)
{
//estado inicial interior, sentido: parte derecha en el interior coche avanza. Variables de entrada velocidad, errors y errorp.
//estado anterior.

switch (estado)
{
    case 1: //carril interior
    {
        LED1=1;
        nop=2;   
        LED2=0;

        centro=0;

        if(contador==0)
        {
            if(ultimosensor==1)
                estado=4;
            else if(ultimosensor==0)
                estado=5;
        }   
    }break;

    case 2: //carril exterior
    {
        LED1=0;
        nop=2;   
        LED2=1;
        centro=0;

        if(contador==0)
        {
            if(ultimosensor==1)
                estado=5;
            else if(ultimosensor==0)
                estado=3;
        }
    }break;

    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;

    case 5: //freno
    {
        LED1=0;
        nop=2;   
        LED2=0;
        if(contador!=0)
        {
            if(ultimosensor==1)
                estado=2;     //exterior
            else if(ultimosensor==0)
                estado=1;    //interior
        }

    }break;



    default: 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 *********************************

void obtener_posicion(void) //Control proporcional derivativo. Variables errors, errord.
{
        if (contador!=0)
            {
            servo = 110 - errors*kp + errord*1; //servo=centro-error*constante proporcional + derivada error* constante derivativa

            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.
 
Video1.


Video2.


Para cualquier comentario, duda , error más abajo.


.
Comentarios.


blog comments powered by Disqus