[LinuxFocus-icon]
Home  |  Map  |  Index  |  Zoek

Nieuws | Archieven | Links | Over LF
Dit artikel is beschikbaar in: English  Castellano  Deutsch  Francais  Nederlands  Portugues  Russian  Turkce  Arabic  

convert to palmConvert to GutenPalm
or to PalmDoc

[Photo of the Authors]
door Katja en Guido Socher
<katja(at)linuxfocus.org, guido.socher(at)linuxfocus.org>

Over de auteur:

Katja is de Duitse editor van LinuxFocus. Ze houdt van Tux, film & fotografie en de zee. Haar homepage kan hier worden gevonden.

Guido is al heel lang een Linux fan en hij houdt van Linux omdat het is ontworpen door open en eerlijke mensen. Dit is een van de redenen dat het Open Source wordt genoemd. Zijn homepage is te vinden op linuxfocus.org/~guido.



Vertaald naar het Nederlands door:
Hendrik-Jan Heins <hjh(at)passys.nl>

Inhoud:

 

Het bouwen van een onder Linux aangestuurde, lopende robot

[Illustration]

Kort:

In dit artikel gaan we een zes-benige, lopende robot bouwen die we vervolgens gaan besturen met een Linux PC via de parallele poort interface.
Andere apparaten kunnen op een soortgelijke manier worden bestuurd via de parallele poort.

 

Inleiding

Robots hebben ons altijd gefacineerd en dus waren we beiden zeer blij toen we enige tijd geleden een boek over robots vonden met een robot kit om zelf een kleine, insectachtige, robot te bouwen die de Stiquito heet. Stiquito is een speciale robot, aangezien hij geen motor heeft, maar loopt met behulp van nitinol en daardoor is hij heel stil, net als een echt insect. Helaas viel ons na het bouwen op dat het lopen zeer langzaam ging doordat de wrijving met het oppervlak niet groot genoeg was. Gelukkig bevat het boek ook de beschrijving voor enkele andere robot ontwerpen, een ervan vormde uiteindelijk de inspiratie om de robot te bouwen die hieronder beschreven is.

 

Nitinol

Onze robot heeft geen motor en kan alleen lopen doordat de poten zijn aangesloten en aangedreven worden door nitinol. Nitinol is een geheugen-metalen actuator draad die gemaakt is van nikkel en titanium en die net als een spier samentrekt als hij onder stroom komt te staan. Als er een electrische stroom doorloopt, wordt de draad verhit en wordt hij korter (hierna keert hij terug naar de "niet-samengetrokken" staat). Een tegenwicht (in ons geval een snaar (van een muziekinstrument)) is nodig om de nitinol terug te brengen in z'n originele staat. Als je de draad slechts 3 tot 5 procent uittrekt, dan is hij zeer betrouwbaar en kan hij deze beweging milioenen keren, betrouwbaar, maken.


 

Het bouwen van de robot

Om de robot te bouwen, hebben we de volgende onderdelen gebruikt:



[pliers]
Fig 2: tang met een smalle bek
Je kunt de meeste onderdelen waarschijnlijk bij een goede hobbywinkel waar ze ook onderdelen voor modelbouw vliegtuigen, auto's en dergelijken verkopen, vinden. Als je ze niet in je eigen stad kunt vinden, kijk dan eens rond waar de dichtsbijzijnde universiteit met een architectuur opleiding zit. Dit aangezien de studenten meestal modellen moeten bouwen en je daar dus een winkel kunt vinden waar je dingen zoals zeer dunne koperen pijpen kunt vinden.
Als je de smalle bek tang gaat kopen, zorg er dan voor dat de tang een plat oppervlak heeft, anders kan de de nitinol draad niet plooien.


[parts]
Fig 3: De belangrijkste onderdelen voor de robot.

Het bouwen van het lichaam

Voor het lichaam heb je eerst drie delen circuit bord nodig, die met 6x6 gaten en de twee met 6x7 gaten en 4cm 2 mm diameter koperen pijp en 3.7 cm snaar.

