Home Map Index Search News Archives Links About LF
[Top bar]
[Bottom bar]
эта страница доступна на следующих языках: English  Castellano  Deutsch  Francais  Nederlands  Portugues  Russian  Turkce  Arabic  

[Photo of the Authors]
автор Katja and Guido Socher

Об авторе:

Катя является немецким редактором LinuxFocus. Она любит Тукса, фильмы и фотографию, а также море. Ее домашнюю страницу можно найти здесь.

Гвидо уже долгое время поклонник Linux, который нравится ему за то, что создан честными и открытыми людьми. Это одна из причин, по которой мы называем эту систему открытой. Вот страница Гвидо: linuxfocus.org/~guido.


Содержание:

 

Строим Linux-робота

[Illustration]

Резюме:

В этой статье мы строим маленького шестиногого ходячего робота, которым будем управлять через параллельный порт с Linux PC.
Кстати, подобным образом (через параллельный порт) можно управлять и другими устройствами.



 

Введение

Роботы всегда очаровывали нас, так что мы обрадовались, когда нашли книгу c инструментарием для сборки маленького насекомоподобного робота по имени Стикито. Стикито в какой-то степени особенный робот, так как он не имеет мотора, но ходит, потому что к его ногам прикреплен нитинол, так что робот передвигается совершенно бесшумно, как настоящее насекомое. Но когда мы построили Стикито, то заметили, что из-за недостаточно хорошего сцепления с поверхностью двигался он очень-очень медленно. К счастью, книга также включала описания конструкций других киберов, что окончательно вдохновило нас на создание робота, о котором вы можете здесь прочитать.

 

Нитинол

Наш робот не имеет мотора и ходит благодаря тому, что к его ногам прикреплена нитиноловая проволока, которая и приводит их в движение. Нитинол является сплавом, обладающим "эффектом памяти" и состоящим из никеля и титана, он способен сокращаться подобно мышцам, нагреваясь электрическим током. Во время прохождения электрического тока проволока из нитинола нагревается и укорачивается, возвращая материалу его "нерастянутое" состояние. Затем требуется противодействие (в нашем случае это музыкальная струна), чтобы вернуть нитинолу его первоначальную форму. При растяжении проволоки на 3-5% нитиноловая мышца будет очень надежной и отработает миллионы циклов.


 

СБОРКА РОБОТА

Для сборки робота мы использовали следующие материалы:



[pliers]
Рис.2: Пассатижи
Большинство деталей и материалов вы можете купить в магазине типа "Моделист-конструктор", где продаются запчасти для маленьких самолетов, радиоуправляемых автомобилей и т.д. Если вам не удастся добыть их в своем городе, посмотрите рядом с ближайшим институтом, в котором есть факультет архитектуры. Поскольку студенты обычно должны строить модели домов и других зданий, вполне возможно, что вы найдете неподалеку магазин, где продаются такие вещи, как очень тонкие латунные трубки.
Покупая пассатижи, убедитесь, что их рабочая поверхность плоская, иначе вы не сможете хорошо обжать нитиноловую проволоку.


[parts]
Рис.3: Основные части робота.

Сборка туловища

Для туловища вам вначале понадобятся три монтажных платы, одна с отверстиями 6х6 и две с отверсиями 6х7, а также 4см 2мм-ой латунной трубки c 3.7мм струны.

[hinge]
Рис.4: "Хребет" и шина подвода питания

Разрежьте латунную трубку на 8мм, 17.5мм, и 8мм части как показано на рис.4. Вы можете сделать это, покатав трубку взад и вперед острым кухонным ножом и затем согнув ее. Трубка сломается в тех местах, где вы сделали бороздки ножом. Важно, чтобы трубка была немного длиннее, чем плата с 6х6 отверстиями. Отрежьте около 3.7см струны. Длина в результате должна быть примерно на 3мм больше, чем три части трубки, сложенные вместе. Пропустите струну сквозь все три трубки.
Средняя трубка должна свободно вращаться, в то время как крайниe нужно припаять к струне.

[solder the 3 body parts]
Рис.5: Припаяйте платы к "хребту"

Итак, средняя трубка припаяна к плате с 6х6 отверстиями. Убедитесь, что она может вращаться. Две другие трубки припаяны к остальным двум платам.
Теперь возьмите маленькую монтажную плату с 2х7 отверстиями. Ее следует поставить краем на середину латунной трубки. Проделайте бороздку на монтажной плате с помощью резака или напильника. Припаяйте маленькую монтажную плату к середине латунной трубки, как показано на рисунке:
[the flag]
Рис.6: Установка платы 2х7.

