Программирование роботов в домашних условиях

Введение

В своём индивидуальном задании я хотел бы рассказать о том, как можно весело провести время, применив полученные в университете знания на практике :). Программирование роботов, а точнее микроконтроллеров, на которых они построены, - это не сложно. Вот увидите! Начну с теории и описания всего того, что нам пригодится.

Что такое Arduino?

Arduino – аппаратная вычислительная платформа, основными компонентам которой являются простая плата ввода/вывода и среда разработки на языке Processing/Wiring. Arduino может использоваться как для создания автономных интерактивных объектов, так и подключаться к программному обеспечению, выполняемому на компьютере. Документация на аппаратную часть и программный код опубликованы под лицензией «copyleft», но разработчики выразили желание, чтобы название «Arduino» (и производные от него) было торговой маркой для официального продукта и не использовалось для производных работ без разрешения. В официальном документе об использовании названия Arduino подчеркивается, что проект открыт для всех желающих работать над официальным продуктом.

До недавнего времени создание роботов считалось очень непростой процедурой, требующей от разработчика высокой квалификации и специального образования, а также длительного времени на разработку. Но с появлением плат Arduino это занятие может позволить себе почти каждый, кто хоть немного знаком с программированием! Потому как подключение платы к компьютеру не сложнее подключения к нему, например, флешки, а запрограммировать нужные операции требуется на «упрощенном Си» в специальной интегрированной среде разработки, откуда одним нажатием кнопки мыши можно сразу же и прошить плату. Проще некуда, но обо всем по порядку.

Плата Arduino состоит из микроконтроллера Atmel AVR (ATmega328 и ATmega168 в новых версиях и ATmega8 в старых) и элементной обвязки для программирования и интеграции с другими схемами. На каждой плате обязательно присутствуют линейный стабилизатор напряжения 5 В и 16 МГц кварцевый генератор (в некоторых версиях керамический резонатор). В микроконтроллер предварительно прошит загрузчик, поэтому внешний программатор не нужен.

На концептуальном уровне все платы программируются через RS-232 (последовательное соединение), но реализация этого способа отличается от версии к версии. Текущие версии плат, программируются через USB, что осуществляется благодаря микросхеме конвертера USB-to-serial вроде FTDI FT232. В некоторых вариантах для программирования требуется подключение отдельной платы USB-to-serial или кабеля.

Проект Arduino постоянно развивается и имеет множество модификаций. На данный момент доступны 10 версий плат, но конкретно в данном проекте использовалась плата Arduino Diecimila. Она представляет собой небольшую электронную плату, ядром которой является микроконтроллер ATmega168. На плате есть: 14 цифровых входов/выходов, 6 из которых могут работать в режиме ШИМ (PWM) (а следовательно управлять аналоговыми устройствами вроде двигателей и передавать двоичные данные), 6 аналоговых входов (исходной информацией служат не логические 0/1, а значение напряжения), тактовый генератор на 16 МГц, разъёмы питания и USB, ICSP-порт (что-то вроде последовательного интерфейса для цифровых устройств), несколько контрольных светодиодов и кнопка сброса. Этого вполне достаточно, чтобы подключить плату к USB-порту компьютера, установить необходимое программное обеспечение (драйвер и среду разработки) и начать программировать.

Внешний вид платы Arduino Diecimila.
Рисунок 1. - Внешний вид платы Arduino Diecimila.

Краткая спецификация

Преимущества и недостатки

Низкая цена. Платы Arduino относительно недороги по сравнению с другими микроконтроллерными платформами. Самый дешёвый вариант модуля Arduino может быть собран вручную, но даже предварительно собранные модули Arduino стоят менее $50.

Кросс-платформенность. Программное обеспечение Arduino работает под управлением операционных систем Windows, Macintosh OS X и Linux, поскольку является открытым и работает на Java. Большинство микроконтроллерных систем ограничиваются Windows.

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

Открытый исходный код. Язык может быть расширен с помощью библиотек C++, более продвинутые специалисты могут создать свой собственный инструментарий для Arduino на основе компилятора AVR C.

Открытые спецификации и схемы оборудования. Arduino основан на микроконтроллерах ATMEGA8 и ATMEGA168 от Atmel. Схемы модулей опубликованы под лицензией Creative Commons, поэтому опытные схемотехники могут создать свою собственную версию модуля для своих нужд. Даже сравнительно неопытные пользователи могут сделать макетную версию модуля, чтобы понять, каким образом он работает, и сэкономить деньги.

Что же нужно для того, чтобы сделать своего робота?

Робота можно собственноручно собрать, как это делают многие энтузиасты, но можно переработать существующего. В качестве робота подойдет любая игрушка с подвижными деталями. В моём случае – это танк, с подвижными гусеницами, приводящимися в движение встроенными моторчиками (танк имел дистанционное управление). Вот этими моторчиками я и буду управлять с помощью платы.

