Робот удаленного наблюдения
- Войдите на сайт для отправки комментариев
Пнд, 08/12/2014 - 22:05

Потребовалось срочно разработать рабочий концепт роботизированной системы телеметрии для диплома. Так что забирайте если что)
Жена заканчивала университет и настало время писать диплом.
Так как я не программист по образованию, то пришлось делать действующую модель , а не программный продукт.
Первичный концепт формы был разработан довольно быстро- шар на трехколесной опоре. Шар был выбран по соображениям прочности формы и легкости изготовления на глаз, а трехколесная платформа- для удобства управления(впоследствии была изменена на четырехколесную).
Были заказаны 4 колеса из магазина Robocraft.
И примотаны синей изолентой к корпусу, ибо вытачивать крепления оказалось проблематично, а заказывать готовые поздно.

Для управления колесами были закуплены драйверы двигателей L293D(ибо простота и удобство). Делать отдельную плату не посчитал нужным и распаял все на макетке, отдельно добавил радиатор для температурной стабилизации.
<em>Да, при прохождении тока плата нагревается и ее характеристики плывут</em>
<em>Советую использовать быстросъемную панель для микросхемы(но у них иногда пропадает контакт)</em>
Отдельными ножками выведены 4 входа, 4 выхода и питание.


Но просто катающийся робот не тянет ни на систему телеметрии, ни на диплом.
Добавим ему манипулятор для взаимодействия с внешним миром.
Возьмем оргстекло(легко обрабатывается) и дешевые сервы за 300р. Выточим консоли(овальные проще изготовить) и вырежем крепежные отверстия. Теперь вырежем заготовку верхнего крепежа и согнем ее под 90 градусов.

Тесты показали что может приподнять сам себя и немножко воды в пластиковом стакане, ну и в котов тыкать тоже можно.
Теперь добавим возможность наблюдения, но просто камера тоже не пойдет - нет возможности обернуться или посмотреть в лицо собеседнику.

Для этого соберем модуль поворотной камеры "Глаз Саурона" из полосового алюминия и минисервоприводов за 150р, с 4 степенями сворбоды.

Так же смонтируем ArduinoMega к драйверам двигателей в распаечную коробку представляющую силовую часть.
Изменениям подвергнется и ходовая часть- она трехколесная и не позволяет развернуться на месте, это печалило руководителя диплома. В итоге ее сменили на четырехколесную- 2 ведущих по бокам и 2 всенаправленных спереди и сзади.
Наконец был смонтирован мозг- старенький нетбук, предоставляющий доступ к WiFi,интернету, возможности писать свой интерфейс и удаленный доступ. Вот такой вот мегашилд к ардуине.