[hinge]
Fig 4: de ruggegraat en de powerbus

Knip de koperen pijp in stukken van 8, 17.5 en 8mm zoals te zien is op de afbeelding. Je kan dit doen door hem te rollen over het scherpe keukenmes en hem daarna te buigen. De pijp zal breken op de inkeping die gemaakt is met het mes. Het is van belang dat de pijp in het midden iets langer is dan het ciruit bord met de 6x6 gaten. Knip ongeveer 3.7cm snaar af. De uiteindelijke lengte moet ongeveer 3 mm langer zijn dan de 3 pijpen tezamen. Leg de snaar door de drie pijpen.
De pijp in het midden moet kunnen draaien terwijl de andere twee worden vastgesoldeerd aan de snaar.

[solder the 3 body parts]
Fig 5: soldeer de borden aan de ruggegraat

De pijp in het midden is nu vastgesoldeerd aan het ciruit bord met de 6x6 gaten. Let er goed op dat hij kan draaien. De andere twee pijpen worden aan de andere twee circuit borden gesoldeerd.
Pak nu de twee kleine ciruit borden met de 2x7 gaten. Ze moeten rechtop staan op een kant ten opzichte van de middelste koperen pijp. Het circuit bord moet inkepingen hebben, die kan je maken met een kleine vijl of met een mes of zaag. Soldeer ze aan de middelste koperen pijp en het middelste circuit bord zoals op de afbeelding te zien is:
[the flag]
Fig 6: toevoegen van het kleine circuit bord

Schuur de 1mm koperen pijp en knip meerdere 4mm lange stukken van de pijp. Rol de pijp over het keukenmes en buig hem dan. Je hebt 16 van deze plooien nodig, maar het is slim om er een paar extra te maken.

Aangezien je een boel moet plooien, is het slim om het nu een beetje te testen met een klein beetje nitinol, voordat je begint: Plaats het einde van de nitinol draad in de zeer dunne koperen pijpjes (1mm buiten diameter) en knijp dan in de koperen pijp met de platte bek tang. Dit heet "crimping" (plooien). Zorg er voor dat je een goede platte bek tang koopt, aangezien de kracht die er op komt te staan zeer groot is. Je kunt ook de uiteinden van de nitinol een klein beetje schuren om een betere electrische geleiding te krijgen.

Nu gaan we de nitinol draad die wordt gebruikt om de poten naar boven en beneden te bewegen aanleggen.

[the bridge]
Fig 7: "de brug"

Je spant de nitinol draad alsof je een brug wilt bouwen. Je start aan een kant. Daar trek je de nitinol draad door het laatst mogelijke gat aan de linker en rechte zijde. Je legt een knoop in de nitinol draad (om een betere verbinding te verkrijgen) en plaatst er een plooi (een van ongeveer 4 mm koperen pijp) over en trekt deze strak zodat hij vast zit en de nitinol draad door het tweede gat van boven aan de linkerkant gehaald kan worden en daarna door het laatst mogelijke gat aan de linker rechte zijde. Aan de onderkant moet opnieuw een knoop worden gelegd in de nitinol draad en er moet weer een plooi over die vastgezet wordt (zie figuur 7). De nitinol draad moet strak, maar niet te strak worden gespannen. Als je het wegduwt met je vingertop moet hij ongeveer 2-4 mm speling hebben. Als hij te strak zit of niet strak genoeg, dan zal de robot straks niet goed bewegen. Soldeer de plooien vast aan het bord.
Do hetzelfde aan de andere kant.
Probeer, voor je verder gaat, uit of het werkt. Gebruik een 1.5V AA batterij en verbindt deze met een van de nitinol draden. Als de draad samentrekt moet het middelste lichaamsdeel 10-20 graden draaien. Let er wel op dat je de batterij niet langer dan 1 seconde verbindt. Je kan de draad beschadigen als hij oververhit raakt.

De poten


[music wire for legs]
Fig 8: buig de draad

