Volver a Robótica

Robot controlado por el MC8051

¿Qué hace el Robot?.

Básicamente se desplaza en línea recta y no cambia su estado hasta que no se den dos condiciones:

Si el robot se traba o choca contra algún obstáculo, dobla sus ruedas delanteras hacia la derecha y retrocede 6 pasos. Una vez que termino esta rutina vuelve a la lógica anterior (avanza hasta que...), pero apuntando levemente en otra dirección. Todo esto parece funcionar bien, pero existe la posibilidad de que cuando retrocede se trabe o choque con algo antes de terminar los 6 pasos. Si esto ocurriera, el robot deja de retroceder y vuelve a la lógica anterior. Parece algo sin sentido, pero funciona, por que repite esta secuencia todas las veces que sea necesario hasta que el robot logre un cambio significativo en su dirección y evite el obstáculo, para entender mejor esto, veamos un dibujo.


El robot consiste en un carro con cuatro ruedas, de las cuales dos son de tracción y dos de dirección. Está construido con Lego, estos ladrillitos facilitaron un montón la parte mecánica del proyecto, por que están pensados para este tipos de proyectos (ver figura 1). Volviendo al robot, enumeremos los sensores:

Figura 1

El robot está controlado por el Micro Controlador 8051 de Dallas. El programa para controlar el robot lo escribo en la PC y después lo "bajo" al MC por medio de un puerto serie (el RS232). El Micro tiene una memoria ROM de 4 Kbytes y una RAM de 4 Kbytes. La memoria de ROM tiene quemado un BootStrap, un programa que le permite cargar programas en la memoria RAM a través del puerto serie. La memoria ROM está abajo de la memoria RAM, es decir, la memoria ROM está desde la dirección 0 a la 4000 y la memoria RAM de la dirección 8000 a la 16000 (esto es aproximado). La memoria RAM podría estar desde la dirección 4000 a la 8000, pero no es así por razones de comodidad en el hard, que no causan problemas en el soft, solamente hay que tener en cuenta estos parámetros al leer y escribir memoria.

La placa donde está montado el micro, permite utilizar:

La parte electrónica y mecánica del proyecto, se puede apreciar en los siguientes esquemas:

Esquema General

Figura 2

Sensor que detecta la posición de las ruedas de dirección

Este sensor está compuesto por un led infrarrojo y tres fototransistores. Los fototransistores están en un agujero cada uno de un ladrillito, que está en la parte fije del sistema de dirección. El emisor de luz infrarroja está en un agujereo de un ladrillito de la parte móvil del sistema de dirección. Cuando las ruedas están derechas, el led IR ilumina el fototransistor del medio. Cuando las ruedas se mueven, se iluminan los fototransistores de los costados.

Los fototransistores están conectados al MC, y le envían pulsos eléctricos cuando están iluminados. De esta forma se entera en que posición, aproximada, están las ruedas. Para entender mejor el sensor, veamos la figura siguiente:

Figura 3

Sensor de luz y conversor analógico digital

Este sensor de luz, con ayuda de una linterna que se prende y se apaga, me permite detectar obstáculos antes de chocarlos. La linterna se controla desde el MC, entonces puede hacer mediciones con la linterna prendida y con la linterna apagada. Si las mediciones con la luz apagada son de menor intensidad que las mediciones con la luz prendida quiere decir que estoy viendo el reflejo de algo.

El sensor de luz no es un fototransitor al aire libre, si no que está dentro de un tubo negro, de unos 5 cm de largo, para que sea bastante direccional.

Antes de poder prender o apagar la linterna, lo que hacía era simplemente ver luz, y cuando sobrepasaba una intensidad determinada, esquivaba. El problema era que no se calibraba para distintos ambientes con más o menos luz.

El sensor de luz es muy sencillo, pero el problema es transformar esta magnitud análoga en un número binario. Para eso está el Conversor Analógico-Digital (ADC). Este conversor necesita un pequeño programa que lo ayude, que se explica en la figura 4.

Figura 4

Sensor que cuenta los pasos

Este sensor es muy sencillo, y es una rueda con 5 agujeritos, que interrumpen el paso de luz entre un led y un fototransistor. El fototransistor está conectado a un pin del puerto E, el pin que activa la interrupción externa numero 0. De esta forma cada vez que el fototransistor recibe luz, el programa que está corriendo en el MC se detiene, y se hace un JMP a la rutina de la interrupción. Una vez que la rutina termina de hacer lo suyo retorna al curso normal del programa.

Esto se ve más en detalle, en la parte del informe que explica la programación del MC.

La interface del sensor es igual a la fracción señalada en la figura 3.

Circuito interface de los motores

Sobre este punto no hay mucho que decir, es simplemente armar el circuito, toda la parte de control de los motores queda a cargo del MC. Más adelante se explica como.

Figura 5

Interface de la linterna

Es el mismo caso que el anterior, el circuito es muy sencillo y todo queda a cargo del MC, todo se verá mas adelante cundo veamos la programación del Robot.

Figura 6

Disposición de patas de los transistores e integrados

Programación del Robot

Para entender mejor la programación del micro, veamos ejemplos de programas sencillos, es decir no ver el programa final de golpe. Además no voy a explicar todas las virtudes del Micro primero por que llevaría un libro exclusivo a la descripción del mismo. Por otro lado, las características que sé las voy a describir a medida que aparezcan a lo largo del desarrollo del proyecto.

