Lectura de los sensores, asignación del error.

Se va a realizar el primer intento de robot velocista con la placa de sensores QTR-8A en lugar de la inicialmente seleccionada QTR-8C ,por razones de simplicidad, si el resultado no es bueno pues habrá que considerar el uso de la placa QTR-8C que implica complicar el código a cambio de tener una lectura analógica de la línea, pero en principio con la QTR-8A debería bastar.

Fisicamente las dos placas son iguales en cuanto a tamaño y posición del conector, por lo que se pueden sustituir una por otra sin problemas, para leer ambas en digital.


La placa QTR-8A está pensada para leer un valor analógico de tensión, que se corresponde con la posición de la línea respecto al sensor.

Para este robot no se va a leer el valor analógico que requiere el uso de un ADC, en la Baby Orangutan se tienen 8 ADCs quitando el potenciometro de usuario, por lo que se podría usar para una lectura en analógico de esta placa de sensores. Se van a leer los sensores en digital, es decir detectaremos cuando la línea está bajo el sensor. Leyendo de esta forma tenemos un error de la medida correspondiente al espacio entre sensores, pero que podemos considerar despreciable en cuanto a la ubicación del robot respecto a la línea. Si ésto no resulta posible habrá que utilizar la otra placa.

Para leer el sensor simplemente hay que configurar el pin del micro que va conectado al cada sensor como entrada, y ver si está a uno o a cero. Si está a uno significa que la línea negra está debajo del sensor, y si está a cero el sensor se encuentra sobre blanco, así de fácil.

Tenemos 8 sensores y queremos que la línea se sitúe en el centro de la placa de sensores, a cada sensor le debemos asignar un valor numérico que representa la distancia del sensor al centro de la placa de sensores (punto medio de los dos sensores centrales).

Tenemos 8 sensores y los nombramos de izquierda a derecha: I3 I2 I1 I0 D0 D1 D2 D3, al punto medio entre I0 y D0 le asignamos el valor 0, a los sensores de la derecha de D0 a D3 los valores 1, 3, 5, 7 y a los de la izquierda de I0 a I1 los valores -1, -3, -5, -7.

I3  -7
I2 -5
I1  -3
I0  -1
D0 1
D1  3
D2  5
D3  7

Si la línea está sobre el sensor I2 tenemos un error de -5, si está sobre D1 un error de 3, etc... Al leer la placa de sensores debemos calcular un error (distancia de la línea al punto medio de la placa de sensores), que se corresponde con la suma de los valores de todos los sensores a 1 dividida entre el número de sensores a 1.
A la hora de hacer divisiones con estos micros debemos evitar que en el resultado tengamos decimales, ya que hacer este tipo de operaciones le llevan mucho tiempo al microcontrolador, siempre que se divida hay que buscar resultados enteros.

Con estos valores siempre vamos a obtener números enteros de error al dividir (los sensores a 1 han de ser consecutivos). Si tengo 2 sensores a 1, por ejemplo 3 y 5, resto al primero 1 y se lo sumo al segundo, tengo 4 y 4 que es lo mismo que 2*4, que entre dos sensores activos obtengo error=4. Si tengo 3 sensores -1 , 1, y 3, resto dos al último y se lo sumo al primero y me queda 1,1 y 1 que es lo mismo que 3*1 y entre 3 activos queda el error=1, y así en adelante...

Por lo que una función para leer los sensores sería la siguiente:

char obtener_errorp(void)
{
    char errorp=0;
    unsigned char contador_sensor=0;

    if((PINC & 0x02) != 0) //I3 PC1 -7
    {
        errorp -= 0x07;
        contador_sensor++;
    }

    if((PINC & 0x04) != 0) //I2 PC2 -5
    {
        errorp -= 0x05;
        contador_sensor++;
    }

    if((PINC & 0x08) != 0) //I1 PC3 -3
    {
        errorp -= 0x03;
        contador_sensor++;
    }

    if((PINB & 0x10) != 0) //I0 PB4 -1
    {
        errorp -= 0x01;
        contador_sensor++;
    }

    if((PINB & 0x20) != 0) //D0 PB5 +1
    {
        errorp += 0x01;
        contador_sensor++;
    }

    if((PIND & 0x04) != 0) //D1 PD2 +3
    {
        errorp += 0x03;
        contador_sensor++;
    }

    if((PIND & 0x10) != 0) //D2 PD4 +5
    {
        errorp += 0x05;
        contador_sensor++;
    }

    if((PIND & 0x80) != 0) //D3 PD7 +7
    {
        errorp += 0x07;
        contador_sensor++;
    }

    if(contador_sensor != 0)
        return(errorp/contador_sensor);
    else
        return(0);
}

La función devuelve un valor que se corresponde con la distancia de la línea al centro de la placa de sensores, podemos tener valores comprendidos entre -7 y +7, cuando el robot esté en el centro el valor devuelto será cero. Si el  robot no lee ningún valor devuelve el valor cero, esto se debe cambiar devolviendo por ejemplo el valor -9 si el último sensor que se ha leído está a la izquierda y el robot ve todo blanco, y +9 si el último sensor leído estaba a la derecha. También se puede implementar un giro máximo a la izquierda o a la derecha cuando el robot pierda la línea.

De momento se deja así y  para comprobar la lectura de los sensores se hace el siguiente bucle principal:

    while ( 1 )
    {   
        velocidad = obtener_errorp();

        if(velocidad == 0)
        {       
            M1_forward(0);        //Motor derecho.
            M2_forward(0);    //Motor izquierdo.
        }

        else if(velocidad < 0)
        {   
            velocidad = velocidad*(-36);
               
            M1_forward(velocidad);        //Motor derecho. 
            M2_forward(0);                //Motor izquierdo.
        }

        else
        {
            velocidad = velocidad*(36);       
            M1_forward(0);            //Motor derecho.
            M2_forward(velocidad);    //Motor izquierdo.
        }

Tenemos la variable velocidad que recibe el valor de la llamada a la función anterior, obtener_error(), cuanto más alejada esté la línea del centro de la placa de sensores más rápido gira la rueda del motor correspondiente, para fijarnos que todo funciona correctamente pasamos la línea negra por toda la placa despacio, y vemos como el motor va aumentando o disminuyendo su velocidad según se aleja o se acerca la línea al centro. Código completo.

También un código para probar el robot sobre la pista a una velocidad lenta y sólo con error proporcional, para ver si es capaz de andar.... La rueda loca trasera la voy a quitar, ya que si se encuentra con superficies no lisas como la que tengo aquí el robot pierde tracción al tener 4 puntos de apoyo, por lo que habrá que equilibrar o quizás pensar en una nueva base, ya que el pvc expandido de 3mm tiene demasiada flexibilidad.

Video prueba de sensores y primeros pasos del robot.

La primera impresión es que no me gustan ni los sensores ni la base =(.

Para cualquier duda, idea: foro.