Важным этапом, естественно, служит получение в своё распоряжение одной из плат Arduino. В моём случае это плата Arduino Diecimila. Также для подключения платы к компьютеру необходим USB кабель любой длины стандарта A-B. Через этот кабель будет осуществляться обмен данными между компьютером и микроконтроллером, а также подача питания на плату, т.е. внешний блок питания не обязателен. Еще один компонент, который необходим для управления моторами – это плата расширения MotorShield.

Плата расширения MotorShield и комплект деталей.
Рисунок 2. - Плата расширения MotorShield и комплект деталей.

Что и как подключать к MotorShield.
Рисунок 3. - Что и как подключать к MotorShield.

Далее нужно определиться с целями: мне нужно к имеющемуся игрушечному танку приделать дистанционное управление, но не обычное «куда нажал – туда поехал», а такое, при котором танку передавались бы координаты на воображаемом поле и он самостоятельно бы их достигал. Т.е. нужно представить, что комната (или любой другой участок, по которому будет двигаться танк) разбита на квадраты, представляющие собой систему координат. Тогда танку необходимо будет передавать координаты какого-либо квадрата и он должен будет повернуться к нему и проехать необходимое расстояние, чтобы стать в этот квадрат.

Процесс проектирования.
Рисунок 4. - Процесс проектирования.

Игрушечный танк с материнской платой.
Рисунок 5. - Игрушечный танк с материнской платой.

Материнская плата явно больше платы Arduino :).
Рисунок 6. - Материнская плата явно больше платы Arduino :).

Есть танк с моторами, есть плата, есть плата расширения. Необходимо средство для передачи координат. Это будет программа на компьютере пользователя, которая будет передавать данный на танк посредством Wi-Fi связи. Должен заметить, что Wi-Fi не понятен плате, поэтому на танке присутствует еще и обычная материнская плата (позже заменена на ноутбук :) ), которая будет от адаптера Wi-Fi транслировать данные в COM-порт, через который будет связь с платой Arduino. От нее сигналы уже будут поступать на плату расширения, и моторы должны будут закрутиться. Сложно это всё только на первый взгляд. На самом деле крепится все друг к другу просто, и задача сводится к написанию двух программ: одной – для передачи данных от компьютера пользователя на Wi-Fi адаптер, другой – для обработки данных внутри микроконтроллера.

Wi-Fi адаптер для приёма команд.
Рисунок 7. - Wi-Fi адаптер для приёма команд.

Итак, поехали!

Программу, отвечающую за обмен данными между ПК и микроконтроллером через COM-порт, писать можно на чём угодно. Пусть это будет Delphi.

Для краткости приведу исходный код только той функции, которая будет передавать танку команды, отвечающие за поворот и передвижение на нужные угол/расстояние. Функция принимает на вход текущие координаты (x0,y0), новые координаты (x1,y1) и текущий угол поворота танка alpha. Возвращать функция будет новый текущий угол. Текущие координаты и угол хранятся вне функции. Код откомментирован в нужных местах, поэтому описывать не стану.


Function MoveTank(x0, y0, x1, y1, alpha: integer): integer;
var newAlpha: integer; // новый угол
    FlagsField : byte; // содержит код направления движения
    angle_tmp: integer;
    TmpStr: string;
    angle, dist: byte; // угол и расстояние, передаваемые танку
begin
     // Вычисление нового текущего угла
     newAlpha := Round(ArcTan(Abs((x0-x1)/(y0-y1))));
     // Поворот относительно текущего положения
     angle_tmp := (360 + newAlpha - alpha) mod 360;
     // Расстояние между заданными координатами
     dist := Round(10*Sqrt(Sqr(x0-x1) + Sqr(y0-y1)));
     FlagsField := 0;
     // Определение оптимального направления движения
     if angle_tmp <= 90 then FlagsField := 0 // передом, вправо
     else if angle_tmp < 180 then
            begin
              angle_tmp := 180 - angle_tmp;
              FlagsField := FlagsField or 4;   // задом, вправо
            end
     else if angle_tmp < 270 then
            begin
              angle_tmp := angle_tmp - 180;
              FlagsField := FlagsField or 6;   // задом, влево
            end
     else   begin
              angle_tmp := angle_tmp - 270;
              FlagsField := FlagsField or 2;   //передом, влево
            end;

     angle := angle_tmp;

     // Далее нужно отправить в COM-порт сначала флаги, затем данные.
     FlagsField:= FlagsField or 1;    // для передачи угла
     TmpStr := Chr(FlagsField);
     ComPort_.Write(TmpStr);
     TmpStr := Chr(angle);
     ComPort_.Write(TmpStr);

     FlagsField:= FlagsField and 254; // для передачи расстояния

     TmpStr := Chr(FlagsField);
     ComPort_.Write(TmpStr);
     TmpStr := Chr(dist);
     ComPort_.Write(TmpStr);

     Result := newAlpha;
end;

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

В программе для приёма данных используется пин №9 (TxD). Соответственно 2й контакт СОМ порта материнской платы (RxD) необходимо подключить к пину №9 на Arduino. Ещё одно требование: нужно настроить СОМ порт материнской платы на скорость 9600 бод.