El programa Motor01.asm hace andar un motor a distintas velocidades sin usar los timers

$MOD51 ; Le indica al ensamblador de que modo de va a trabajar
Port1 EQU 0E000h ; En esta linea le dice que Port1 equivale al numero 0E000 (hexa)
Port2 EQU 0E001h ; Lo mismo para Port2 pero con el numero 0E001
Port3 EQU 0E002h ; y lo mismo para Port3. Esto equivale a los #define de C
; Estos números son las direcciones del puerto A, B y C ; respectivamente.
; Estas equivalencias se hacen para más comodidad en el manejo ; del programa
PrtMode EQU 0E003h ; Esta es la dirección para setear el modo de trabajo de los puertos
ORG 4023h ; Lugar de origen del programa (direccion de memoria)
;--- Main ---------
Top: ; Declara un label, es decir un lugar a donde puedo hacer un JMP ; (GOTO)
CALL SetP ; Llama a la rutina que inicializa o "setea" los puertos
MOV DPTR, #Port1 ; El Data Pointer (DPTR) apunta a la dirección Puerto1 ; (el puerto A).
Loop:
CALL Delay ; Llama a una rutina que pierde tiempo
MOV A, #01h ; En el acumulador pone el valor 1 (hexa)
MOVX @DPTR, A ; Al lugar donde apunta el Data Pointer le copia el acumulador, es ; decir pone un 1 en el puerto A (Prende el motor).
CALL Delay ; Llama de nuevo la rutina que pierde tiempo
MOV A, #00h ; Pone un 0 en el acumulador
MOVX @DPTR, A ; Copia el acumulador al puerto A, es decir apaga el motor
JMP Loop ; Salta al label Loop, empieza todo de nuevo.
;------------------------------------------------------------------------------
SetP: ; Rutina que setea los puertos
MOV DPTR, #PrtMode ; El Data Pointer apunta a la dirección donde está el modo de los ; puertos
MOV A, #80h
MOVX @DPTR, A ; Todos los puertos de entrada.
RET ; Cuando se lo llama con la instrucción CALL, de ve tener esta ; sentencia al final, que permite retornar al lugar desde donde se ; llamo a la rutina (Esto no sirve para la sentencia JMP).
;-------------------------------------------------------------------------------
Delay: ; Rutina que pierde tiempo 
MOV R0, #0FFh ; Al registro 0 le pone valor 255 (FF hex); hay 8 resgistros de 1 ; byte cada uno
Big: 
DEC R0 ; le resta uno a R0 (DEC= Decrementar).
MOV R1, #0FFh ; Al registro 1 le pone valor 255 (FF hex).
Small:
DEC R1 ; Le resta uno a R1
CJNE R1, #00h, Small ; Pregunta si R1 es igual a 0, si no es igual a 0 salta a small es ; decir, le resta uno a R1 hasta que llegue a 0
CJNE R0, #00h, Big ; Hace exactamente lo mismo con R0
; De esta forma ejecuta FF x FF veces sin hacer nada, pierde ; tiempo
RET ; Una vez que R0 llego a 0, vuelve al lugar de donde la llamaron
CodeEnd EQU $ ; Fin del programa
; XSEG AT CodeEnd
; buff: DS 1
END

El programa lo que hace es enviar una corriente pulsante por un pin del puerto A, esta corriente es amplificada por el circuito interface. La pulsación de la corriente es lo que logra las distintas velocidades del motor. Para variar la velocidad, hay que cambiar los valores de los registros 0 y 1, de este modo los pulsos van mas rápidos o mas despacio, pero existe un problema, el programa varía el tiempo entre pulso y pulso y el ancho del pulso, nosotros no queremos eso, sino que queremos un pulso de ancho fijo y solamente variar la distancia entre pulso y pulso. 

Figura 7

Insisto en esto por que los motores que uso en el proyecto necesitan recibir corriente por un tiempo mínimo para poder moverse. Si yo achico la distancia entre pulsos y el ancho del pulso, llega un momento que el motor no se mueve. Pero si tengo un pulso de ancho fijo, por más que achique la distancia entre pulsos, el motor no se va a detener.

Para lograr que el programa haga esto, se le pueden hacer varias modificaciones, un de ellas es hacer otra rutina igual a delay, pero que sea un retardo fijo para el ancho del pulso. Pero lo que se hizo fue usar las interrupciones y los timers. ¿Qué es una interrupción? Se la puede definir como un evento determinado que te lleva a ejecutar otra parte del programa. Por ejemplo, yo hago una interrupción que cuando un pin determinado de algún puerto, cambie de nivel, el programa haga un JMP a una sección de código que me incrementa una variable y luego retorna al punto del programa donde se produjo la interrupción. Este sería el principio de un contador de pasos. Nótese la gran ventaja de las interrupciones, ya que yo no debo fijarme cada tanto el estado del pin (por ejemplo), si no que la interrupción "me avisa" al desviarme a cierta sección de código de mi programa.

Pero hay un detalle, las interrupciones no se activan ante cualquier evento, solo ante algunos, que en el caso del MC 8051 son:

La interrupción que nos interesa es la interrupción de los timers.

La rutina que maneja los timers para mandar los pulsos a los motores están en el archivo Motor02.asm

Volver a Robótica