Miniz 0.1            


Subo una primera versión del hard del miniz y programa que puede servir para probar la base, incompleta en todos los aspectos pero con la que se puede empezar a trabajar y probar para pensar lo que se quiere hacer, (no está probado todo el hard ni firm, es sólo una versión de prueba que en principio parece que funciona). Recopilo toda la información desde el principio:

El objetivo es modificar un coche radiocontrol de escala 1/28 para convertirlo en un robot velocista, elegimos esta escala porque es de las menores que podemos encontrar (aunque Kyosho ha sacado un coche 1/38 o por ahí, dnano, que habrá que probar) y por tanto nos permite movernos en radios de curvatura más pequeños, con el 1/28 podemos trazar los radios de curvatura mínimos del Cosmobot sin problemas, otra cosa es a que velocidad seamos capaces de hacerlo..

Lo primero es hacerse con un miniz (MR02, MR015, AWD), en tienda ronda los 130 euros, en los foros de rc se pueden conseguir coches prácticamente nuevos y upgradeados a un buen precio, http://www.minizz.com/forum10.html y foro coches rc son buenos sitios donde buscar. Una vez que tengamos el coche lo primero es reutilizar la máxima electrónica posible, aquí está la electrónica que trae y como usarla: miniz electrónica , de esta forma tenemos toda la electrónica necesaria, y sólo tendremos que hacer una placa de sensores para leer la línea y otra con un microcontrolador para mandar la señal de control a la electrónica del coche en función de la lectura de los sensores. Para elaborar las placas en casa este enlace.

Una primera placa de sensores es la de abajo, son 16 sensores uno a continuación de otro para leer en digital, con una anchura de aproximadamente 12.5 cm, y en esta placa es lo primero que debemos de pensar a la hora de diseñar el coche. Primero si queremos leer en digital o en analógico con las ventajas de resolución y número de sensores que aporta a costa de complicar más el firm, segundo la anchura de la placa y resolución necesaria. Los sensores se han puesto uno a continuación de otro de tal forma que tendremos el máximo número de CNY70 posibles sobre la línea, ya que en principio se va a intentar leer en digital.

La anchura de la placa de sensores dependerá de la distancia de ésta al punto del coche que debe de seguir la línea, y aquí es donde está mi primer problema que aún sin la prueba/error suficiente no sé enfocar muy bien para resolverlo. ¿Qué punto del coche debe de seguir la línea?. El centro de giro del coche se encuentra fuera de éste, en el punto intersección de las rectas del eje delantero y del eje trasero (si se observa la primera foto y se prolonga imaginariamente los ejes se puede hacer una idea). Bueno pues yo he considerado que el punto del coche que debe de seguir la línea es el punto central entre las dos ruedas traseras, éste va a ser mi punto de referencia a la hora de programar, por lo que si pincho con un compás en el centro de giro (para el giro máximo de las ruedas delanteras) y trazo una circunferencia desde el punto central trasero veo que superficie de sensores de la placa me resulta útil, ya que el punto central trasero sólo va a poder girar/ir hasta el punto intersección de la circunferencia trazada con el eje "cny" de la placa de sensores, por lo que ese sensor indicaría el giro máximo de la rueda, y todo sensor más alejado del centro que el sensor de giro máximo en principio sería inútil para el valor proporcional, para este coche a esta distancia me salen 8 cm de placa de sensores necesaria.

Cuanto más alejada esté la placa de sensores del coche mayor será la resolución que tendremos ya que necesitaremos más superficie de sensores para un mismo ángulo de giro, pero tb mayor será la probabilidad de tocar la línea roja y ser descalificados. Si el punto del coche que debe seguir la línea y debemos tomar como referencia es otro como el centro de masas, pues complicaría la cosa bastante.., primero porque habría que hallarlo para conocer la superficie útil de sensores o ajustar por prueba y error la constante proporcional, perderíamos mucha resolución y necesitaríamos una placa mucho más pequeña ya que estaría mucho más cerca de los sensores. Con todo esto en mente he diseñado una primera placa de sensores con 16 cny para que en cuanto a superficie y pruebas sea lo más flexible posible, una vez que sepamos lo que necesitamos habría que reducirla a las dimensiones requeridas, ya que cuanto más ancha peor, mayor es la porbabilidad de tocar la línea roja.

