Este documento está disponible en los siguientes idiomas: English Castellano Deutsch Francais Nederlands Portugues Russian Turkce Arabic |
por Katja and Guido Socher Sobre el autor:
Katja es la editora de la edicion alemana de LinuxFocux. Le gusta Tux, el cine, la fotografía y el mar.
Su pagina personal la podeis encontrar aqui.
Contenidos: |
Resumen:
En este artículo se propone la construcción de un pequeño robot de seis patas con capacidad para andar. El cual se controlara con Linux, utilizando para ello el puerto paralelo del PC.
Utilizando el puerto paralelo se puede controlar de forma similar otros dispositivos.
Los robots siempre nos han fascinado. Cuando encontramos un libro que incluia un kit para montar un pequeño robot del tipo insecto y que se llama Stiquito, nos entusiasmamos. Stiquito es un robot especial, anda sin la ayuda de ningun motor. Sus patas son cables con nitinol y de esta forma se desplaza de manera tan sileciosa como la hace un insecto. Pero despues de montarlo nos dimos cuenta que sus movimientos eran muy lentos debido ha que no habia suficiente fricción con la superficie por la que se desplazaba. Por suerte, el libro incluia descripciones de diseños de otros robots lo que nos inspiro la construcción del robot que os vamos a describir en este artículo.
Para contruir el robot necesitaremos el siguiente material:
Fig 1: Placa |
Fig 2: alicates de punta curva |
Para construir el cuerpo necesitas tres partes de la placa de circuito: una de 6x6 agujeros y dos de 6x7 agujeros. Ademas de 4 cm del tubo de laton junto con 3,7cm de cable de música.
Fig 4: La columna vertebral y el powerbus
Corta el tubo de latón en piezas de 8 , 17.5 y 8mm tal como se muestra en la figura.
Puedes cortarlo deslizando el tubo sobre el cuchillo y entonces curvandolo. El tubo se cortara cuando le hagas una muesca con el cuchillo. Es importante que el tubo del medio sea ligeramente mas largo que la placa de 6x6 agujeros. Corta unos 3.7 cm de cable músical. Ha de ser unos 3 mm mas largo que los tres tubos juntos. Introduce el cable en el interior de los tubos.
El tubo del medio tendra la capacidad de girar cuando los otros dos esten soldados a la cuerda de música.
Fig 5: soldar la placas a la columna
El tubo del medio se suelda a la placa de 6x6 agujeros. Debes ir con cuidado por que puede girar. Los otros dos tubos se sueldan a las otras dos placas.
Ahora coje la placa más pequeña, la de 2x7 agujeros.
Se pone de canto sobre la mitad del tubo. Realizar una muesca en la placa con el cutter. Colocar la parte media del tubo en la parte media de la placa y soldar el conjunto (Observar la figura)
Fig 6: Añadiendo la placa de circuito pequeña
Lija el tubo de 1mm y cortalo varias piezas de 4mm largo. Haz rodar el tubo sobre el filo del cuchillo de cocina y ves flexionandolo.
Necesitaras 16, pero mejor corta alguno más.Estos tubos se utilizarán como tope donde atar el cable de litinol.
Antes de nada, vamos a hacer una pruebas con alguno de los tubos cortados: Pon el final del nitinol en el tubo de 1mm de diámetro externo y apreta con el alicate de punta curva. A esto se le llama rizar o crimpar. Procura comprar un buen alicate, por que se ha de realizar un gran fuerza sobre el tubo. Con el fin de tener un buen contacto eléctrico lija el final del cable de nitinol.
Vamos a cablear con el cable nitinol para poder mover las patas de arriba a abajo.
Fig 7: "el puente"
Coloca el nitinol como si quisieras construir un puente. Empiezas en un lado. Pon el cable en el último agujero de la izquierda. Haces un nudo en el cable de nitinol(para asegurarnos una buena conexión) , pasa uno de los tubitos de 4mm y vuelve apasar el cable por el tubito y tensalo bien tenso. Pasa el cable por el segundo agujero de la parte superior lado izquierdo y lleva el cable atraves del último agujero posible. De nuevo en la parte de debajo de la placa haz un nudo en el cable de nitinol. (ver Fig 7). El nitinol debe estar tenso pero no mucho. Si presionas ligeramente se debe mover de 2 a 4 mm. Si no esta lo suficientemente tenso o lo esta demasiado, más tarde el robot no se movera correctamente. Suelda los tubitos a la placa.
Haz lo mismo en el otro lado.
Antes de continuar vamos a ver si funciona. Utiliza una pila de 1.5V del tipo AA mignon y conectala a uno de los cables de nitinol. Cuando el cable se contraiga, la parte media del cuerpo girará entre 10 y 20 grados.¡ESTA PRUEBA HA DE DE DURAR COMO MUCHO 1 SEGUNDO! Por que puedes quemar el cable por sobre calentamiento.
Fig 8: la forma del cable
Para las patas vamos a cortar 3 trozos de cable de música de 10 cm. En cada uno de los trozos doblar el cable 1.5cm en cada lado . Soldamos cada pata una en cada parte del robot. Procurar que queden paralelas.
Fig 9, 10: las patas montadas sobre el robot
Ahora debes cablear el nitinol sobre las seis patas.
Fig 11: añadir los actuadores
Pasa el cable de nitinol por la parte de arriba atraves de uno de los tubitos y por el un agujero del circuito impreso. La longitud del cable de música es de 3 agujeros.
Mantenlo tirate (mira el dibujo de arriba).
Bobina sobre el cable de música hasta que lleges al doblez de la pata.
Pon el cable de nitinol sobre el y bobinalo fuertemente. Ahora viene la parte más dificil. Manten el robot y dobla las patas. El cable de músia hace el efecto opuesto al del nitinol. Para que trabaje el cable de nitinol no debe estar suelto.
El cable de música debe tirar atraves de uno de los agujeros de la placa hacia el nitinol y la parte bobinada debe estar solda a la pata.
Fig 12: el nitinol y el cable de música al mismo nivel
Comprueba que el nitinol y el cable de música estan igualados.
Cuando el nitinol se contrae las patas no se han de mover de arriba a abajo. La pierna se mueve hacia atras.
Haz lo mismo con las otras patas.
El conjunto formado por las patas y el cable músical junto con los tubitos de latón actuan como un bus de potencia y ademas hay una conexión electrica entre todos ellos.
La parte dentral del robot tiene mayor movilidad al poder rotar y ademas no tiene una buena conexion. Esto último se mejora utilizando uno de los tubitos de 4mm y enrrollando un trozo de cable de cobre de 3 cm y 0.1mm de diámetro obteniendo una pequeña bobina. Extrae el tubito y suelda la bobina entre la mitad de las patas centrales y una de las exteriores. La forma de bobina del cable garantiza una mayor flexibilidad.
Cuando el robot este listo, soldaras diversos cables de cobre barnizado de 0.1mm de diámetro y de 0.5m de longitud o más. Necesitaras 9 cables : 6 para las patas , 2 para subir y bajar y otro para la masa. Uno de los extremos se soldará a un conctor que se conectará al correspondiente conector del circuito driver.
Nuestro robot esta diseñado para andar de forma tripode. Es decir,
3 patas tocan el suelo (dos de un lado y una del otro), mietras que las otras 3 estan en el aire. Cuando el robot anda, las 3 patas que tocan el suelo se mueven en una dirección, mientras las que estan en el aire se mueven en dirección opuesta.
Fig 13: La manera de andar
Esta placa te permite tener el control de los actuadores desde el PC a traves del puerto paralelo.
Mientras desarrollamos el programa, testeamos su funcionamiento
controlando leds. Cuando nos aseguramos que la simulación de los movientos con los leds era correcta, conectamos los cables del robot a la placa de control.
El robot es un ser hambriento, se necesitan de 200 a 250 mA de corriente
para contraer el cable de nitinol. 3 cms de cable de nitinol tienen una impedancia de 7 Ohms. Antes de dar potencia al circuito, hay que poner en marcha el programa para inicializar el port paralelo y prevenir que se estropee el cable de nitinol. Esto se hace asi por que la bios activa las salidas del puerto paralelo a cualquier valor aleatorio. En esta circunstacia se puede quemar el cable de nitinol, ya que si circula corriente más de 1 segundo se calienta y pierde sus propiedes cuando se sobrepasa 1.5 veces el tiempo necesario para calentarse..
El esquema del circuito:
Fig 14: esquema
Tal como puedes ver en el circuito de encima utilizamos un regulador de tensión integrado. Así nos aseguramos una tensión estable y de paso se protege el puerto. Como alimentador externo se puede utilizar cualquiera que permita suministrar entre 6Vdc y 24Vdc. El 7805 es un regulador estandar. Se ha de tener en cuenta que los dos condesadores , 470uF y 0.1uF, han de estar cerca del regulador como medida de protección y evitar que se estropee.
Este diseño se repite 8 veces : para controlar cada pata y 2 para los
movimientos de las patas de arriba y abajo.
Se utilizaran transistores NPN del tipo Darlington poruqe el robot consume
bastante corriente. El BC875 o el BC618 pueden comuntar unos 500mA.
La resistencia de 47K conectada a la entrada nos asegura que cuando esta
quede abiertaon (por ejemplo con el ordenador desconectado) equivalga a "off".
Los niveles de tensión del puerto paralelo son : 4 V para el estado "on"
y por debajo de 1V para el estado "off". El transistor trabajoa en modo interruptor.
Las resitencias de 15 Ohm limitan la corriente y protege a las patas del robot y al
transistor. Los LEDs nos muestran el estado, ya sea on o off.
Debajo teneis el circuito. Para poder ver bien los LEDs rojos (los que estan en
paralelo con los actuadores del robot) se utilizan del tipo transparente.
Las resistencias de 15 Ohms las hemos fabricado con rollos de cable de
constantan. Esto ha sido asi, porque teniamos mucho y no resultaba más barato
que comprarlas hechas.
El puerto paralelo esta diseñado para servir como puerto de salida de datos del Pc y para conectar la impresora. Algunos puertos permiten la transmisión bidireccional de datos. En esta aplicación solo lo utilizaremos para enviar datos. En un posterior artículo se añadiran sensores al robot y utilizaremos el modo de entrada de datos de este puerto. El conector de este puerto tiene 25 pins de lso cuales se utilizan 9. Ocho lineas corresponden a datos y la otra es masa. Acontinuación presentamos la asignación de pines:
25 PIN D-SUB Hembra al PC. Pin Name Dir Description 1 STROBE [-->] Strobe 2 D0 [-->] Data Bit 0 3 D1 [-->] Data Bit 1 4 D2 [-->] Data Bit 2 5 D3 [-->] Data Bit 3 6 D4 [-->] Data Bit 4 7 D5 [-->] Data Bit 5 8 D6 [-->] Data Bit 6 9 D7 [-->] Data Bit 7 10 ACK [<--] Acknowledge 11 BUSY [<--] Busy 12 PE [<--] Paper End 13 SEL [<--] Select 14 AUTOFD [-->] Autofeed 15 ERROR [<--] Error 16 INIT [-->] Initialize 17 SELIN [-->] Select In 18 GND [---] Signal Ground 19 GND [---] Signal Ground 20 GND [---] Signal Ground 21 GND [---] Signal Ground 22 GND [---] Signal Ground 23 GND [---] Signal Ground 24 GND [---] Signal Ground 25 GND [---] Signal GroundEl driver se conecta al pin 18 (GND) y a los pines de datos(2-9).
==== pprobi.c ===== /* vim: activa sw=8 ts=8 si : */ /* * Este programa es sofware libre; puedes redistribuirlo y/o modificarlo * bajo los terminos de la licencia publica GNU . * Visitar http://www.gnu.org/copyleft/ para mayores detalles. * * Escrito por Katja Socher <katja@linuxfocus.org> * and Guido Socher <guido@linuxfocus.org> * */ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <math.h> #include <signal.h> #include "robi.h" /* ----------- */ static int opt_r=0; static int fd=0; /* ----------- */ /* ----------- */ void help() { printf("pprobi -- Software de control para el robot andante\n\ USO: pprobi [-h] [parport-device]\n\ \n\ OPCIONES:\n\ -h HELP\n\ -r puesta a cero de los pins del port paralelo y exit\n\ \n\ El device es por defecto /dev/parport0 \n\ "); #ifdef VERINFO puts(VERINFO); #endif exit(0); } /* Evento : todo apagado y fin */ void offandexit(int code) { robi_setdata(fd,0); set_terminal(0); exit(0); } /* ----------- */ int main(int argc, char **argv) { int state,bpat,alternate; char *dev; /*Lo siguiente es utilizado por getopt: */ int ch; extern char *optarg; extern int optind; extern int opterr; opterr = 0; while ((ch = (char)getopt(argc, argv, "hr")) != -1) { switch (ch) { case 'h': help(); /*no hay ruptura, desde help no se vuelve */ case 'r': opt_r=1; break; case ¿': fprintf(stderr, "serialtemp ERROR: Opción no diponible. Ayuda : -h.\n"); exit(1); /*sin acción */ } } if (argc-optind < 1){ /* sin argumentos */ dev="/dev/parport0"; }else{ /* el usuario a asignado un argumento */ dev=argv[optind]; } fd=robi_claim(dev); /* robi_claim autochequeo de errores */ /* Se captura las señales INT y TERM y se ponen todas la lineas de datos a cero antes de * terminar */ signal(SIGINT, offandexit); signal(SIGTERM, offandexit); /* Inicialización de la linea de datos parpprt a cero: */ robi_setdata(fd,0); set_terminal(1); /* set_terminal tiene su propio sistema de detección de errores */ state=0; alternate=0; if (opt_r){ offandexit(1); } while(1){ ch=getchoice(); if (ch!=0) state=ch; if (ch == ' '){ printf("Stop\n"); robi_setdata(fd,0); usleep(500*1000); } if (ch == 'q'|| ch == 'x'){ printf("Quit\n"); break; } if (state=='l'){ /*derecha */ printf("Desplazamiento a la derecha\n"); walkright(fd); } if (state=='h'){ /*left */ printf("desplazamiento a la izquierda\n"); walkleft(fd); } if (state=='j'){ printf("marcha atras\n"); walkback(fd); } if (state=='k'){ if (alternate){ printf("desplazamiento hacia a\n"); walkstraight_a(fd); }else{ printf("esplazamiento hacia b\n"); walkstraight_b(fd); } alternate=(alternate +1) %2; } } /* Si llegado aqui se ha pulsado q */ set_terminal(0); return (0); } ==== robi.c ===== /* vim: set sw=8 ts=8 si : */ /* * Este programa es sofware libre; puedes redistribuirlo y/o modificarlo * bajo los terminos de la licencia publica GNU . * Visitar http://www.gnu.org/copyleft/ para mayores detalles. * * Escrito por Katja Socher <katja@linuxfocus.org> * and Guido Socher <guido@linuxfocus.org> * */ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <sys/types.h> #include <sys/time.h> #include <fcntl.h> #include <unistd.h> #include <signal.h> #include <linux/ppdev.h> #include <sys/ioctl.h> #include <termios.h> #include "robi.h" /* como printf pero se abandona el programa*/ static int die(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vprintf(fmt, ap); va_end(ap); exit(1); } /* Se coge un caracter de stdin * Si el caracter leido es diferente de cero, se devuelve no cero * Asignación de las flechas: * <- = h * -> = l * v = j * ^ = k */ int getchoice() { int c; char s[20]; if (fgets(s,20,stdin)){ c=s[0]; switch (c){ case 0x1b: /* ESC */ if (s[1] == 0x5b){ /* si se pulsan las flechas */ switch (s[2]){ case 0x41: /*flecha arriba*/ c='k'; break; case 0x42: /*dflecha abajo*/ c='j'; break; case 0x44: /*tecla l */ c='h'; break; case 0x43: /*tecla r */ c='l'; break; default: c=0; } }else{ c=0; } break; case ' ': case 'h': case 'j': case 'k': case 'l': case 'q': case 'x': break; default: c=0; } return(c); } return(0); } /* Activa el terminal en modo no canonico * o se resetea es terminal. * Uso: set_terminal(1) para modo canonico */ int set_terminal(int canonical) { static struct termios originalsettings; struct termios newsettings; static int origok=0; /* sActivo si originalsettings es valido */ if (canonical){ /* Guarda los parametros y se activa el modo canonico*/ tcgetattr(fileno(stdin),&originalsettings); newsettings=originalsettings; newsettings.c_lflag &= ~ICANON; newsettings.c_lflag &= ~ECHO; newsettings.c_cc[VMIN]=0; /* do not block */ newsettings.c_cc[VTIME]=1; /* 100 ms */ if (tcsetattr(fileno(stdin),TCSANOW,&newsettings) !=0){ die("ERROR: No se han podido activar los atributos de stdin\n"); } origok=1; }else{ if (origok){ /* Recuperando los datos programados */ tcsetattr(fileno(stdin),TCSANOW,&originalsettings); } } return(0); } /* abre el dispositivo /dev/parportX y lo captura. * Uso: fd=robi_claim("/dev/parport0"); * El valor devuelto es un descriptor de fichero usado por otras * funciones como robi_setdata */ int robi_claim(char *dev) { int fd,i; fd = open(dev, O_RDWR ); if (fd < 0) { die("ERROR: no se puede comunicar con el dispositivo %s\n",dev); } i=0; /* wNecesitamos permiso y no activar las lineas de control */ /*ioctl(fd, PPEXCL, &i)&&die("ERROR: fallo en la busqueda de permisos\n");*/ ioctl(fd, PPCLAIM, &i)&&die("ERROR: fallo de comunicación con parport\n"); return(fd); } /* desplazamiento a la izquierda */ int walkleft(int fd) { /* Las patas B al suelo*/ robi_setdata(fd,LEGBD); usleep(400 *1000); /* all A legs 1 step */ robi_setdata(fd, LEGB1 | LEGB3 ); usleep(1100 *1000); /* Patas A al suelo, enfriando B*/ robi_setdata(fd,LEGAD); usleep(400 *1000); robi_setdata(fd,0); usleep(1000 *1000); return(0); } /* Desplazamiento a la derecha */ int walkright(int fd) { /* patas A al suelo */ robi_setdata(fd,LEGAD); usleep(500 *1000); robi_setdata(fd, LEGA3 | LEGAD); usleep(300 *1000); /* all A legs 1 step */ robi_setdata(fd, LEGA1 | LEGA3 ); usleep(1100 *1000); /* patas B al suelo , enfriamiento de A*/ robi_setdata(fd,LEGBD); usleep(400 *1000); robi_setdata(fd,0); usleep(1000 *1000); return(0); } /* Dando un paso atras con 3 patas */ int walkstraight_a(int fd) { /* patas A al suelo*/ robi_setdata(fd,LEGAD); usleep(800 *1000); /* all A legs 1 step */ robi_setdata(fd, LEGA1 | LEGA2 | LEGA3 ); usleep(1000 *1000); /* patas B al suelo, se enfria A*/ robi_setdata(fd,LEGBD); usleep(500 *1000); robi_setdata(fd,0); usleep(1200 *1000); return(0); } /*Desplazamiento hacia adelante*/ int walkstraight_b(int fd) { /* patas B al suelo */ robi_setdata(fd,LEGBD); usleep(400 *1000); /* topas la patas B una paso */ robi_setdata(fd,LEGB1 | LEGB2 | LEGB3); usleep(1000 *1000); /* A down and cool */ robi_setdata(fd,LEGAD); usleep(800 *1000); robi_setdata(fd,0); usleep(1200 *1000); return(0); } /* Desplazamiento con todas las patas un paso hacia atras */ int walkback(int fd) { /* primeras patas A hacia delante/ robi_setdata(fd,LEGAD); usleep(800 *1000); /* Todas las patas B dan un paso en el aire*/ robi_setdata(fd, LEGB1 | LEGB2 | LEGB3 ); usleep(500 *1000); /* primeras patas B al suelo, se enfria A*/ robi_setdata(fd,LEGBD); usleep(500 *1000); /*todas la patas A un paso en el aire*/ robi_setdata(fd,LEGA1 | LEGA2 | LEGA3); usleep(500 *1000); /* A down and cool */ robi_setdata(fd,LEGAD); usleep(800 *1000); robi_setdata(fd,0); usleep(1000 *1000); return(0); } /*---------*/ /* Se escribe un patron de bits en el puerto * Uso: rc=robi_setdata(fd,bitpat); * Valor devuelto 0 */ int robi_setdata(int fd,unsigned char bitpat) { int rc; rc=ioctl(fd, PPWDATA, &bitpat); return(rc); } ==== robi.h ===== /* vim: set sw=8 ts=8 si et: */ #ifndef H_ROBI #define H_ROBI 1 #define VERINFO "version 0.2" /* la primera cosa que necesitas hacer: */ extern int robi_claim(char *dev); /* Se escribe un patron de bits en el puerto: */ extern int robi_setdata(int fd,unsigned char bitpat); /* entrada y funciones del terminal */ extern int set_terminal(int canonical); extern int getchoice(); extern int walkstraight_a(int fd); extern int walkstraight_b(int fd); extern int walkback(int fd); extern int walkleft(int fd); extern int walkright(int fd); /* Asignación de datos a las patas: * A1------=------B1 * = * = * B2------=------A2 * = * = * A3------=------B3 * * * Pin para poner las patas A al suelo= AD * Pin para poner las patas A al suelo= BD * * Puerto paralelo Pata * ------------------------- * data 0 A1 * data 1 A2 * data 2 A3 * data 3 AD * data 4 B1 * data 5 B2 * data 6 B3 * data 7 BD */ #define LEGA1 1 #define LEGA2 2 #define LEGA3 4 #define LEGAD 8 #define LEGB1 16 #define LEGB2 32 #define LEGB3 64 #define LEGBD 128 #endif
El software usa el interface programable ppdev de la versión 2.4.x del Kernel (Necesitaras la versión 2.3.x o 2.4.x del Kernel. No trabajará con versiones anteriores del kernels). Este interface permite programar de manera sencilla el port paralelo. En versiones anteriores del kernel se debia escribir un nuevo modulo o utilizar un metodo que tan solo permitia al root ejecutar el programa. El interface ppdev usa el dispositivo /dev/parport0 . Configurando los provilegios se controla quienes pueden usar el puerto paralelo.
Se compilaran conjuntamente PARPORT y PPDEV, asi se obtiene un nuevo módulo del kernel. Y el fichero .config quedará :
# # Soporte para el puerto paralelo # CONFIG_PARPORT=m CONFIG_PARPORT_PC=m CONFIG_PARPORT_PC_FIFO=y # CONFIG_PARPORT_PC_SUPERIO no activo # CONFIG_PARPORT_AMIGA no activo # CONFIG_PARPORT_MFC3 no activo # CONFIG_PARPORT_ATARI no activo # CONFIG_PARPORT_SUNBPP no activo CONFIG_PARPORT_OTHER=y CONFIG_PARPORT_1284=y # # Caracteres # CONFIG_PPDEV=m #
Lo primero que hace el programa es inicializar el port con el comanto ioctl de PPCLAIM. Entonces activa el terminal en modo no canonico.
De esta manera se controla desde el teclado sin necesidad de pulsar siempre el enter despues de cada dato. El programa entra en un bucle esperando las ordenes para que el robot ande. Si no recibe ninguna orden el programa mantiene la ultima orden ( por ejemplo : manteniendo el robot andado recto).
El comando ioctl(fd, PPWDATA, &bitpat); se utilixa para activar las salidas a un valor determinado.
Los pines del robot se conctan de la siguiente manera al driver:
Legs: A1------=------B1 = = B2------=------A2 = = A3------=------B3 Pin to set A-legs to ground= AD Pin to set B-legs to ground= BD Correspondencias entre la salida de datos y el driver: data 0 A1 data 1 A2 data 2 A3 data 3 AD data 4 B1 data 5 B2 data 6 B3 data 7 BDEl Data 0 es la salida del circuito driver que se conecta al pin 2 (D0) dek puerto paralelo.
Esperamos que disfrutes construyendo este robot. Haznos saber tus experiencias, sobre todo si realizas un diseño diferente
|
Contactar con el equipo de LinuFocus
© Katja and Guido Socher, FDL LinuxFocus.org Pinchar aquí para informar de algún problema o enviar comentarios a LinuxFocus |
Información sobre la traducción:
|
2001-06-19, generated by lfparser version 2.9