Cuando yo tenía 13 años, por el año 1981 tuve la gran suerte de que mis padres me regalaran por mi cumpleaños uno de los primeros ordenadores que salieron al mercado, al abrir el regalo me quedé impactado, era un Atari 400 nada más y nada menos, estaba en una caja plateada con las letras de colores degradados, al abrirla lo primero que hice fue oler su interior, el olor a electronica de la época era embriagador. Lo instalé rápidamente en mi habitación, tenía un televisor de tubo de 14 pulgadas que me venía perfecto, junto con el ordenador venía un cartucho para programar en basic, al encender la computadora sintonicé el televisor y al cabo de unos segundos ahí estaba la pantalla azul con su palabra READY junto con el cursor, el ordenador estaba listo y esperaba que yo le dijese algo para funcionar.
Desde ese mismo instante empecé una aventura con mi Atari , aprendi basic, me introduje en sus gráficos, disfruté con sus "player missile graphics" y en mí empezó una pasión por saber programar videojuegos y dominar aquella computadora maravillosa.
Pero en aquella epoca me topé con un problema, había poca literatura sobre mi máquina, no había internet y no podía conseguir por ningun sitio información sobre su sistema, su hardware, la programacion en ensamblador y su arquitectura, toda la información que tenía provenía de los propios manuales, alguna que otra revista de informática de la época y algún libro prestado sin mucha información.
Al cabo de un tiempo me empezó el gusanillo de la curiosidad con un conector que tenía en el costado derecho, ahí se podía conectar la unidad de cassette, la unidad de disco de 5 y 1/4 o la impresora.
Descubrí que ese conector con forma de trapecio y muchos pines se llamaba SIO PORT, tenía una curiosidad enorme de saber como funcionaba, de poder conectar en él alguna cosa que yo hiciera y poder controlarlo desde mi Atari.
Pero como dije antes no tenía información de la arquitectura de mi máquina y de cómo se podía acceder a ese puerto con programación.
Pasaron los meses, años y nunca conseguí como acceder al puerto SIO, al final desistí no solo por la falta de información sino también porque la computación avanzaba y otras máquinas sustituyeron el Atari, seguí estudiando otros sistemas y mi primera computadora la aparté para siempre.
Lo bonito de esta historia es que sigo conservando mi máquina y la misma curiosidad por saber como funciona el dichoso puerto, pues bien, hoy en el año 2020 y gracias a la información que puedo encontrar en internet pude realizar el proyecto que tenía en mente desde los 13 años: controlar algún dispositivo desde el Atari.
El proyecto que os presento en un robot controlado por Arduino, el chasis y los motores son de Lego y el control de los movimientos los hago desde un joystick conectado al Atari de 8 bits, en el antiguo ordenador he conectado al puerto SIO un emisor XBEE para poder enviar la información al robot.
EL CUERPO DEL ROBOT:
Lo primero que hice fue contruir la base del robot en Lego e instalarle dos motores de la serie POWER FUNCTIONS 8883 con un juego de engranajes.
Con sus dos ruedas es capaz de ir hacia adelante y hacia atrás, los giros los hace girando una rueda hacia adelante y la otra hacia atrás.
EL CONTROL DE LOS MOTORES:
Cada motor posee una caja reductora y 4 conexiones para funcionar, una de ellas es la alimentación, trabajan a 9V, la otra es la masa GND y los dos cables centrales llamados C1 y C2 son para el control de giro (foward y reverse). En mi robot los motores van alimentados a 11,1V, así utilizo la alimentación de una bateria LIPO directamente en ellos.
Batería LIPO de 11,1V. |
Conexiones cable motor Lego. |
En la entrada VMS se conecta la tensión de la bateria, el propio DRIVER posee un regulador de tensión a 5V para la propia lógica y en los conectores señalados como MOTOR A y MOTOR B se conectan los cables C1 y C2 del motor de Lego.
En los pines EN_A y EN_B se intruduce una señal PWM en cada uno para el control de la velocidad y en los pines IN1, IN2, IN3 Y IN4 se introduce la lógica para el control de giro, movimiento hacia adelante y movimiento hacia atrás.
EL PUERTO SIO, PINES, PROGRAMACIÓN Y CONEXIÓN A UN XBEE:
El puerto ATARI SIO (serial input/output) es la forma que tienen las computadoras Atari de 8 bits para la comunicación con sus periféricos, es un puerto serie anterior a los puertos de las computadoras actuales, pero se puede programar en ATARI BASIC para hacerlo compatible con los puerto serie actuales. Posee 13 pines y solo 4 de ellos los usaremos para el control del robot.
Puerto SIO.
Cable SIO con el Xbee. |
Uso dos XBEE series 2 para la transmisión de datos desde el Atari al robot. La sicronización de los dos módulos XBEE no lo explico aquí, hay muchas páginas que explican muy bien como sincronizarlos y empezar a trasmitir entre ellos.
También utilizo dos módulos para insertar el XBEE en él, lo podéis conseguir en Bricogeek o Sparkfun
También utilizo dos módulos para insertar el XBEE en él, lo podéis conseguir en Bricogeek o Sparkfun
Módulo explorer. |
La programación en ATARI BASIC del puerto SIO para poder usarlo como un puerto serie actual es muy sencilla, el fragmento importante es el siguiente:
53760 Tone of Voice 1 (SOUND 0)
53761 Distortion and Volume of Voice 1
53762 Tone of Voice 2 (SOUND 1)
53763 Distortion and Volume of Voice 2
53764 Tone of Voice 3 (SOUND 2)
53765 Distortion and Volume of Voice 3
53766 Tone of Voice 4 (SOUND 3)
53767 Distortion and Volume of Voice 4
53768 Tone "clock" control
53761 Distortion and Volume of Voice 1
53762 Tone of Voice 2 (SOUND 1)
53763 Distortion and Volume of Voice 2
53764 Tone of Voice 3 (SOUND 2)
53765 Distortion and Volume of Voice 3
53766 Tone of Voice 4 (SOUND 3)
53767 Distortion and Volume of Voice 4
53768 Tone "clock" control
Se configura a 9600 baudios gracias a los pokes 53767,53764, 53766 y 53768.
El poke 53770 resetea los bits 5 -7 del registro de estado del puerto serie en 53775 a uno.
El poke 53775 es el SKCTL, controla la configuración del puerto serie.
El poke 53773 es el serial out, si introducimos un número en la variable "A" saldrá por el puerto serie.
Como ejemplo, si queremos enviar al puero serie el caracter "F" escribiremos su código ASCII:
EL PROGRAMA EN ATARI BASIC:
El robot lo muevo a las órdenes de un joystick conectado al Atari, si muevo el joystick hacia adelante enviará en caracter "F" al puerto serie, si lo muevo hacia la derecha enviará el caracter "R", y así en las cuatro direciones, tambien he incluido el botón de disparo que al accionarlo suena un buzzer en el robot, el caracter que envío para el botón es el "C" y al dejar de apretarlo envía el caracter "N".
Utilizo una variable llamada FL (flag) para que cuando el joystick este en reposo envíe solo una vez el caracter "S", así si el joystick se queda en reposo mucho tiempo evito que continuamente se envíe en caracter "S" al puerto serie y sature el Xbee.
Para cada posición del joystick existe un número definido, de esta manera podemos saber en cualquier momento que movimiento se está ejecutando en él.
Las posiciones del joystick con sus respectivos números los vemos en el siguiente dibujo:
Con la información de las posiciones del joystick y el fragmento de configuración del puerto serie, he creado el siguiente programa en Atari Basic para detectar la posición del joystick y enviar un caracter al puerto serie.
Al ejecutar el programa se muestra una pantalla negra con letras grandes en amarillo indicando lo que el robot está haciendo en ese momento y con una ventana azul en la parte de abajo de la imagen se muestra el numero de movimiento del joystick:
EL PROGRAMA EN EL ARDUINO:
Ahora vamos a introducir el siguiente programa en un Arduino Uno, el funcionamiento es muy sencillo, recibe por el puerto serie los caracteres enviados por el Atari y dependiendo el caracter que recibe hace una llamada a una rutina de movimiento de los motores.
Dependiendo el caracter recibido hace la llamada a la rutina de motores cambiando los parametros de la función, son cuatro bits a nivel alto o bajo y lo que hace es enviar estos bits a través de los pines del Arduino 8, 9, 12 y 13 al driver de los motores.
Seguramente estaréis pensando que con dos pines del Arduino y un inversor nos ahorraríamos dos pines, pero quise evitar el inversor y hacerlo sencillo para que lo entendáis mejor.
Por los pines 10 y 11 envío el PWM para la velocidad de los motores, aquí se deben ajustar para cada motor, existe una tolerancia y los motores no giran a la misma velocidad con el mismo PWM, ajustarlo para que el robot vaya en línea recta.
En el pin 6 también se envía otro PWM para excitar el buzzer y pueda sonar al recibir el caracter 'C'.
El poke 53775 es el SKCTL, controla la configuración del puerto serie.
El poke 53773 es el serial out, si introducimos un número en la variable "A" saldrá por el puerto serie.
Como ejemplo, si queremos enviar al puero serie el caracter "F" escribiremos su código ASCII:
poke 53773, 70
Con estas 5 líneas de programación en ATARI BASIC podéis enviar cualquier caracter por el puerto serie del Atari, en mi proyecto se envía a un Xbee que a su vez lo transmite al robot a otro Xbee conectado a un Arduino Uno, este recibe el caracter y ejecuta lar órdenes que le he enviado.
Aprovecho el pin 10 del SIO PORT para alimentar a 5V el Xbee.
Esquema de los 4 pines usados en el puerto SIO al Xbee. |
El Xbee en el robot, recibe la información desde el Atari. |
EL PROGRAMA EN ATARI BASIC:
El robot lo muevo a las órdenes de un joystick conectado al Atari, si muevo el joystick hacia adelante enviará en caracter "F" al puerto serie, si lo muevo hacia la derecha enviará el caracter "R", y así en las cuatro direciones, tambien he incluido el botón de disparo que al accionarlo suena un buzzer en el robot, el caracter que envío para el botón es el "C" y al dejar de apretarlo envía el caracter "N".
Utilizo una variable llamada FL (flag) para que cuando el joystick este en reposo envíe solo una vez el caracter "S", así si el joystick se queda en reposo mucho tiempo evito que continuamente se envíe en caracter "S" al puerto serie y sature el Xbee.
Para cada posición del joystick existe un número definido, de esta manera podemos saber en cualquier momento que movimiento se está ejecutando en él.
Las posiciones del joystick con sus respectivos números los vemos en el siguiente dibujo:
Números asignados para cada movimiento del joystick, el 15 es en estado de reposo. |
Programa en Atari basic.
Al ejecutar el programa se muestra una pantalla negra con letras grandes en amarillo indicando lo que el robot está haciendo en ese momento y con una ventana azul en la parte de abajo de la imagen se muestra el numero de movimiento del joystick:
Programa en el Atari en ejecución. |
EL PROGRAMA EN EL ARDUINO:
Ahora vamos a introducir el siguiente programa en un Arduino Uno, el funcionamiento es muy sencillo, recibe por el puerto serie los caracteres enviados por el Atari y dependiendo el caracter que recibe hace una llamada a una rutina de movimiento de los motores.
Dependiendo el caracter recibido hace la llamada a la rutina de motores cambiando los parametros de la función, son cuatro bits a nivel alto o bajo y lo que hace es enviar estos bits a través de los pines del Arduino 8, 9, 12 y 13 al driver de los motores.
Seguramente estaréis pensando que con dos pines del Arduino y un inversor nos ahorraríamos dos pines, pero quise evitar el inversor y hacerlo sencillo para que lo entendáis mejor.
Por los pines 10 y 11 envío el PWM para la velocidad de los motores, aquí se deben ajustar para cada motor, existe una tolerancia y los motores no giran a la misma velocidad con el mismo PWM, ajustarlo para que el robot vaya en línea recta.
En el pin 6 también se envía otro PWM para excitar el buzzer y pueda sonar al recibir el caracter 'C'.
/* Control robot Lego vía Atari 8 bits v3.0 */ /* Sergio Curci 2020 */ #define pwm_motor_der 11 #define pwm_motor_izq 10 #define pwm_claxon 6 #define sentido_motor_d_bit0 13 #define sentido_motor_d_bit1 12 #define sentido_motor_i_bit0 9 #define sentido_motor_i_bit1 8 char dato; char bit0; char bit1; void setup() { Serial.begin(9600); pinMode(pwm_motor_der,OUTPUT); pinMode(pwm_motor_izq,OUTPUT); pinMode(pwm_claxon,OUTPUT); pinMode(sentido_motor_d_bit0,OUTPUT); pinMode(sentido_motor_d_bit1,OUTPUT); pinMode(sentido_motor_i_bit0,OUTPUT); pinMode(sentido_motor_i_bit1,OUTPUT); } void loop() { analogWrite(pwm_motor_der,110); analogWrite(pwm_motor_izq,110); if (Serial.available()>0){ dato=Serial.read(); switch (dato) { case 'F': motores(HIGH,LOW,LOW,HIGH); /* Mueve los motores hacia adelante */ break; case 'B': motores(LOW,HIGH,HIGH,LOW); /* Mueve los motores hacia atras */ break; case 'R': motores(LOW,HIGH,LOW,HIGH); /* Gira a la derecha */ break; case 'L': motores(HIGH,LOW,HIGH,LOW); /* Gira a la izquierda */ break; case 'S': motores(LOW,LOW,LOW,LOW); /* apaga los motores*/ break; case 'C': analogWrite(pwm_claxon,150); break; case 'N': analogWrite(pwm_claxon,0); break; } } } /* Rutina para enviar los bit a la placa de control
de motores y ejecutar los movimientos */ void motores(char d_bit_0, char d_bit_1, char i_bit_0, char i_bit_1){ digitalWrite(sentido_motor_d_bit0,d_bit_0); digitalWrite(sentido_motor_d_bit1,d_bit_1); digitalWrite(sentido_motor_i_bit0,i_bit_0); digitalWrite(sentido_motor_i_bit1,i_bit_1); }