Bueno pues este es mi principal problema, que no sé como enfocar la parte mecánica y si lo que he pensado es correcto, y me doy cuenta que tener clara la parte mecánica para saber lo que se quiere hacer es lo más importante a la hora de diseñar un robot, y la electrónica y la programación son sólo las herramientas para hallar esos objetivos. Agradecería cualquier comentario sobre como enfocar/resolver la colocación de la placa de sensores y que punto del coche se debe tomar como referencia a la hora de programar, tema de inercias etc.. ya que mis conocimientos de mecánica son muy pobres.

Adjunto el esquema de la placa de sensores y el pcb en pdf (espero que salga a escala real, he utilizado una impresora a pdf de esas que hay). PCB para realizar la transparencia. La transparencia hay que invertirla para que las letras se lean de izquierda a derecha. El valor de las resistencias de diodo es de 120 ohmios (R1, R26...) y el valor de la resistencia de transitor 15k ohmios (R9, R10..), el valor de la R del led depende del color, en este caso para un led rosa 180 ohmios.





Resultado del montaje final:






La otra placa que debemos hacer es la del microcontrolador que lea los sensores y mande la señal de control a la electrónica del coche, como micro se ha usado un 18f452 aunque sigo pensando en el atmega16, la placa es lo más sencilla posible. 16 entradas de sensores pasadas por un trigger smichtt interno del puerto del micro, un par de diodos leds para posibles pruebas, detectar resets etc.. y unos cuantos interruptores. También se ha añadido un mosfet para apagar y encender la placa de sensores, ya que el consumo de 16 cny con esas resistencias de diodo es bastante elevado, por lo que la idea es encender, leer y apagar hasta el siguiente ciclo. PCB de la placa del pic para realizar la transparencia, aquí las letras están en la cara top y no hay que invertir la transparencia a la hora de colocarla sobre el cobre, hay que realizar un puente entre el punto que está al lado de R8 y el otro cercano a S1.





Resultado final del montaje:



Los valores de los componentes se pueden apreciar en la foto, cristal de 16 Mhz con los condensadores de 22pF, condensador de desacoplo del pic de 100nF, R de led de 150 Ohmios, R de pull-up interruptores de 10K, R de mosfet de 120k, R del divisor de 560 ohmios para adaptar niveles entre el micro del coche y el nuestro.

El micro está programado en C usando el compilador de microchip, del que se puede bajar una versión gratuita con límite de dos meses en las opciones de optimización, para generar la señal requerida por el miniz usaremos una interrupción de un timer del pic, como se explica aquí. El resto de programa es sólo un control proporcional de posición con unos valores de velocidad fija para que el coche siga la línea, está hecho deprisa y corriendo para probar el hard del coche por lo que habrá muchos errores. Se usan float cuando se deben evitar ya que las operaciones en coma flotante son mucho más lentas, por lo que habrá que escalar los valores asignados a los sensores para siempre obtener números enteros en las operaciones, es sencillo y evitamos usar float.

Respecto a la mecánica del coche he visto que poner upgrades no es lo mejor, se ha cambiado la bancada trasera para añadir un motor más potente y pasa a ser casi incontrolable, por lo que puede que mejor sea vovler al motor de serie, ya que también dispará el consumo por tres, comiendose la batería en unas pocas vueltas. Con el miniz anterior de serie y unas pilas recargables de 850 mAh le hemos tenido hasta 30 min en pista dando vueltas de forma continua a más de 130 cm/s, por lo que el motor de serie casi seguro que va a ser la mejor opción. Otra cosa muy importante es utilizar la opción del freno, en las pruebas el coche en parar sin frenar desde una velocidad elevada lo hace en uno, dos metros, frenando, en 3-10 cm aproximadamente. Por lo que si queremos correr y ser competitivos trabajar en este punto es muy importante.

La programación es el punto donde más hay que trabajar, y es lo que intentaremos los próximos meses, a ver si conseguimos que un cochecito de estos le plante cara a un diferencial, la parte D del regulador es 100% necesaria, ya que en recta oscial demasiado nada más que se quiere correr un poco, también puede ser un problema de las mecánicas de estos coches que probablemente haya que upgradear para solucionar.

Esta electrónica la voy a probar en un nuevo modelo de miniz que compre en uno de los foros anteriores por la mitad de su precio sin uso, un miniz AWD , tracción a las 4 ruedas, a ver que tal sale. En principio la electrónica que lleva parece ser la misma a simple vista (aún hay que comprobarlo), por lo que estas dos mismas placas valdrían.

Miniz AWD.