Обработайте наждачной бумагой 1мм-ю латунную трубку и отрежьте от нее несколько кусочков длиной 4мм. Катайте трубку лезвием кухонного ножа и затем ломайте ее. Вам понадобится 16 зажимов, однако сделайте несколько запасных.
Поскольку мы будем много обжимать, сейчас вам лучше поэкспериментировать с небольшим кусочком нитинола: вложите конец нитиноловой проволоки в зажим и сожмите его пассатижами. Эта процедура называется обжим. Позаботьтесь о том, чтобы купить хорошие пассатижи, так как необходимо очень большое усилие для сжатия трубки. Вы можете также пропустить нитинол через тонкую наждачную бумагу для лучшего электрического контакта.

А сейчас мы займемся нитиноловой проволокой, которая необходима для перемещения ног вверх и вниз.

[the bridge]
Рис. 7: "Мост"

Натяните проволоку так, как если бы вы хотели построить мост. Начните с одной стороны, где пропустите нитинол сквозь последнее свободное отверстие cлева. Завяжите узел на проволоке (для уверенности, что соединение надежное) и наденьте на нее зажим (приготовленный заранее 4мм-й отрезок трубки), после чего обожмите его. Пропустите проволоку через второе отверстие сверху и затем через последнее свободное отверстие слева. С нижней стороны завяжите узел и обожмите его. Нитиноловая проволока должна быть натянута, но не слишком сильно. Если вы слегка коснетесь ее, она должна провинуть на 2-4мм. Если проволока недостаточно натянута, или натянута слишком сильно, робот не будет двигаться как надо. Припаяйте зажимы к плате.
Сделайте то же самое на второй стороне
Перед тем, как продолжить, испытайте, как все это работает. Возьмите миниатюрную батарейку на 1.5В и подсоедините ее к нитиноловой проволоке. Когда проволока сократиться, средняя часть тела робота должна повернуться на 10-20 градусов. Будьте осторожны, не держите батарейку подсоединенной дольше 1 секунды. Вы повредите проволоку, если перегреете ее.

Ноги


[music wire for legs]
Рис.8: Как согнуть проволоку

Откусите от струны три отрезка длиной 10см, они будут использоваться в качестве ног. Согните каждую на расстоянии 1.5см от обоих концов. Припаяйте струны к трем частям робота. Они должны быть параллельны друг другу.

[legs top view]

[legs bottom viewl]
Рис. 9, 10: Как укрепить ноги на роботе

Теперь вы должны прикрепить нитиноловую проволоку, играющую роль привода, ко всем шести ногам.

[leg and nitinol]
Рис. 11: Установка приводов

Пропустите нитиноловую проволоку сверху сквозь зажим и сквозь отверстие на монтажной плате. Расстояние до струны - 3 отверстия. Обожмите ее как следует (см. рис. ниже).
Затем тяните зажим по струне, пока не достигнете коленного изгиба. Вставьте нитинол в зажим и плотно обожмите его. Теперь самое трудное. Удерживая робота с помощью небольших тисков, обмотайте его ноги клейкой лентой или дополнительным медным проводом. Музыкальная струна создает противодействие нитинолу, который должен вплотную прилегать к ней. Струну следует вытянуть через отверстие в 1-й монтажной плате в направлении нитинола, после чего зажим должен быть припаян к ноге.
[nitinol must not be loose]
Рис. 12: Нитинол и струна на одном уровне


Убедитесь, что нитинол и струна находятся на одном и том же уровне. При сокращении нитинола ноги должны двигаться назад, а не перемещаться вверх и вниз.

Сделайте то же самое с остальными пятью ногами.
Ноги и струна с латунными трубками посередине робота выполняют функции шины подвода питания, поэтому между ними должен быть электрический контакт. Однако средняя часть туловища должна вращаться, вследствие чего у нее отсутствует надежное соединение. Мы исправим положение, взяв 3см 0.1мм-го провода в лаковой изоляции и намотав его на неиспользованную латунную трубку, чтобы получилась небольшая спираль. Выньте трубку и припаяйте спираль к середине внутренней пары ног и внешней паре ног. Свитый в виде спирали провод обеспечивает максимальную гибкость.

Когда робот будет готов, припаяйте 0.5м (или длиннее, если хотите) отрезки 0.1мм провода к зажимам на плате и припаяйте сами зажимы к монтажной плате. Нам понадобится 9 проводов, 6 для ног, 2 для поднятия пар ног вверх и вниз и 1 для шины питания. Вы можете припаять другие концы проводов к небольшому коннектору, который затем вы будете включать в соответствующее гнездо в блоке управления.

 

Я милого узнаю по походке

Наше насекомое создано для трехногой ходьбы. Это означает, что пока три ноги (две на левой и одна на правой стороне) находятся на земле, другие три приподняты. Когда робот идет, ноги на земле двигаются в одном направлении, в то время как приподнятые - в обратном.
[The gait]
Рис. 13: Способ хотьбы



 