Покупать аккумулятор+зарядное оказалось дороговато, поэтому он питался от розетки. На защите диплома это преподносилось как физическая защита от взлома- отъехал дальше положенного и выключился.
Теперь перейдем к коду ардуины и интерфейса.
Разработка программного обеспечения контроллера
Для написания исполняемого кода будем использовать Arduino IDE, в нем реализованы все необходимые библиотеки и функционал.
Далее я буду описывать написание кода с подробными комментариями о выполняемых действиях и выборе решений.
//Подключим стандартную библиотеку для обмена с компьютером
#include <SoftwareSerial.h>
//Подключим библиотеку управления сервоприводами
#include <Servo.h>
//Создадим две переменные для эмуляции сторожевого таймера, так как использование метода delay(time) останавливает исполнение остального кода.
unsigned long time1;
unsigned long time2;
//Создадим объекты класса Servo для сервоприводов камеры и манипулятора
Servo cam2;
Servo cam;
Servo man1;
Servo man2;
Servo man3;
Servo man4;
//Создадим переменные для хранения значений положения сервопроводов камеры и манипулятора
int posman1=20;
int posman2=90;
int posman3=90;
int posman4=90;
int poscam=100;
int poscam2=100;
//Опишем исходные параметры запуска
void setup()
{
//Создадим объект класса Serial для общения на скорости 9600 бод
Serial.begin(9600);
//Сконфигурируем отдельные ножки для управления двигателями на выход
pinMode(2,OUTPUT);
pinMode(3,OUTPUT);
pinMode(4,OUTPUT);
pinMode(5,OUTPUT);
//Опишем присоединение управления каждым сервоприводом на отдельную ножку
man1.attach(8);
man2.attach(9);
man3.attach(10);
man4.attach(7);
cam.attach(11);
cam2.attach(12);
//Установим управляющие сигналы в логическую единицу заранее, чтобы робот не двигался без входящей команды
digitalWrite(2,1);
digitalWrite(3,1);
digitalWrite(4,1);
digitalWrite(5,1);
}
//Начало исполняемого цикла
void loop()
{
//Установим сервоприводы манипулятора в экпериментально установленные положения.
man1.write(posman1);
man2.write(posman2);
man3.write(posman3);
man4.write(posman4);
//Установим сервоприводы камеры в экпериментально установленные положения.
cam.write(poscam);
cam2.write(poscam2);
//Для защиты от лишней нагрузки поставим условие, что код будет выполняться только если в порт пришла какая либо информация.
if(Serial.available())
{
//Создадим переменную, содержащую символ управления
int input=Serial.read();
//Если входящим символом является «w» в ASCII формате, то включим обоим моторам движение вперед
if(input==119)
{
//Запись в порт управляющего сигнала
digitalWrite(3,0);
digitalWrite(2,0);
//Запомним время прошедшее с момента включения микроконтроллера, это необходимо в дальнейшем, чтобы через определенный промежуток остановить действие.
time1=millis();
//Для тестирования выведем в порт надпись «вперед»
Serial.println("forward");
}
//Назад
if(input==115)
{
digitalWrite(5,0);
digitalWrite(4,0);
time1=millis();
Serial.println(" back");
}
//Для поворота робота моторы включаются разнонаправленно, что позволяет ему развернуться на любой угол на месте.
if(input==97)
{
digitalWrite(5,0);
digitalWrite(2,0);
time1=millis();
Serial.println(" left");
}
//Право
if(input==100)
{
digitalWrite(3,0);
digitalWrite(4,0);
time1=millis();
Serial.println("right");
}
//Для управления сервоприводами нужно передать им значение угла поворота
if(input==121)
{
//Поступление каждого управляющего символа изменяет угол поворота на 3 градуса, но максимальный угол поворота 180 градусов, поэтому предусмотрим условие ограничивающее его.
if(posman1<180)
{
posman1+=3;
}
man1.write(posman1);
Serial.println(" up ");
Serial.print(posman1);
}
if(input==104)
{
if(posman1>0)
{
posman1-=3;
}
man1.write(posman1);
Serial.println(" down ");
Serial.print(posman1);
}
if(input==117)
{
if(posman2<180)
{
posman2+=3;
}
man2.write(posman2);
Serial.println(" up ");
Serial.print(posman2);
}
if(input==106)
{
if(posman2>0)
{
posman2-=3;
}
man2.write(posman2);
Serial.println(" up ");
Serial.print(posman2);
}
if(input==105)
{
if(posman3<180)
{
posman3+=3;
}
man3.write(posman3);
Serial.println(" up ");
Serial.print(posman3);
}
if(input==107)
{
if(posman3>0)
{
posman3-=3;
}
man3.write(posman3);
Serial.println(" up ");
Serial.print(posman3);
}
if(input==111)
{
if(posman4<180)
{
posman4+=3;
}
man4.write(posman4);
Serial.println(" up ");
Serial.print(posman4);
}
if(input==108)
{
if(posman4>0)
{
posman4-=3;
}
man4.write(posman4);
Serial.println(" up ");
Serial.print(posman4);
}
//Управление сервоприводами камеры
//Камера вниз
if(input==114)
{
if(poscam>0)
{
poscam-=3;
}
cam.write(poscam);
Serial.println(" cam down ");
Serial.print(poscam);
}
//Камера вверх
if(input==102)
{
if(poscam<180)
{
poscam+=3;
}
cam.write(poscam);
Serial.println("cam up ");
Serial.print(poscam);
}
//Камера вправо
if(input==118)
{
if(poscam2>0)
{
poscam2-=3;
}
cam2.write(poscam2);
Serial.println(" cam right ");
Serial.print(poscam2);
}
//Камера влево
if(input==99)
{
if(poscam<180)
{
poscam2+=3;
}
cam2.write(poscam2);
Serial.println(" cam left ");
Serial.print(poscam2);
}
}
//Повторно возьмем время работы микроконтроллера
time2=millis();
//И если разница больше 100 миллисекунд, то остановим движение всех моторов.
if(time2-time1>100)
{
digitalWrite(2,1);
digitalWrite(3,1);
digitalWrite(4,1);
digitalWrite(5,1);
}
}
Интерфейс пользователя
Изначально хотелось написать свою полноценную дуплексную связь, но скилов не хватило, поэтому взял готовое решение(ТимВивер).Для связи с ардуино используем язык Processing(весьма красочный и удобный).

