|
|
Cet article est disponible en: English Castellano Deutsch Francais Nederlands Portugues Russian Turkce Arabic |
par Katja et Guido Socher <katja(at)linuxfocus.org, guido.socher(at)linuxfocus.org> About the authors: Katja est l'éditrice Allemande de LinuxFocus. Elle aime Tux, les films et la photographie et la mer. Sa page personnelle est ici. Guido est fan de Linux de longue date et il l'aime parce qu'il est conçu par des gens honnêtes et ouverts. C'est aussi une des raisons pour laquelle nous l'appelons "open source". Sa page personnelle est linuxfocus.org/~guido. Traduit en Français par: John Perr <johnperr(at)linuxfocus.org> Sommaire: |
Résumé:
Dans cet article, nous construisons un petit robot marcheur à six pattes
qui peut être contrôlé avec un PC sous Linux en utilisant l'interface parallèle.
D'autres appareils peuvent être pilotés de la même manière par cette interface.
Les robots nous ont toujours fascinés et nous avons été très excités lorsque nous avons trouvé, il y a quelques temps; un livre sur les robots qui incluait un kit pour construire un petit robot insectoïde appelé Stiquito. Stiquito est un robot un peu spécial car il n'a pas de moteur mais marche grâce à ses pattes faites de nitinol. De cette façon, il progresse en silence comme un véritable insecte. Lors de sa construction, nous avons cependant noté qu'à cause du manque d'adhérence de la surface sur laquelle il marchait, son déplacement était très lent. Heureusement, le livre contenait des descriptions d'autres sortes de robots qui nous ont inspirés pour aboutir à celui qui nous concerne ici.
Pour construire le robot nous avons utilisé les pièces suivantes:
Fig 1: Circuit imprimé |
Fig 2: pince à becs fins |
Vous devriez trouver la plupart des composants dans des magasins de
modélisme ou l'on se procure habituellement des pièces pour des petits
avions, des voitures radio-commandées etc... Si vous n'en trouvez pas
dans votre ville, recherchez l'école d'architecture la plus proche.
Comme les étudiants doivent généralement construire des maquettes de maisons
et autres bâtiments, vous trouverez sûrement un commerce où il est possible
d'acheter des choses comme le tube de laiton très fin.
Lors de l'achat des pinces à becs fins, assurez vous qu'elles ont une face
plate, sinon vous n'arriverez pas à plier le fil de nitinol.
Traduction des termes du dessin: Holes = Trous Music Wire = Corde à Piano (Steel Wire) = (Fil d'acier) |
|
Fig 3: Les principaux composants du robot. |
Pour le corps vous avez d'abord besoin de trois morceaux de circuit
imprimé, un de 6x6 trous et deux de 6x7 trous ainsi que de 4 cm de tube de
laiton de 2 mm de diamètre et 3,7 cm de corde à piano.
Fig 4: Colonne vertébrale et arbre de transmission (Ndt:Solder=Soudure)
Coupez le tube de laiton en morceaux de 8, 17,5 et 8mm comme montré sur le dessin.
Cela peut être fait en le roulant d'avant en arrière sous un couteau de cuisine bien
aiguisé puis en le tordant. Le tube se cassera à l'endroit du rétrécissement fait
par le couteau. Il est important que le tube central soit légèrement plus long que
le circuit imprimé de 6x6 trous. Coupez environ 3,7 cm de corde à piano afin qu'elle
soit plus longue d'environ 3 mm que l'ensemble des 3 tubes. Passer la corde à
piano dans les trois tubes.
Le tube central doit pouvoir tourner alors que les deux autres sont soudés
sur la corde à piano.
Traduction des termes du dessin: Middle part moves = La partie centrale est mobile Holes = Trous Solder = Soudure |
|
Fig 5: Souder les plaques à l'axe principal |
Ebarbez le tube de laiton de 1 mm et coupez plusieurs morceaux de
4 mm de long. Roulez le tube sur le couteau de cuisine puis courbez-le.
Vous avez besoin de 16 de ces cavaliers mais préparez-en quelques uns
de rechange.
Comme de nombreux sertissages sont nécessaires, faites des essais avec
un peu de nitinol avant de commencer: placer le bout du fil de nitinol
dans le tube de laiton très fin (1 mm de diamètre externe) puis écrasez-le
avec la pince à becs fins. Cette opération s'appelle un sertissage. Vous
aurez besoin d'une pince de bonne qualité car le sertissage des tubes de
laiton nécessite une force importante. Vous pouvez aussi décaper les bouts
du fil de nitinol avec du papier de verre grain 600 pour garantir de bonnes
connexions électriques.
Passons maintenant au fil de nitinol qui servira à monter et descendre les
pattes.
Traduction des termes du dessin: Crimp = Sertissage Press with Finger = Appuyer avec le doigt -> Moves 2 mm = -> Bouge de 2 mm |
|
Fig 7: "Le pont" |
Fig 8: Pliez le fil
Coupez trois morceaux de corde à piano de 10 cm de long pour les pattes.
Pliez 1,5 cm de chaque coté puis soudez-les aux trois corps du robot afin
qu'elles soient parallèles entre elles.
TOP VIEW = VUE DE DESSUS | |
BOTTOM VIEW = VUE DE DESSOUS SOLDER = SOUDURE |
STEEL WIRE = CORDE A PIANO 1 HOLE = 1 TROU |
Quand le robot est prêt, vous pouvez souder des morceaux de 0,5 m (ou plus si vous voulez) de fil de cuivre vernis fin de 0.1 mm aux sertisseurs sur la carte, puis souder les sertisseurs du corps au circuit imprimé. Il faudra 9 fils, 6 pour les pattes, 2 pour le mouvement haut/bas et un pour le bus de puissance. Vous pouvez souder l'autre extrémité des fils à un petit connecteur que vous pourrez ensuite raccorder dans une prise correspondante sur le circuit pilote.
Notre insecte est conçu pour marcher à une allure de tripode. Cela signifie
que trois pattes sont sur le sol (2 d'un coté, une de l'autre) pendant que
les trois autres sont en l'air. Quand le robot marche, les trois pattes
sur le sol se déplacent dans une direction pendant que celles en l'air vont
dans l'autre sens.
Fig 13: L'allure
Ce circuit imprimé vous permet d'utiliser votre PC pour contrôler
les moteurs du robot et se branche sur le port parallèle.
Quand nous avons essayé notre programme, nous l'avons d'abord fait avec
des diodes électro-luminescentes (LED), et nous avons seulement
connecté le robot quand tout marchait correctement, c'est à dire que les
LED montraient une allure de marche correcte. Vous devriez faire de même
lors de vos essais avec le programme.
Le robot est plutôt gourmand et vous aurez besoin d'un courant de 200 à 250 mA
à travers le nitinol pour le contracter. Les fils de nitinol de 3 cm font
à peu près 7 Ohms. Démarrez toujours le logiciel d'abord car celui-ci met
toutes les sorties à zéro dès le début pour éviter d'abîmer le fil de nitinol.
Le bios affecte l'état des sorties du port parallèle aléatoirement. De ce fait,
certaines sorties pourraient être à l'état actif et le nitinol pourrait être
endommagé si le courant y circule plus longtemps qu'une seconde. Le temps
nécessaire au nitinol pour se refroidir doit être 1,5 fois le temps de
chauffage.
Le schéma:
Traduction des termes du schéma: Power Supply = Alimentation 7805 Voltage Regulator = Régulateur 7805 The driver circuit for One leg.= L'interface pour 1 patte You need this 8 times: = A faire en 8 exemplaires Nitinol Wire = Fil de Nitinol Data in = entrée To computer = Coté ordinateur |
|
Fig 14: Schéma de principe |
Le port parallèle à été conçu pour servir de port de sortie sur
un ordinateur personnel auquel on connecte une imprimante. Certains
ports parallèles permettent à la fois des entrées et des sorties. Ici nous
n'utilisons le port que pour les sorties. Dans un futur article, nous
brancherons des capteurs sur le robot et nous utiliserons alors les
capacités d'entrées du port parallèle. Bien qu'il y ait 25 broches sur ce port,
nous n'en utilisons que 9. Huit sont utilisées comme sorties de données
et une autre sert de masse.
Le brochage du port parallèle est le suivant:
SUB-D 25 broches FEMELLE sur le PC. Broche Nom 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 GroundLe circuit se connecte à la broche 18 (Masse) et aux broches de données, broches (2-9).
==== pprobi.c ===== /* vim: set sw=8 ts=8 si : */ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License. * See http://www.gnu.org/copyleft/ for details. * * Written by 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 -- control software for a walking robot\n\ USAGE: pprobi [-h] [parport-device]\n\ \n\ OPTIONS:\n\ -h this help\n\ -r reset the parallel port data pins (all zero) and exit\n\ \n\ The default device is /dev/parport0 \n\ "); #ifdef VERINFO puts(VERINFO); #endif exit(0); } /* Signal handler: all off then exit */ 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; /* The following things are used for 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 break, help does not return */ case 'r': opt_r=1; break; case '?': fprintf(stderr, "serialtemp ERROR: No such option. -h for help.\n"); exit(1); /*no default action for case */ } } if (argc-optind < 1){ /* less than one argument */ dev="/dev/parport0"; }else{ /* the user has provided one argument */ dev=argv[optind]; } fd=robi_claim(dev); /* robi_claim has its own error checking */ /* catch signals INT and TERM and switch off all data lines before * terminating */ signal(SIGINT, offandexit); signal(SIGTERM, offandexit); /* initialize parpprt data lines to zero: */ robi_setdata(fd,0); set_terminal(1); /* set_terminal has its own error handling */ 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'){ /*right */ printf("walking right\n"); walkright(fd); } if (state=='h'){ /*left */ printf("walking left\n"); walkleft(fd); } if (state=='j'){ printf("walking back\n"); walkback(fd); } if (state=='k'){ if (alternate){ printf("walking straight on a\n"); walkstraight_a(fd); }else{ printf("walking straight on b\n"); walkstraight_b(fd); } alternate=(alternate +1) %2; } } /* we get here if q was typed */ set_terminal(0); return (0); } ==== robi.c ===== /* vim: set sw=8 ts=8 si : */ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License. * See http://www.gnu.org/copyleft/ for details. * * Written by 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" /* like printf but exit the program */ static int die(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vprintf(fmt, ap); va_end(ap); exit(1); } /* get one character from stdin * Returns non zero if char was read otherwise zero * The arrow keys are mapped as follows: * <- = 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){ /* arrow keys are pressed */ switch (s[2]){ case 0x41: /*up arrow*/ c='k'; break; case 0x42: /*down arrow*/ c='j'; break; case 0x44: /*l arrow*/ c='h'; break; case 0x43: /*r arrow*/ 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); } /* Set the Terminal to Non Canonical mode with echo off * or reset the terminal. * USAGE: set_terminal(1) for canonical */ int set_terminal(int canonical) { static struct termios originalsettings; struct termios newsettings; static int origok=0; /* set if originalsettings valid */ if (canonical){ /* save original settings and set canonical mode*/ 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: could not set terminal attributes on stdin\n"); } origok=1; }else{ if (origok){ /* restore settings */ tcsetattr(fileno(stdin),TCSANOW,&originalsettings); } } return(0); } /* open /dev/parportX device and claim it. * USAGE: fd=robi_claim("/dev/parport0"); * The return value is a file descriptor used by other * functions such as robi_setdata */ int robi_claim(char *dev) { int fd,i; fd = open(dev, O_RDWR ); if (fd < 0) { die("ERROR: cannot open device %s\n",dev); } i=0; /* we need exclusive rights as we do not set the control lines*/ /*ioctl(fd, PPEXCL, &i)&& die("ERROR: request for exclusive rights failed\n");*/ ioctl(fd, PPCLAIM, &i)&&die("ERROR: could not claim parport\n"); return(fd); } /* Walk left */ int walkleft(int fd) { /* first B legs to ground */ robi_setdata(fd,LEGBD); usleep(400 *1000); /* all A legs 1 step */ robi_setdata(fd, LEGB1 | LEGB3 ); usleep(1100 *1000); /* first A legs to ground, cool B*/ robi_setdata(fd,LEGAD); usleep(400 *1000); robi_setdata(fd,0); usleep(1000 *1000); return(0); } /* Walk right */ int walkright(int fd) { /* first A legs to ground */ 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); /* first B legs to ground, cool A*/ robi_setdata(fd,LEGBD); usleep(400 *1000); robi_setdata(fd,0); usleep(1000 *1000); return(0); } /* Walk with all 3 legs 1 step forward */ int walkstraight_a(int fd) { /* first A legs to ground */ robi_setdata(fd,LEGAD); usleep(800 *1000); /* all A legs 1 step */ robi_setdata(fd, LEGA1 | LEGA2 | LEGA3 ); usleep(1000 *1000); /* first B legs to ground, cool A*/ robi_setdata(fd,LEGBD); usleep(500 *1000); robi_setdata(fd,0); usleep(1200 *1000); return(0); } /* Walk with all 3 legs 1 step forward */ int walkstraight_b(int fd) { /* first B legs to ground */ robi_setdata(fd,LEGBD); usleep(400 *1000); /* all B legs 1 step */ 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); } /* Walk with all 6 legs 1 step back */ int walkback(int fd) { /* first A legs to ground */ robi_setdata(fd,LEGAD); usleep(800 *1000); /* all B legs 1 step in the air*/ robi_setdata(fd, LEGB1 | LEGB2 | LEGB3 ); usleep(500 *1000); /* first B legs to ground, cool A*/ robi_setdata(fd,LEGBD); usleep(500 *1000); /* all A legs 1 step in the air*/ 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); } /*---------*/ /* Write a bit pattern to the data lines * USAGE: rc=robi_setdata(fd,bitpat); * The return value is 0 on success. */ 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" /* the first thing you need to do: */ extern int robi_claim(char *dev); /* write a bit pattern to the data lines of the parallel port: */ extern int robi_setdata(int fd,unsigned char bitpat); /* input and terminal functions */ 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); /* data pins to legs: * A1------=------B1 * = * = * B2------=------A2 * = * = * A3------=------B3 * * * Pin to set A-legs to ground= AD * Pin to set B-legs to ground= BD * * parallel port leg name * ------------------------- * 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
Le logiciel utilise la bibliothèque ppdev issue du noyau 2.4.x (Vous devez avoir un noyau 2.3.x ou 2.4.x. Cela ne marchera pas avec une version plus ancienne). C'est une bibliothèque pour écrire des pilotes utilisateurs pour le port parallèle. Dans les noyaux plus anciens, nous aurions dû écrire un module pour le noyau ou utiliser une méthode moins élégante qui aurait seulement permis au super utilisateur d'exécuter le programme. L'API ppdev utilise le fichier /dev/parport0. En changeant les permissions de ce fichier, vous pouvez contrôler qui est autorisé à utiliser le port parallèle.
Pour compiler ppdev comme un module du noyau, vous devez compiler le module PARPORT en même temps que PPDEV. Voici ce que cela donne dans le fichier .config:
# # Parallel port support # CONFIG_PARPORT=m CONFIG_PARPORT_PC=m CONFIG_PARPORT_PC_FIFO=y # CONFIG_PARPORT_PC_SUPERIO is not set # CONFIG_PARPORT_AMIGA is not set # CONFIG_PARPORT_MFC3 is not set # CONFIG_PARPORT_ATARI is not set # CONFIG_PARPORT_SUNBPP is not set CONFIG_PARPORT_OTHER=y CONFIG_PARPORT_1284=y # # Character devices # CONFIG_PPDEV=m #
Le programme initialise d'abord le port parallèle avec la commande
ioctl PPCLAIM. Puis il passe le terminal en mode non canonique. Cela permet
de récupérer directement les entrées du clavier sans que l'utilisateur ait à
taper la touche retour après chaque entrée. Ensuite, il entre dans une boucle
où il regarde d'abord s'il y a eu des commandes utilisateur, puis fait
marcher le robot en accord avec la commande. Sans action de votre part,
le programme fera marcher le robot selon le dernier ordre reçu (par exemple
continuer à marcher en avant).
La commande ioctl(fd, PPWDATA, &bitpat); est utilisée pour
changer l'état des lignes de données.
Les broches de votre robot doivent être connectées aux sorties du circuit d'interface de la manière suivante:
Pattes: A1------=------B1 = = B2------=------A2 = = A3------=------B3 Broches des pattes A à la masse=AD Broches des pattes B à la masse=BD Lignes de sorties correspondantes du circuit: data 0 A1 data 1 A2 data 2 A3 data 3 AD data 4 B1 data 5 B2 data 6 B3 data 7 BDLa ligne Data 0 est la sortie du circuit qui se raccorde à la broche 2 du port parallèle (D0).
Nous espérons que vous vous êtes bien amusés en construisant ce robot. Tenez-nous au courant de la construction de votre robot, surtout s'il est construit différemment!
|
Site Web maintenu par l´équipe d´édition LinuxFocus
© Katja et Guido Socher, FDL LinuxFocus.org Cliquez ici pour signaler une erreur ou envoyer un commentaire à Linuxfocus |
Translation information:
|
2002-04-23, generated by lfparser version 2.27