Управление роботом с помощью Linux компьютера

 

Схема блока управления

Блок управления позволяет использовать ваш PC для контроля над приводами робота, включается он в параллельный порт.
Когда мы разрабатывали нашу компьютерную программу, то первым делом проверяли ее на светодиодах и включали провода управления в гнезда лишь после того, как светодиоды показывали правильную походку, что говорило о корректной работе программы.
Робот весьма прожорлив. Вам нужно пропускать ток 200-250мА через нитиноловую "мускулатуру", чтобы заставить ее сокращаться. Сопротивление 3см нитиноловой проволоки на ноге около 7 Ом. Всегда запускайте программу перед подачей питания на блок управления, потому что в этом случае значение управляющего сигнала на контактах будет "Выкл", что позволит избежать повреждения нитинола. Поскольку BIOS компьютера устанавливает случайные значения на контактах параллельного порта, некоторые из них могут получить состояние "Вкл", вследствие чего ток через проволоку будет протекать гораздо дольше одной секунды и повредит ее. Время охлаждения нитинола должно равняться 1.5 времени нагрева.

Электросхема:
[circuit]
Рис. 14: Электросхема

Как вы видите на схеме выше, мы используем стабилизированный блок питания. Это нужно для обеспечения хорошего стабильного питания и для защиты параллельного порта. В качестве внешнего источника вы можете подсоединить любой блок питания с постоянным током и напряжением на выходе 6В и 24В. Микросхема 7805 является стандартным регулятором напряжения. Единственная вещь, на которую вам следует обратить внимание, это расположение двух конденсаторов (470мкФ и 0.1мкФ). Установите их как можно ближе к регулятору напряжения 7805, потому что он может начать раскачиваться и выйдет из строя.

Устройство управления должно быть собрано восемь раз. По разу для каждой ноги и два раза для перемещения пар ног вверх и вниз. Мы используем маленький n-p-n Дарлингтон-транзистор, потому что нашему роботу нужен сильный ток. BC875 или BC618 могут коммутировать около 500мА. Резистор 47кОм на входе нужен для обеспечения состояния "Выкл" открытой цепи (например, когда компьютер не подключен). Напряжение на параллельном порту около 4В для состояния "Вкл" и ниже 1В для "Выкл". Транзистор работает только как коммутатор. Резисторы 15 Ом ограничивают ток и защищают ноги робота и транзистор. Светодиоды показывают состояние ("Вкл" или "Выкл").

Ниже вы видите снимки монтажа. Красные светодиоды (включенные параллельно приводам робота) трудно различить, поскольку мы использовали прозрачные красные светодиоды. Мы сделали резисторы на 15 Ом из константановой проволоки, свитой в спираль, но лишь потому, что у нас было ее много. Дешевле купить два резистора мощностью 2Вт.


[the final drivercircuit1] [the final drivercircuit2]
Рис.15: Монтаж



 

Параллельный порт

Параллельный порт был разработан в качестве выходного порта с персонального компьютера на принтер. Некоторые параллельные порты позволяют работу на вход и выход. Здесь мы используем порт только как выход. В одной из следующих статей мы подключим к роботу датчики и будем использовать входные линии. Хотя параллельный порт имеет 25 линий, мы используем лишь 9. Восемь линий использованы как выходные линии и одна для подключения электрической земли.

Цоколевка параллельного порта:

25-контактный D-SUB "мама" для PC.

Контакт  Обозначение  Направление   Описание
 1       STROBE       [-->]      Строб (готовность данных)
 2       D0           [-->]      0 бит данных
 3       D1           [-->]      1 бит данных
 4       D2           [-->]      2 бит данных
 5       D3           [-->]      3 бит данных
 6       D4           [-->]      4 бит данных
 7       D5           [-->]      5 бит данных
 8       D6           [-->]      6 бит данных
 9       D7           [-->]      7 бит данных
 10      ACK          [<--]      Контроль приема данных
 11      BUSY         [<--]      Принтер не готов к приему (занят)
 12      PE           [<--]      Кончилась бумага
 13      SEL          [<--]      Контроль состояния принтера
 14      AUTOFD       [-->]      Автоматический перевод строки после
                                    перевода каретки
 15      ERROR        [<--]      Ошибка
 16      INIT         [-->]      Инициализация принтера
 17      SELIN        [-->]      Принтер готов работе
 18      GND          [---]         Корпус
 19      GND          [---]         Корпус
 20      GND          [---]         Корпус
 21      GND          [---]         Корпус
 22      GND          [---]         Корпус
 23      GND          [---]         Корпус
 24      GND          [---]         Корпус
 25      GND          [---]         Корпус