//Добавим стандартные библиотеки работы с видеоизображением и последовательным портом.
import processing.video.*;
import processing.serial.*;
//Создадим объект класса «Видеозахват»
Capture cam;
//Создадим объект класса «Последовательный порт»
Serial myPort;
//Создадим переменую хранящую последнюю нажатую клавишу
int whichKey = -1;
//Создадим переменную для хранения ответа микроконтроллера
int inByte = -1;
void setup() {
//Зададим размер окна приложения
size(640, 480);
//Для тестирования выведем список всех доступных портов
println(Serial.list());
//По умолчанию единственный доступный на обмен информацией порт стоновится первым, поэтому возьмем его название.
String portName = Serial.list()[0];
//Создадим объект класса последовательных портов.
myPort = new Serial(this, portName, 9600);
//Создадим объект класса захвата видеоизображения с заданным разрешением.
cam = new Capture(this, 640,480);
//Запустим захват видеоизображения
cam.start();
//Установим частоту смены изображения 30 кадров в секунду.
frameRate(30);
}
//Начнем отрисовку окна приложения
void draw() {
//Установим условие, что действие произойдет, если камера работоспособна
if (cam.available() == true) {
//Прочтем массив пикселей из камеры
cam.read();
}
//Если камера не отвечает выведем паническое сообщение.
else
{
fill(255,0,0);
text(“PANIC!!!! CAMERA DIE!!!”,320,240);
}
//Выведем кадр изображения с камеры в окно приложения
image(cam, 0, 0);
//Отобразим последнюю нажатую клавишу
fill(0);
//Так как символы управления приходят в цифровом формате, переведем полученное значение в символ.
text("Последнее нажатие " + char(whichKey), 10, 30);
//Для большей информативности и наглядности увеличим размер текста.
textSize(30);
//А так же раскрасим различные группы клавиш управления, придав эффект полупрозрачности.
fill(0,255,0,50);
//Круглые клавиши воспринимаются мягче, поэтому сделаем их таковыми
ellipse(30,430,50,50);
ellipse(80,430,50,50);
ellipse(130,430,50,50);
ellipse(80,380,50,50);
fill(0);
text('A',20,440);
text('S',70,440);
text('D',120,440);
text('W',70,390);
//Камера
fill(255,255,0,50);
ellipse(200,430,50,50);
ellipse(200,380,50,50);
ellipse(250,405,50,50);
ellipse(300,405,50,50);
fill(0);
text('R',190,390);
text('F',190,440);
text('C',240,415);
text('V',290,415);
//Манипулятор
fill(255,83,0,50);
ellipse(400,380,50,50);
ellipse(450,380,50,50);
ellipse(500,380,50,50);
ellipse(550,380,50,50);
ellipse(400,430,50,50);
ellipse(450,430,50,50);
ellipse(500,430,50,50);
ellipse(550,430,50,50);
fill(0);
text('Y',390,390);
text('U',440,390);
text('I',500,390);
text('O',540,390);
text('H',390,440);
text('J',440,440);
text('K',490,440);
text('L',540,440);
}
//Прочтем пришедшую с микроконтроллера информацию
void serialEvent(Serial myPort) {
//Поместим в переменную полученную информацию
inByte = myPort.read();
}
//Создадим стандартную функцию слежения за нажатием клавишь.
void keyPressed() {
//Запишем в последовательный порт символ управления, являющийся нажатой
клавишей.
myPort.write(key);
whichKey = key;
}
После всего вышеперечисленного ставим на нетбук ТимВивер или Радмин, запускаем наш код и понеслась) можно так же включить двустороннюю аудиосвязь в ТимВивере и пообщаться с роботом.
Ну и в конце сам диплом, вдруг кому пригодится.
Модер, я попутал ветку( прошу перенести в проекты.
А что за вуз. И сколько жена получила за диплом?
мгупи, оценка отлично, но это на фоне еще более слабых работ.
Спасибо. Это филиал какой или сама Москва?
А с какой целью интересуетесь?
Диплом какой-то слабый, откровенно говоря. Тока без обид, вы спросили я честно ответил.
Я закончил учиться в универе по специальности радиотехника 15 лет назад с мешком троек за спиной (потом, лет через 10 была еще была одна вышка - экономическая, где я понял что или экономисты дураки или уровень преподавания падает). Не представляю что сейчас в институах творится. Неужели все так плохо и мои догадки верны?
вы правы, все плохо(