Voor de poten knip je drie 10 cm lange stukken af van de snaar. Ieder wordt 1.5cm omgebogen aan beide kanten. Daarna worden ze vastgesoldeerd aan de drie lichaamsdelen van de robot. Ze moeten parallel ten opzichte van elkaar liggen.

[legs top view]

[legs bottom viewl]
Fig 9, 10: poten aan de robot

Nu moet je de nitinol draden koppelen aan de 6 poten.

[leg and nitinol]
Fig 11: voeg de actuators toe

Plaats de nitinol draad van boven door een plooi en door een gat in het circuit bord. De afstand tot de snaar is 3 gaten. Plooi hem vast (zie bovenstaande afbeeldingen).
Trek daarna een plooi over de snaar totdat de knie gebogen staat. PLaats de nitinol draad er doorheen en plooi hem vast. Nu komt het moeilijkste deel. Houdt de robot vast en buig de poten een beetje bij met tape of een extra koperen draad. De snaar dient als tegenwicht voor de nitinol draad. Om te zorgen dat dit werkt, moet de nitinol draad absoluut niet los zitten. De snaar moet door 1 gat in het circuit bord richting de nitinol gelegd worden en daarna moet de plooi vastgesoldeerd worden aan de poot.
[nitinol must not be loose]
Fig 12: nitinol en de snaar op hetzelfde niveau


Zorg ervoor dat de snaar en de nitinol op hetzelfde niveau vast zitten. De poten moeten niet naar boven of naar beneden bewegen als de nitinol verkort. De poot moet naar achteren bewegen.

Doe hetzelfde met de andere vijf poten.
De poten en de snaar met de koperen pijp in het midden van de robot dienen als een "power bus" en er moet daarom een electrische verbinding tussen alle delen mogelijk zijn. Maar doordat het middelste deel van het lichaam meer bewegingsvrijheid heeft en kan draaien, maakt het geen goede verbinding. We hebben dat verbeterd door 3cm van de 0.1 mm koperen draad te nemen en die om de koperen pijp te wikkelen om een kleine spoel te maken. Haal de koperen pijp eruit en soldeer de spoel aan de middelste poten en aan de buitenste poten. De speol-vorm van de draad zorgt voor maximale flexibiliteit.

Als de robot klaar is, kan je 0.5m lange stukken (of langere stukken als je dat wilt) van 0.1 mm verniste koperen draad vastsolderen aan de plooien op het bord en de plooien zelf kan je aan het circuit bord vastsolderen. We hebben 9 draden nodig, 6 voor de poten, 2 voor op en neer en een voor de "powerbus". Je kan de andere uiteinden vastsolderen aan een kleine connector die je in kan pluggen in een corresponderende socket op het driver circuit.

 

De gang

Ons insect is ontworpen om te lopen met een tripod gang. Een tripoid gang betekent dat er altijd 3 poten op de grond staan (twee aan een kant en een aan de andere kant) en de andere 3 zijn opgetild. Als de robot loopt bewegen de drie poten op de grond in dezelfde richting, terwijl de poten in de lucht in de omgekeerde richting bewegen.
[The gait]
Fig 13: De gang



 

De robot besturen met je Linux computer

 

Het driver circuit

Dit circuit bord maat het mogelijk om de PC te gebruiken om de actuators op de robot te besturen via de paralelle poort.
Toen we ons computer programma ontwikkelden hebben we het eerst getest met de LEDs en we hebben pas de controle draden op het bord geplugd toen we met de LEDs gecontroleerd hadden dat de gang correct werkte. Het is slim om hetzelfde te doen las je experimenteert met het programma.
De robot is nogal hongerig. Je moet tussen de 200 en 250 mA stroom zetten door de nitinol om het te laten samentrekken. De 3cm lange nitinol draden op de poten hebben een weerstand van ongeveer 7 Ohm.Start de software altijd voordat je de spanning op het driver circuit zet omdat alle data pins eerst zijn ingesteld op "off" door de software om schade aan de nitinol te voorkomen. Aangezien de BIOS van de computer de paralelle poort data pins random waardes toewijst, kunnen enkelen daarvan aan staan en de nitinol kan beschadigen als je er langer dan 1 seconde stroom op zet. De tijd die nitinol nodig heeft om af te koelen is ongeveer 1.5 maal zolang als de tijd dat het verhit is.

