CraftDuino v2.0
  • - это CraftDuino - наш вариант полностью Arduino-совместимой платы.
  • CraftDuino - настоящий конструктор, для очень быстрого прототипирования и реализации идей.
  • Любая возможность автоматизировать что-то с лёгкостью реализуется с CraftDuino!
Просто добавьте CraftDuino!

Управляемая веб-камера или же web-cam-бот

Управляемая веб-камера
Не так давно я уже похвастался, что мою(и Zoltberg-а) статью про Arduino — «Веб-камера на сервоприводах» опубликовали в журнале Хакер. Статья уже выложена на их сайте и её можно прочитать здесь.

Вкратце расскажу про создание такой камеры.

Как видно на фотографии, я собрал поворотную основу для камеры из самых простых и дешёвых маленьких сервSG-90.
Камера крепится прямо к качалке верхней сервы, которая привинчивается к Г-образной загогулине, вылепленной из ПКЛ (поликапролактон — замечательный пластик для моделирования и прототипирования!). Эта же загогулина другим концом крепится к качалке второй сервы.

Основу я недолго думая вырезал из пластиковой бутылки :) Хотя можно было бы вылепить из того же пластика ПКЛ ;)

Вот и вся механика. Очень просто и быстро. Использовать ПКЛ для таких поделок сплошное удовольствие. Но если у вас нет под рукой паяльной станции с феном, то нужно держать наготове чайник с кипятком ;)
Так же обратите внимание, что массивные детали из пластика будут размегчаться дольше, чем мелкие. Это можно наблюдать по цвету. Нагреваясь пластик становится прозрачным, а в глубине у него может оставаться белый стержень более холодного и твёрдого пластика.

Далее обе сервомашинки напрямую подключаются к 7 и 8 портам контроллера Arduino/CraftDuino:


В данном случае Arduino/CraftDuino играет роль шлюза, т.е. углы поворота сервомашинок передаются контроллеру по последовательному порту от управляющей программы на ПК, а Arduino просто получает значение угла поворота и поворачивает нужную серву на заданный угол.

Для работы с сервомашинками воспользуемся библиотекой Servo, а для общения с контроллером через последовательный порт используем библиотеку Firmata, которая так же как и библиотека Servo уже входит в стандартный набор библиотек Arduino IDE.

Вот какая программа для Arduino у нас получится (фактически — это немного модифицированный пример, поставляемый с библиотекой Firmata)

#include <Firmata.h>
#include <Servo.h>

Servo servo7;
Servo servo8;

void analogWriteCallback(byte pin, int value)
{
    if(pin == 7)
      servo7.write(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);
}

void loop() 
{
    while(Firmata.available())
        Firmata.processInput();
}


Вот и всё — механика и электроника готовы и остаётся только написать программу для управления этим мини-роботом!

Так как дальнейшие планы научить этого мини-web-cam-бота самостоятельно обнаруживать объекты и следить за ними, то для работы с камерой я воспользуюсь библиотекой OpenCV.

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

Так как в моей конструкции робота web-камеру пришлось закрепить на боку, то в программе приходится это исправлять (поворачивать картинку на 90 градусов против часовой стрелки).
Эта процедура реализуется функцией rotate(), которая является обёрткой вокруг функции OpenCV: cvWarpAffine(), которая и выполняет поворот изображения (Аффинное преобразование).

//
// программа для управления 
// сервомашинками мини-web-cam-бота
// 
// robocraft.ru

#include <cv.h>
#include <highgui.h>
#include <stdlib.h>
#include <stdio.h>

#include "serial.h"

Serial sg; // для работы с COM-портом

// положение 1-й сервы
int A = 0;
int Amax = 180;

// положение 2-й сервы
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);
}

void myTrackbarF(int pos) {
	F = pos;
	// Firmata
	char buf[3];
	buf[0] = 0xE0 | 8;
	buf[1] = F & 0x7F;
	buf[2] = (F >> 7) & 0x7F;
	sg.Send(buf, 3);
	Sleep(100);

}

// функция поворота изображения на заданный угол
void rotate(IplImage* _image, double _angle=90)
{
	// матрицы трансформации
	CvMat* rot_mat = cvCreateMat(2,3,CV_32FC1);
	// вращение относительно центра изображения
	CvPoint2D32f center = cvPoint2D32f(_image->width/2, _image->height/2);
	double angle = _angle;
	double scale = 1;
	cv2DRotationMatrix(center,angle,scale,rot_mat);
	
	IplImage* Temp = 0;
	Temp = cvCreateImage(cvSize(_image->width, _image->height) , _image->depth, _image->nChannels);

	// выполняем вращение
	cvWarpAffine(_image,Temp,rot_mat);

	// сохраняем результат
	cvCopy(Temp, _image);

	cvReleaseImage(&Temp);
	cvReleaseMat(&rot_mat);
}