Un video del funcionamiento del coche anterior, el motor es demasiado potente, por lo que si se quiere usar habrá que meterle muchas horas de programación.


Para cualquier duda, comentario, error

Gracias por pasar por aquí.






Código.


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

void inicializar (void);
void reseteo (void);
void timer2_isr (void);
void obtener_error(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 // default code section


#define LED1 PORTEbits.RE0 // Ambar
#define LED2 PORTEbits.RE1 // Rojo
#define SENSORES PORTEbits.RE2 // Placa de sensores
#define MINIZ PORTBbits.RB4 // Control miniz

#define R7 PORTCbits.RC0 //Extremo derecho
#define    R6 PORTCbits.RC1
#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
#define    L6 PORTDbits.RD6
#define    L7 PORTDbits.RD7 // Extremo izquierdo

//Variables
unsigned char DelayCounter1;
char servo = 44, velocidad = 44;
char servo_v=44;
int contador=0;
int errors=0;
float errort=0;
float errort_old=0;
float media_error=0;

//Programa principal

void main (void)
    {
        inicializar();
        reseteo();
        LED1 = 1;
        SENSORES=1;

        while(1)
        {
        obtener_error();
        }
    }

//******************************FUNCIONES*******************************************
void inicializar (void)
{
      TRISA = 0b11111111;     // Configuración de los puertos
      TRISB = 0b11101111;        //
      TRISC = 0b11111111;        //
    TRISD = 0b11111111;        //
      TRISE = 0b00000000;      // 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;
}

void reseteo (void)
{

    INTCONbits.GIE = 0;
    LED2 = 1;                  //3 parpadeos para detectar los posibles resets del pic
    LED1 = 0;
    Delay10KTCYx(200);
    LED2 = 0;
    Delay10KTCYx(200);
    LED2 = 1;
    Delay10KTCYx(200);
    LED2 = 0;
    Delay10KTCYx(200);
    LED2 = 1;
    Delay10KTCYx(200);
    LED2 = 0;
    INTCONbits.GIE = 1;
}

#pragma interrupt timer2_isr save=DelayCounter1  // interrupción, salvamos la variable de los delays

void timer2_isr ( void)  // 24 44 64

{
    PIR1bits.TMR2IF = 0;  //Limpia el flag de interrupción del timer2
    MINIZ = 1;
    Delay100TCYx(16);      // 400 uS
    MINIZ = 0;
    Delay100TCYx(servo);
    MINIZ = 1;
    Delay100TCYx(16);      //400 uS
    MINIZ = 0;
    Delay100TCYx(velocidad);   
    MINIZ = 1;
    Delay100TCYx(16);   
    MINIZ = 0;   
}

void obtener_error(void)
{
       
        errors=0;
        contador=0;
        errort=0;

//        if(L7==1)
//            {
//            errors+=16;
//            contador++;
//            }
//        if(L6==1)
//            {
//            errors+=6;
//            contador= contador+1;
//            }
        if(L5==1)
            {
            errors+=5;
            contador= contador+1;
            }
        if(L4==1)
            {
            errors+=4;
            contador= contador+1;
            }
        if(L3==1)
            {
            errors+=3;
            contador= contador+1;
            }
        if(L2==1)
            {
            errors+=2;
            contador= contador+1;
            }
        if(L1==1)
            {
            errors+=1;
            contador= contador+1;
            }
        if(L0==1)
            {
            errors+=0;
            contador= contador+1;
            }
        if(R0==1)
            {
            errors+=0;
            contador= contador+1;
            }
        if(R1==1)
            {
            errors+=(-1);
            contador= contador+1;
            }
        if(R2==1)
            {
            errors+=(-2);
            contador= contador+1;
            }
        if(R3==1)
            {
            errors+=(-3);
            contador= contador+1;
            }

        if(R4==1)
            {
            errors+=(-4);
            contador= contador+1;
            }
        if(R5==1)
            {
            errors+=(-5);
            contador= contador+1;
            }
//        if(R6==1)
//            {
//            errors+=(-6);
//            contador= contador+1;
//            }
//        if(R7==1)
//            {
//            errors+=(-16);
//            contador++;
//            }


        if (contador!=0)
            {
            velocidad=39;
            errort=errors/contador;
            servo= 42 - errort*3;  //servo=centro-error*constante proporcional

            if (servo>64)
                servo=64;
            if (servo<24)
                servo=24;
            }
        else if (contador==0)
            {
            velocidad=44;
            }

}