Het circuit diagram:
[circuit]
Fig 14: circuit diagram

Zoals je kan zien in het bovenstaande diagram, gebruiken we een electronisch gestabiliseerde voeding. Dit is om er zeker van te zijn dat er geen vreemde fluctuaties zitten in de aangevoerde spanning en om de paralelle poort te beschermen. Als externe stroomvoorziening kan je iedere DC voeding aansluiten die een waarde heeft van tussen de 6 en 24 V. De 7805 is een standaard spannings regulatir. Het enige waar je hier op moet letten is het feit dat de twee condensatoren (470uF en 0.1uF) zeer dicht bij de 7805 spanningsregulator zitten aangezien het anders kan gebeuren dat de 7805 chip begint te oscilleren waardoor de 7805 kapot kan gaan.

De eigenlijke driver moet 8 maal gebouwd worden. een voor iedere poot en 2 om de robot te laten draaien (de poten op en neer te laten bewegen). We maken gebruik van een kleine NPN Darlington transistor aangezien onze robot veel stroom nodig heeft. De BC875 of BC618 kan ongeveer 500mA schakelen. De 47K op de input zorgt ervoor dat een open circuit (dus de computer is niet aangesloten) altijd gelijk is aan "off". Het spanningsniveau op de parallele poort is meer dan 4V voor "on" en minder dan 1V voor de staat "off". De transistor werkt alleen als een schakelaar. De 15 Ohm weerstand beperkt de stroom en beschermt zowel de poten van de robot als de transistor. De LEDs tonen de staat ("on" of "off").

Hieronder zie je de afbeeldingen van het circuit. De rode LEDs (degenen die parralel staan aan de actuatoren van de robot) zijn moeilijk te zien doordat we transparante rode LEDs hebben gebruikt. We hebben de 15 Ohm weerstanden gemaakt van constantaan draad spoelen, maar dat hebben we alleen maar gedaan omdat we heel veel van die draad hadden. Het is goedkoper om twee standaard 2W weerstanden te kopen.


[the final drivercircuit1] [the final drivercircuit2]
Fig 15: het circuit



 

De parallele poort

De parallele poort is ontworpen om te dienen als output poort van de personal computer en om er een printer aan te hangen. Sommige parallele poorten staan zowel in- als output toe. Hier gaan we de poort alleen gebruiken voor output. In een volgend artikel zullen we sensors gaan verbinden met de robot en dan zullen we ook de input gaan gebruiken. Hoewel de paralelle poort 25 pins heeft, gana we er maar 9 gebruiken. Acht lijnen worden gebruikt als data output lijnen en een lijn is aarde.
De pinout voor de parallele poort is als volgt:

25 PIN D-SUB FEMALE aan de PC.

 Pin  Name   Dir   Omschrijving
 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 Ground
Je verbindt het driver circuit met pin 18 (GND) en aan de data pins (2-9).

De parallele poort schrijft normaal gesproken een byte naar de data lijnen waarna de computer de strobe lijn op 1 zet om aan te geven aan de printer dat de data lijnen nu geldig zijn. Wij gebruiken de data lijnen direct omdat we geen extra logica voor de strobe lijn nodig hebben.

 

De software

Je kan de software hier downloaden .
Pak het uit met het commando tar zxvf pprobi*.tar.gz. Installatie instructies worden meegeleverd.