int main(int argc, char* argv[])
{
	// получаем любую подключённую камеру
	CvCapture* capture = cvCaptureFromCAM(CV_CAP_ANY);
	assert( capture );

	// устанавливаем ширину и высоту кадра
	cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 640);//1280); 
	cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 480);//960); 


	IplImage* frame=0;

     // окно для вывода изображения
	cvNamedWindow("capture", CV_WINDOW_AUTOSIZE);

	// инициализация COM-порта
	int port=19; // номер виртуального COM-порта Arduino
	printf("[i] try to open COM-port %d\n", port);
	bool b = sg.Open(port, 9600);
	if(!b)
	{
		printf("[!] Error open COM-port!\n");
		return 1;
	}
	printf("[i] ok\n");

	// добавляем ползунки для управления положением сервомашинок
	cvCreateTrackbar("A", "capture", &A, Amax, myTrackbarA);
	cvCreateTrackbar("F", "capture", &F, Fmax, myTrackbarF);

     // цикл обработки кадров с камеры
	while(true){
		// получаем кадр
		frame = cvQueryFrame( capture );
          // копируем изображение
		dest = cvCloneImage(frame);

		// поворачиваем картинку на 90 градусов
		rotate(dest);

		// показываем
		cvShowImage("capture", dest);

		// освобождаем изображение
		cvReleaseImage(&dest);
	
		char c = cvWaitKey(33);
		if (c == 27) { // нажата ESC
			break;
		}
	}
	// освобождаем ресурсы
	sg.Close();
	cvReleaseCapture( &capture );
	cvDestroyWindow("capture");
	return 0;
}


Вот и всё!
Главное — желание и хорошая идея! ;)

исходники к статье можно скачать по адресу:
http://robocraft.ru/files/opencv/servobot/servobot.zip
  • +1
  • 30 октября 2010, 10:49
  • noonv

Комментарии (25)

RSS свернуть / развернуть
+
0
Подскажите пожалуйста, чем компилируется второй код программы (программа для управления сервомашинками мини-web-cam-бота)?
avatar

Alex29

  • 31 октября 2010, 16:42
+
0
а с serial.h случайм serial.lib и serial.dll нет???, а то чёто ругается на неразрешенные внешние элементы… и она тока для Arduino или можно с чем угодно юзать?
avatar

Romiks

  • 1 ноября 2010, 21:39
+
0
исходники класса Serial есть в архиве. Ничего дополнительного ему не требуется. Как я уже указал — для передачи углов поворота используется протокол Firmata, но от него можно отказаться и использовать что-то другое — для этого нужно просто изменить содержимое функций
void myTrackbarA(int pos);
void myTrackbarF(int pos);
avatar

noonv

  • 1 ноября 2010, 22:05
+
0
спс
avatar

Romiks

  • 1 ноября 2010, 22:07
+
0
В общем остаточно оригинально и технически интересно, но имхо можно было бы и по красивей. Например самая нижняя серва отвечает не за горизантальный а за вертикальный угол, к ней в притык серва за горизонталь, камера весит на трубке. Тогда весь механизм и электронику можно спрятать в коробку с прорезью, и снаружи только камера. Так красивей смотреться будет.
avatar

mogalkov

  • 5 ноября 2010, 23:23
+
0
Я конечно извиняюсь, но конструкция у вас выглядит как-то не очень :-)
Я тож управляемую камеру делал (это наверное первая мысля у всех ардуиновцев, купивших первую серву), но управление по сети. Мало того — из браузера. Ардуина пашет независимо от компа, спасибо езернет шылду. Перемещение либо клавишами вверх-вниз-влево-вправо, либо мышой щёлкать по соответсвующим ссылкам. Но намного интересней пропорциональное управление — в брауере нарисован квадрат, все движения мыши с нажатой левой кнопкой фиксируются и пишутся в БД, откуда читаются и обрабатываются ардуиной.

Пара ссылок на эту мою управляемую хреновинку. Первая ссылка эт первый рабочий вариант, там сервы местами перепутаны были :-) Вторая ссылка — видеоролик уже с окончательной крутилкой, правда я там больше процесс движения камеры снимал, а не само управление. Вроде виден там зелёный квадрат для управления.
www.g0l.ru/blog/n2436
www.g0l.ru/blog/n2446