Для управления движением танка будем использовать два мотора - для левой и правой гусениц (разъемы M1 и M2 на Motor Shield). Для упрощения работы с моторами используем фреймворк AFMotor (http://www.ladyada.net/media/mshield), легко подключаемый к нашему проекту одной строкой «#include "AFMotor.h"». Моторы обозначим цифрами 1 для левой и 2 для правой гусениц. В коде, приведенном ниже, видно, что работа с моторами не представляет собой ничего сложного.


// библиотека для удобства обращения с движками
#include "AFMotor.h"

// пин на Arduino, куда подключен выход из COM-порта
#define TX             9

// кодирование команд от джойстика
#define cmdForward     1
#define cmdBackward    2
#define cmdRapidLeft   3
#define cmdRapidRight  4
#define cmdLeft        5
#define cmdRight       6

// скорости вращения движков
// MaxSpeed       - обычное движение
// MinSpeed       - скорость одной из гусениц при резком повороте
// HalfSpeed      - скорость одной из гусениц при плавном повороте
#define MaxSpeed       200
#define MinSpeed       100
#define HalfSpeed      150

// движение танка со скоростями левой и правой гусениц LTS и RTS
// в направлении Direction
void MoveTank(byte LTS, byte RTS, byte Direction);

// чтение одного байта с COM-порта
byte COMread();

// хранит команду, полученную с COM-порта
byte Command = 0;

// текущее направление движения
byte CurrentDirection = FORWARD;

// выбираем 1й и 2й разъемы на Motor Shield, куда подключены движки
AF_DCMotor LeftTrack(1, MOTOR12_1KHZ);
AF_DCMotor RightTrack(2, MOTOR12_1KHZ);

void setup()
{
  LeftTrack.setSpeed(MaxSpeed);
  RightTrack.setSpeed(MaxSpeed);
  pinMode(TX, INPUT);
}

void loop()
{
  Command = COMread();
  switch (Command)
  {
  case cmdForward:
    MoveTank(MaxSpeed, MaxSpeed, FORWARD);
    CurrentDirection = FORWARD;
    break;
  case cmdBackward:
    MoveTank(MaxSpeed, MaxSpeed, BACKWARD);
    CurrentDirection = BACKWARD;
    break;
  case cmdRapidLeft:
    MoveTank(MinSpeed, MaxSpeed, CurrentDirection);
    break;
  case cmdRapidRight:
    MoveTank(MaxSpeed, MinSpeed, CurrentDirection);
    break;
  case cmdLeft:
    MoveTank(HalfSpeed, MaxSpeed, CurrentDirection);
    break;
  case cmdRight:
    MoveTank(MaxSpeed, HalfSpeed, CurrentDirection);
    break;
  default:
    LeftTrack.run(RELEASE);      // останавливаем двигатели
    RightTrack.run(RELEASE);
    break;
  }
}

void MoveTank(byte LTS, byte RTS, byte Direction)
{
  LeftTrack.setSpeed(LTS);
  RightTrack.setSpeed(RTS);
  LeftTrack.run(Direction);
  RightTrack.run(Direction);
}

byte COMread()
{
  byte val = 0;
  while (digitalRead(TX));
  // ждем стартовый бит
  if (digitalRead(TX) == LOW)
  {
    delayMicroseconds(42);
    for (int k = 0; k < 8; k++)
    {
     delayMicroseconds(84);
     val |= digitalRead(TX) << k;
    }
    // ожидание 9го бита и стопового
    delayMicroseconds(168);
    return val;
  }
}

Осталось только прошить эту программку в Arduino (а делается это нажатием одной кнопки в интерфейсе Arduino IDE) и можно развлекаться, засылая танк в тыл врага :).

Заключение

Конечно, можно не ограничиваться просто пересылкой координат. Можно добавить интерактивности, используя для управления танком джойстик. А используя веб-камеру, прикрепленную к башне танка, можно наблюдать за движением, сидя за компьютером. Но для этого понадобится дополнительное ПО. Но даже это не делает программирование Arduino чем-то непосильным. Работать с такой платой просто, легко, а главное - доступно! Хотя нет, главное - это получение море удовольствия как от результата, так и от самого процесса!

Рекомендуемые ссылки

  1. http://www.ladyada.net/learn/arduino/ - Основной ресурс. Сайт посвящен электронике, гаджетам. Здесь есть множество уроков и примеров.
  2. http://www.arduino.cc - Официальный сайт Arduino
  3. http://ru.wikipedia.org/wiki/Arduino - Материал из Википедии.
  4. http://mk90.blogspot.com - Блог, посвященный вопросам, относящимся к сборке и программированию Arduino, оживлению микроэвм Электроника МК-90.
  5. http://freeduino.ru/lang.html - Описание основных функций языка Wiring
  6. http://habrahabr.ru/blogs/arduino/ - Блог Arduino на Habrahabr.ru
  7. http://www.freeduino.org - Известный во всём мире индекс знаний об Arduino и Freeduino