| Веб-камера на сервоприводах: совмещаем простой код и железо с помощью Arduino
Если ты всю жизнь завидовал гикам из американских фильмов, которые из всякого
хлама ловко делают роботов или системы контроля доступа, — настал твой час.
Когда писать обычные программы надоедает, а хочется, чтобы код заставил работать
что-то физическое, путь даже робота на столе, пора переходить в другую лигу.
Можно начать с физики и узнать, чем отличается транзистор от конденсатора, а
можно сразу купить контроллер Arduino и действовать.
Программирование микроконтроллеров на базовом уровне — не такая уж и сложная
вещь. Если ты внимательно читал замечательные статьи во "Фрикинге" по этой теме,
то должен отлично это понимать. И все-таки, чтобы сделать что-то действительно
стоящее, придется немало попыхтеть, изучить множество материала, попробовать
полученные знания в деле, и только потом получить какой-то осязаемый результат.
Но, к счастью, есть вариант создать работающий девайс здесь и сейчас самой малой
кровью. И в этом нам поможет замечательная разработка — контроллер Arduino.
Разбираться в его основах было бы чрезвычайно скучно, поэтому мы не будем долго
размусоливать теорию, а сразу покажем его в действии. Задача — проапгрейдить
обычную веб-камеру, снабдив ее возможностью поворачиваться в нужном
направлении по нашей команде. Приступим?
Что такое Arduino?
Девайс, который мы выше назвали
Arduino,
представляет собой простую и удобную плату ввода/вывода со встроенной средой
разработки на специальном языке Wiring. Прелесть в том, что язык этот фактически
является C++, поэтому нет никакой необходимости осваивать набор программ
контроллера и фактически писать программу на ассемблере. Плата Arduino состоит
из микроконтроллера ATmega328 или ATmega168 и небольшой элементной обвязки для
программирования и интеграции с другими схемами. На каждой плате обязательно
присутствуют линейный стабилизатор напряжения 5 В для питания микроконтроллера и
16 МГц кварцевый резонатор, задающий тактовую частоту работы микроконтроллера
(МК). Все эти данные — лишь для общего развития. Нам важно знать другое. В
микроконтроллер предварительно прошивается загрузчик (бутлоадер), это значит,
что внешний программатор не нужен, и прошивка пользовательских программ (так
называемых скетчей) производится из Arduino IDE нажатием одной кнопки. "В чем
фишка?", — спросишь ты. Суди сам: чтобы залить (прошить) программу в большинство
микроконтроллеров требуются специальные устройства — программаторы. Для разных
МК и других нужд существует куча программаторов — от специализированных (шьет
только AVR) до универсальных (шьет все), от простых (7 проводков от LPT-порта к
ножкам МК) до сложных (часто и сами они построены на МК). Общая проблема
программаторов в том, что их надо где-то взять (купить, взять у товарища, спаять
самому). А теперь почувствуй разницу: для Arduino программатор не нужен.
Прошивка может заливаться в нее через обычный USB-шнурок. Более того, саму
Arduino можно использовать как программатор и шить ею другие МК! Питаться
Arduino может как от внешнего постоянного напряжения 9- 2В (то есть запитать
ардуину можно от блока питания компьютера или ноутбука, батареек или
аккумуляторов), так и от USB-порта компьютера. Короче говоря, чтобы начать
работать с микроконтроллером, нужна только сама плата и USB-шнурок типа A-B,
которым к ПК подключаются принтеры.
Взять и сделать
Освоить работу с микроконтроллером можно буквально за один вечер. Для этого
нужно понимать несколько вещей. Arduino — это плата ввода/вывода. Нам доступны
14 цифровых вводов/выводов и шесть аналоговых входов. К этим выводам
подключаются многие другие девайсы, вроде моторчиков, датчиков и т.д. С их
помощью мы можем передавать команды или наоборот получать какие-то данные. Если
не вдаваться в подробности, то цифровые порты Arduino позволяют работать с
логическими 0 и 1. Аналоговые входы позволяют считывать значение напряжение на
порту с точностью до 5 мВ. Это первое, что надо запомнить.
Но без программы микроконтроллер — это не более чем бесполезная железка. Для
того, чтобы он начал выполнять какие-то задачи, его необходимо программировать.
Это второй момент.
Программировать Arduino можно как из родной среды — специальной Arduino IDE,
которая использует язык Wiring (по сути, это обычный C++), так и через
популярную среду программирования микроконтроллеров семейства AVR — WinAVR. В
последнем случае код необходимо писать на чистом C. Простота в освоении Arduino
привлекает новичков, вызывают негодование у профессиональных программистов
микроконтроллеров. Разумеется, как и в любом холиваре, здесь есть своя правда у
обеих сторон. Документация на Arduino доступна на
официальном сайте Arduino.
Помимо этого под открытой лицензией распространяется и схема микроконтроллера,
поэтому у оригинального Arduino существует множество клонов. Само название
Arduino является торговой маркой, и поэтому все платы-клоны называются иначе
(хотя и имеют в своем названии "duino"): например, Freeduino, Seeduino или
отечественный аналог — CraftDuino. Приобрести оригинальную плату Arduino можно,
например, в
Linuxcenter или, если хочешь сэкономить, в каком-нибудь западном
интернет-магазине (скажем,
www.sparkfun.com). Цена вопроса — от $30.
Дополнительные шилды
Впрочем, прелесть Arduino не заканчивается в простоте подключения и легкости
программирования под него. Огромное число энтузиастов пишут для микроконтроллера
программные библиотеки — своего рода модули, которые ты можешь подключить к
своей программе. В результате, всего несколькими строчками кода можно управлять
сервомашинками, взаимодействовать с компьютерной клавиатурой/мышкой и т.д. Более
того, для Arduino разрабатываются так называемые шилды — платы-дополнения
(модули, только аппаратные), которые невероятно расширяют возможности
контроллера. Например, Ethernet-шилд позволяет подключить Arduino к компьютерной
сети и даже работать в интернете (клиентом или сервером). Есть GSM-шилд для
взаимодействия с сотовой сетью, GPS-шилд для взаимодействия с GPS-приемниками,
Wi-Fi-шилд для работы с беспроводными сетями и т.д. Все это дает невероятную
возможность на простой платформе создавать сложные и хитроумные девайсы. По
сути, Arduino превращается в конструктор для быстрого прототипирования и
воплощения в жизнь самых безумных идей, не требующий при этом паяльник. Любая
возможность автоматизировать что-то с легкостью реализуется с Arduino!
Выкладывать ритм сердцебиения в Twitter? Или через инет удаленно включить полив
цветов? Легко! Автоматизация аквариума, элементы умного дома, кодовый замок или,
наоборот, цифровая отмычка в виде универсального ключа — все это возможно с
помощью Arduino. Мы же сегодня попробуем еще одну отрасль, в которой так силен
микроконтроллер — робототехнике.
Управляемая камера
Чтобы не быть голословным, попробуем взять вполне полезную задачу. В нашем
распоряжении есть веб-камера и Arduino. Условие — сделать управляемую камеру и
управлять углом ее обзора с компьютера. Приводить в движение мы ее будем с
помощью так называемых сервоприводов. Вообще для движения камеры можно было бы
использовать специальные моторчики. Но чтобы управлять обычными моторчиками,
Arduino, как и любому контроллеру, требуется силовой модуль (так называемый
драйвер). Зачем он нужен? Дело в том, что токи, которыми может управлять
микроконтроллер, очень малы (не более 40 мА на порт). Любым же исполнительным
устройствам типа моторчиков требуются для работы токи намного большие. И если
подключить их напрямую к МК, то он просто сгорит. Поэтому и получается, что
напрямую к портам Arduino можно подключать только обычные светодиоды (да и те
нужно включать через токоограничительный резистор). Обычно в роли такого
драйвера выступает микросхема L293D (именно на базе этой микросхемы построен
Motor-шилд — дополнительная плата, подключаемая к Ардуино и позволяющая
управлять двумя моторчиками). Это сложно. Зато помимо моторчиков приводить в
движение легкую камеру можно еще и с помощью сервомашинок. Сервомашинка — это
мото-редуктор, способный поворачивать выходной вал на заданный угол и удерживать
его в этом положении. Плюс сервы в том, что никаких дополнительных модулей для
управления не требуется, и кроме того, их можно подключать к Arduino напрямую.
Разумеется, питать сервомашинки (особенно мощные) лучше от отдельного источника,
но маломощную и самую дешевую SG-90 можно подключать прямо к USB. Приобрести
сервомашинки можно опять же в любом интернет-магазине электроники по $5 за
штуку.
Как управлять сервоприводом?
Вообще, сервоприводы нужны в первую очередь, моделистам, для управления
положениями закрылок, рулей и вертолетных лопастей. Вал мотор-редуктора жестко
связан с движком переменного резистора. Резистор подключен в схему контроля и
своим текущим сопротивлением сообщает о текущем положении вала. На схему
контроля поступают сигналы управления, сообщающие, в какое положение нужно
повернуть выходной вал (и резистор соответственно). Схема подает питание на
моторчик и крутит им до нужного угла (сопротивления резистора), там замирает и,
если что-нибудь повернет вал из нужной точки, вернет ее на место. При этом
управлять сервой очень просто — у нее есть три провода:
- земля (коричневый/черный)
- питание +5 вольт (красный)
- сигнальный (оранжевый/желтый/белый).
Управление импульсное, по сигнальному проводу. Особая прелесть состоит в том,
что сигнальный провод слаботочный — импульсы можно давать непосредственно с ноги
микроконтроллера. Чтобы удерживать определенную позицию — импульс должен
повторяться. Все это может звучать сложно, но на деле довольно просто. Задача
упрощается еще и потому, что в комплекте штатных библиотек Arduino IDE уже есть
библиотека
Servo для управления сервомашинками. В результате очень просто можно
набросать код, который заставит серву делать поворот от 0 до 180 градусов и
обратно:
#include <Servo.h>
Servo myservo;
// создаем объект для контроля сервы
// максимальное количество таких объектов — 8
int pos = 0;
// переменная для хранения позиции сервы
void setup()
{
myservo.attach(9); // серва подключена к девятому пину
}
void loop()
{
for(pos = 0; pos < 180; pos += 1)
// от 0 до 180 градусов
{
// с шагом в 1 градус
myservo.write(pos);
// устанавливаем положение
delay(15);
// ждем 15 мс пока серва займет новое положение
}
// и обратно
for(pos = 180; pos>=1; pos-=1)
// от 180 до 0 градусов
{
myservo.write(pos);
delay(15);
}
}
Пишем программу для Arduino
Для того, чтобы управлять камерой, нам понадобится две сервомашинки. На
качалку первой сервомашинки прикрепим веб-камеру, которая будет отвечать за
высоту (широту) поворота камеры. Теперь закрепим первую серву на качалке второй
— она отвечает за азимутальный угол поворота. То, что у меня получилось, можно
увидеть на картинке.
Схема управления очень проста. Берем Arduino или аналог (в моем случае —
CraftDuino) и просто подключаем сервомашинки напрямую к плате. То есть
управляющий выход одной сервы подключаем к седьмому порту, а другой — к
восьмому. Вот и все :).
С механикой разобрались, осталось собрать схему управления и написать две
программы: одна для Arduino, а второй будет управляющая программа для ПК. В
нашем случае углы поворота сервомашинок мы будем передавать по последовательному
порту с управляющей программы на ПК. Arduino просто должна получить значение
угла поворота и повернуть нужную серву на заданный угол. Как я уже сказал, для
работы с сервомашинками есть готовая библиотека Servo (идет в составе Arduino
IDE). Для взаимодействия с программой на ПК мы тоже не будем выдумывать свой
велосипед, а воспользуемся готовой библиотекой Firmata, которая, так же как и
библиотека Servo, уже входит в стандартный набор библиотек Arduino IDE. Firmata
— это протокол, позволяющий простым образом общаться программе на контроллере
Arduino с программами на компьютере. В результате недолгих экспериментов у меня
получился следующий код для Arduino, который я по ходу поясню в комментариях:
#include <Firmata.h>
#include <Servo.h>
Servo servo7; // объекты класса Servo
Servo servo8; // для работы с сервомашинками
// функция, обрабатывающая аналоговые сообщения
Firmata
void analogWriteCallback(byte pin, int value)
{
if(pin == 7)
servo7.write(value);
// поворачиваем серву на угол value
if(pin == 8)
servo8.write(value);
}
void setup()
{
// устанавливаем версию протокола
Firmata.setFirmwareVersion(0, 2);
// задаем функцию-обработчик сообщений
Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
servo7.attach(7);
// указываем порт подключения сервы
servo8.attach(8);
Firmata.begin(9600);
// инициализация библиотеки Firmata
}
void loop()
{
while(Firmata.available())
// если есть сообщения
Firmata.processInput();
// запускаем функции-обработчики
}
Теперь этот несложный код компилируем и заливаем получившуюся программу в
Arduino. Для этого необходимо запустить Arduino IDE, выбрать свою версию платы
через меню "Tools q„ Board", затем указать порт, к которому она подключена ("Tools
„Ђ Serial Port"), вставить код и нажать на кнопку компиляции. После завершения
компиляции в строке состояния появится сообщение "Done compiling". Остается
только нажать кнопку "Загрузить скетч в Arduino", и программа начнет прошиваться
в МК. Если все прошло хорошо, загрузка завершается сообщением "Done uploadling".Ура,
механика и электроника готовы! Осталось написать программу для управления этим
мини-роботом.
Управляющая программа
Разработать программу для ПК ты можешь на любом удобном для тебя языке
программирования, но я выбрал С++. Так как в дальнейшие планы входит научить
этого мини-web-cam-бота самостоятельно обнаруживать объекты и следить за ними,
то для работы с камерой я воспользуюсь библиотекой
OpenCV.
Это открытая библиотека компьютерного зрения, которая до первой версии
разрабатывалась в Центре разработки программного обеспечения Intel (причем
российской командой в Нижнем Новгороде). Фактически, OpenCV — это набор данных,
функций и классов для обработки изображений алгоритмами компьютерного зрения.
Эта библиотека очень популярна за счет своей открытости и возможности бесплатно
использовать как в учебных, так и коммерческих целях.
Идея нехитрая: подключаемся к веб-камере и показываем то, что она "видит".
Также выведем в окошко с картинкой пару ползунков, с помощью которых будем
управлять положением сервомашинок. Так как в моей конструкции робота веб-камеру
пришлось закрепить на боку, то в программе приходится это исправлять
(поворачивать картинку на 90 градусов против часовой стрелки). Эта процедура
реализуется функцией rotate(), являющейся оберткой вокруг функции OpenCV:
cvWarpAffine(), которая и выполняет поворот изображения. Полный код программы ты
найдешь на диске, а здесь я приведу
только функцию-обработчик, который считывает положение ползунков в управляющей
программе и отправляет их в качестве команды на микроконтроллер:
// положение первой сервы
int A = 0;
int Amax = 180;
// положение второй сервы
int F = 0;
int Fmax = 180;
IplImage* dest = 0;
//
// функции-обработчики ползунков
//
void myTrackbarA(int pos) {
A = pos;
// Firmata
char buf[3];
buf[0] = 0xE0 | 7;
buf[1] = A & 0x7F;
buf[2] = (A >> 7) & 0x7F;
sg.Send(buf, 3);
Sleep(100);
}
Вот, собственно, и все. Теперь момент истины.
Компилируем код, пробуем его запустить, двигаем ползунки. Сервоприводы издают
звук, и — да, камера двигается! Работает! Если у тебя возникнет желание
повторить подобный опыт, то на освоение всей платформы у тебя едва ли уйдет
больше одного вечера. Каких-то несколько часов — и ты уже можешь создавать
работающие девайсы. Бывалые фрикеры, возможно, скажут, что Arduino годится разве
что для новичков. Но даже если так, то что? Главное, что через минимальное время
ты можешь получить результат.
| |