Сейчас камера отключена, ибо хочу доработать механику и на балкон поставить. Скетчи тож пока не выкладываю, ибо там сплошь тестовый говнокод :-D Но вот свою капельку опыта подкидываю, мож кому пригодится.
avatar

Gol

  • 8 ноября 2010, 00:34
+
0
Отличная работа! На счёт конструкции вы правы — просто делал всё очень быстро — хотел по-быстрее реализовать идею. Нужно будет переделать :)
Управление через Ethernet-шылд — тоже супер. Но у меня в планах добавить обработку видео и реализовать слежение за объектом ;)
avatar

noonv

  • 8 ноября 2010, 10:17
+
0
во, новый ролик снял www.g0l.ru/blog/n2563
правда, темновато получилось :-)
avatar

Gol

  • 9 ноября 2010, 14:19
+
0
Статья была написана больше года назад… но надеюсь мне ещё ктонибудь ответит… Пытался повторить вышеуказаный проект у себя, в качестве языка программирования использовал JavaSE в связке с библиотекой RXTX для общения по COM порту… столкнулся с проблеммой, как передавать сообщение контроллеру… Дело в том что функция myTrackbarF передает сообшения в виде массива char, а Java может отправлять либо массив байт, либо число типа int… Пробовал явное приведение типов (byte) char, никакого эффекта не получил… пробовал передавать последовательно 3 числа тоже не проходит… Подскажите как можно передать данные так, чтобы Firmata их схавал… Заранее спасибо.
avatar

Archi

  • 25 марта 2011, 06:37
+
0
уж точно не больше года назад, а в конце 2010-го :)))))
хм… а в примере как передаётся?
char buf[3];
        buf[0] = 0xE0 | 7;
        buf[1] = A & 0x7F;
        buf[2] = (A >> 7) & 0x7F;
        sg.Send(buf, 3);

— передаётся тот же массив байт О_о
avatar

noonv

  • 25 марта 2011, 10:05
+
+1
Всё, разобрался — моя ошибка незнание… byte — это тоже по сути своей char, только в числовом представлении… а сообщение у меня отправлялось… вот только отправлял я его всего один раз… А при первой отправки данных контроллеру он их куда то теряет, зато все последующие идут прямо на ура)
avatar

Archi

  • 25 марта 2011, 11:32
+
0
Доброго времени суток. Подскажите, как следует искать нужные точки на изображении и по ним уже делать поворот? Например что бы книга всегда была в вертикальном положение. Центрировать ее как то по углам же надо? Меня интересует поиск таких точек и дальнейший поворот на основе этих точек.
avatar

hellolsk

  • 20 марта 2015, 19:10
+
0
см. Трансформация изображения — аффинные преобразования, гомография. Соответственно, вам нужно сделать обратное преобразование, откуда получить углы поворота камеры.
avatar

noonv

  • 23 марта 2015, 10:38
+
0
Здравствуйте, а можно ли подключить еще одну серво-машинку (третью) чтобы она поворачивалась на запрограммированный угол когда камера находит движущийся объект? это нужно прописать в ардуино, но и в опен Cv? какие строки добавить и куда, спасибо
avatar

maxfaks

  • 7 октября 2015, 14:43
+
0
Привет! Можно. Разумеется, нужно будет прописать обработку и на контроллер Arduino и в программу на ПК.
avatar

noonv

  • 7 октября 2015, 17:03
+
0
Извините, а у вас есть почта?
avatar

maxfaks

  • 7 октября 2015, 17:14
+
0
или вк
avatar

maxfaks

  • 7 октября 2015, 17:21
+
0
Для всех вопросов есть форум.
avatar

noonv

  • 7 октября 2015, 17:22
+
0
я просто хотел чтоб вы дописали код под третью серву конечно не за просто так.
avatar

maxfaks

  • 7 октября 2015, 17:43
+
0
Код записан для пайтона2? Установил пайтон2, вгрузил код (мини-web-cam-бота), выдает синтактическая ошибка. ПОЧЕМУ?
avatar

ivan222

  • 14 апреля 2017, 18:24
+
0
А где вы увидели код на питоне?
avatar

admin

  • 15 апреля 2017, 20:53
+
0
Программа одна написана для ардуино, а другая я так понял для питона 2.
avatar

ivan222

  • 15 апреля 2017, 21:50
+
0
В данном случае, приводится программа на C++, но, разумеется, ничего не мешает реализовать подобное и на питоне.
avatar

admin

  • 15 апреля 2017, 21:56
+
0
А лучше этот проект на чем запускать?
avatar

ivan222

  • 15 апреля 2017, 22:35

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.