Her programma is geschreven in C. Met de pijltjes toetsen en de spatiebalk kan je de robot controleren, hem laten lopen; zowel rechtuit als naar links, rechts en achteruit. Gebruik de spatiebalk om de robot te stoppen en q (of x) om het programma te beeindigen. In plaats van de pijltjes toetsen kan je ook de h, j, k, l toetsen (met vi key mapping) gebruiken als je wilt. De waardes die we gebruiken voor de beweging van de poten zijn geoptimaliseerd voor onze robot. Iedere robot is een beetje anders, vooral doordat het lastig is om dezelfde spanning op ieder van de nitinol draden te zetten. Je robot zal direct werken met de software, maar waarschijnlijk zullen niet alle poten met dezelfde stapgrootte bewegen, je zult een beetje moeten experimenteren tot je de waardes vindt die het beste werken met jouw robot. Zorg er wel voor dat de poten niet oververhit raken en genoeg tijd hebben om af te koelen.

==== 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


De software maakt gebruik van de ppdev programmeer interface uit de 2.4.x Kernel (Je hebt een 2.3.x of 2.4.x Kernel nodig. Het werkt niet met oudere kernels). Dit is een schone en handige interface om gebruikers gestuurde commando's aan apparaten te sturen over de paralelle poort. In de oudere kernels hadden we een kernel module moeten schrijven of gebruik moeten maken van een vrij lelijke methode waarbij alleen de root het programma kan draaien. De ppdev interface maakt gebruik van het apparaat betsand /dev/parport0 en door het bijstellen van de eigenaar en de rechten van dat bestand kan je controleren wie deze paralelle poort interface mag gebruiken.

Om ppdev als een module in de kernel te compileren, moet je de PARPORT module gezamelijk mer het PPDEV apparaat compileren. Dit zou er in het .config bestand als volgt uit moeten zien:

#
# 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
#


Het programma claimt (initialiseert) de parallele poort met het ioctl commando PPCLAIM. Daarna stelt het de terminal in in niet-canonnieke modus. Dit is om direct input te kunnen geven via het toetsenbord zonder dat de gebruiker steeds op return moet drukken na het ingeven van een commando. Hierna start het een loop waarin eerst wordt gecontroleerd of er input van de gebruiker is en laat daarna de robot lopen volgens het gegeven commando. Als je niets doet, zal het programma het laatst gegeven commando continu uitvoeren (dus rechtuit blijven lopen).
Het commando ioctl(fd, PPWDATA, &bitpat); wordt gebruikt om de data lijnen van een gegeven bit patroon in te stellen.

De pins van je robot moeten als volgt worden verbonden met de output lijnen van het driver circuit:

Poten:
  A1------=------B1
          =
          =
  B2------=------A2
          =
          =
  A3------=------B3


  Pin naar set A-poten naar ground= AD
  Pin naar set B-poten naar ground= BD

Corresponderende output lijnen van het driver circuit:
  data 0           A1
  data 1           A2
  data 2           A3
  data 3           AD
  data 4           B1
  data 5           B2
  data 6           B3
  data 7           BD

Data 0 is de output van het driver circuit dat verbonden moet worden met de parallele poort op pin 2 (D0).

Hier is hij, de lopende robot:
[yes, it walks]
Hij beweegt een beetje te snel in deze geanimeerde gif. In werkelijkheid is hij een beetje trager door de afkoeltijd die nodig is voor de nitinol die terug moet veren naar de originele lengte.


We hopen dat je het leuk vond om de robot te bouwen. Laat het ons weten als je er een gemaakt hebt, vooral als die van jou is gebouwd volgens een ander ontwerp!

 

Bronnen

 

Talkback voor dit artikel

Elk artikel heeft zijn eigen talkback pagina. Daar kan je commentaar geven of commentaar van anderen lezen:
 talkback pagina 

Site onderhouden door het LinuxFocus editors team
© Katja en Guido Socher, FDL
LinuxFocus.org

Klik hier om een fout te melden of commentaar te geven
Vertaling info:
en --> -- : Katja en Guido Socher <katja(at)linuxfocus.org, guido.socher(at)linuxfocus.org>
en --> nl: Hendrik-Jan Heins <hjh(at)passys.nl>

2002-06-08, generated by lfparser version 2.28