Вы подсоедините блок управления к 18-му контакту (Корпус) и к контактам вывода данных 2-9

Обычно параллельный порт работает следующим образом. Когда на линии данных передано по одному байту, компьютер выставляет сигнал "1" на линии готовности данных (строб), сообщающий принтеру, что в линиях данных имеется информация. Мы используем линии данных напрямую, потому что нам не нужны дополнительные логические операции с участием строба.

 

Программное обеспечение

Вы можете загрузить программное обеспечение отсюда.
Распакуйте его командой tar zxvf pprobi*.tar.gz. Инструкции по установке прилагаются.

Программа написана на C. С помощью клавишей-стрелок вы можете управлять роботом, заставляя его ходить вперед, направо, налево и назад. Используйте пробел для остановки и q (или x) для выхода из программы. Вместо стрелок вы также можете использовать клавиши h,j,k,l (раскладка как в vi), если вам так больше нравится. Переменные, использованные для установки движения робота, оптимизированы для нашей модели. Каждый робот немного отличается от другого, в основном потому, что трудно добиться одинакового натяжения нитиноловых проволок. Ваш робот будет работать с программой без внесения в нее изменений, однако возможно, что не все ноги будут двигаться одинаково, так что вы должны будете поэкспериментировать для нахождения наилучших значений переменных. Вам нужно лишь позаботиться о том, чтобы ноги не перегревались и чтобы у них было достаточно времени для охлаждения.

==== pprobi.c =====
/* vim: set sw=8 ts=8 si : */
/*
 * Эта программа является свободным программным обеспечением.
 * Вы можете распространять
 * или изменять ее в соответствии с Общедоступной лицензией GNU.
 * Подробности на http://www.gnu.org/copyleft/.
 *
 * Авторы Katja Socher <katja@linuxfocus.org>
 *      и 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


Программа использует интерфейс ppdev ядра версии 2.4.х (вам нужны ядра версий 2.3.х или 2.4.х, с более старыми она не будет работать). Это простой и удобный интерфейс для написания пользовательских драйверов параллельного порта. При использовании более старых ядер мы были бы должны написать модуль ядра или использовать кривой метод, который требовал бы привилегий root для запуска программы. Интерфейс ppdev использует файл устройства /dev/parport0 и путем установки владельца и прав доступа вы можете контролировать, кому позволено использовать этот интерфейс.

Для компиляции ppdev как модуля в ядро вам нужно скомпилировать модуль PARPORT вместе с устройством PPDEV. В файле .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
#


В первую очередь программа инициализирует параллельный порт командой ioctl PPCLAIM. Затем она устанавливает терминал в режим non canonical. Это нужно для того, чтобы получать ввод напрямую с клавиатуры без необходимости нажимать Enter после каждого ввода. Потом программа входит в цикл, где вначале проверяет, не было ли ввода данных пользователем, а затем позволяет роботу двигаться в соответствии с командой. Если вы не даете команд, программа просто будет продолжать выполнять последнюю введенную команду (например, двигаться прямо).
Команда ioctl(fd, PPWDATA, &bitpat); используется для наложения заданной маски на линии данных.

Контакты вашего робота должны быть подсоединены к выходным линиям блока управления следующим образом:

Ноги:
  A1------=------B1
          =
          =
  B2------=------A2
          =
          =
  A3------=------B3


  Контакт для подключения A-ног на корпус = AD
  Контакт для подключения B-ног на корпус = BD

Соответствие выходных линий блока управления:
  data 0           A1
  data 1           A2
  data 2           A3
  data 3           AD
  data 4           B1
  data 5           B2
  data 6           B3
  data 7           BD

Линия данных "0" является выходом блока управления, который подсоединяется к параллельному порту на 2-й контакт (D0).

Вот он, идущий робот:
[yes, it walks]
Он двигается слишком быстро на картинке. На самом деле робот немного медленнее из-за затрат времени на охлаждение, которое требуется нитиноловой проволоке для возвращения ее к первоначальной длине.


Мы надеемся, что вы получите много удовольствия, собирая робота. Сообщите нам о нем, особенно если он имеет другую конструкцию!

 

Список литературы и ссылки

 

Страница отзывов

У каждой заметки есть страница отзывов. На этой странице вы можете оставить свой комментарий или просмотреть комментарии других читателей.
 talkback page 

Webpages maintained by the LinuxFocus Editor team
© Katja and Guido Socher, FDL
LinuxFocus.org

Click here to report a fault or send a comment to LinuxFocus
Translation information:
en -> -- Katja and Guido Socher
en -> ru Ilya Palagin

2001-10-12, generated by lfparser version 2.17