...

суббота, 12 июля 2014 г.

Простое удалённое управление с компьютера роботом

Предисловие или зачем извращаться?



Здравствуй, Хабрахабр! Я сидел вечером 11 июня, смотрел фильм. Неожиданно для себя я обнаружил, что мне написала незнакомая мне ранее женщина с предложением сделать робота для их нового квеста. Суть заключается в том, что нужно разгадывать головоломки, исследовать тайники, правильно применять подсказки, использовать доступные вещи и в итоге добывать ключи и открывать двери… От меня требовалось сделать робота, управляемого с компьютера с помощью отдельной программы. У мебя были сомнения по поводу 2 вещей: успею ли я и как именно сделать беспроводную передачу данных (беспроводной передачей данных я занимался до этого только на NXT)? Взвесив все за и против я согласился. После этого я стал думать над передачей данных. Поскольку требовалось сделать робота быстро, то вспоминать и доосваевать, например, дельфи не было времени, поэтому возникла идея сделать модуль который будет заниматься отправкой команд. От компьютера требуется просто посылать данные в СОМ-порт. Этот способ странный, но наиболее быстрый. Его я и хочу описать здесь. Так же я приложу 3 программы которые помогут сделать радиоуправляемую машинку.
Сборка передатчика и его программа.



Я сделал модуль для компьютера из FTDI Basic Breakout 5/3.3V от DFrobot, довольно распространённого микроконтролера ATMEGA 328P-PU с загрузчиком Arduino и радиомодуля на основе микросхемы nRF24L01. По-сути это просто Arduino Uno с радиомодулем. Что есть, то есть. У радиомодуля есть особенность, которую я не сразу заметил: входное напряжение должно быть в диапазоне от 3 до 3.6 вольт (хотя подача на него 5 вольт его не убьёт, но работать не будет), верхняя граница логической единицы составляет 5В. Это означает то, что для подключения радиомодуля к меге не нужен преобразователь уровней между 3.3В и 5В, а вот стабилизатор на 3.3В установить нужно. У FTDI есть встроенный стабилизатор, от него я и подпитал радиомодуль.

Так выглядит сам модуль (внутри и в сборке) :


Программа состоит из инициализации, стартового сообщения и обработки команд из программы управления. Так было в моём случае. Основные команды библиотеки Mirf:


#include <SPI.h>

#include <Mirf.h>

#include <MirfHardwareSpiDriver.h>

#include <MirfSpiDriver.h>

#include <nRF24L01.h>

Эти библиотеки нужны для работы радиомодуля


Mirf.csnPin = 4 — задаёт номер пина, отвечающего за «разрешение общаться» радиомодуля и МК

Mirf.cePin = 6 — задаёт номер пина, отвечающего за режим работы радиомодуля (приёмник/передатчик)

Mirf.spi = &MirfHardwareSpi — настраивает линию SPI

Mirf.init() — инициализирует радиомодуль

Mirf.payload = 1 — размер в байтах одного сообщения (поумолчанию 16, максимум 32)

Mirf.channel = 19 — задаёт канал (0 — 127, по умолчанию 0)

Mirf.config() — задаёт параметры передачи


Mirf.setTADDR((byte *)«serv1») — переводит радиомодуль в режим передатчика

Mirf.setRADDR((byte *)«serv1») — переводит радиомодуль в режим приёмника


Mirf.send(data) — отправляет массив типа byte

Mirf.dataReady() — сообщает об окончании обработки принятых данных

Mirf.getData(data) — записать принятые данные в массив data


Mirf.setTADDR((byte *)«serv1») — переводит радиомодуль в режим передатчика

Mirf.setRADDR((byte *)«serv1») — переводит радиомодуль в режим приёмника


Mirf.send(data) — отправляет массив типа byte

Mirf.dataReady() — сообщает об окончании обработки принятых данных

Mirf.getData(data) — записать принятые данные в массив data


Прилагаю код программы передатчика.


Программа передатчика
#include

#include

#include

#include

#include

char active;

byte data[1];


void setup()

{

Serial.begin(19200);


Mirf.csnPin = 4;

Mirf.cePin = 6;

Mirf.spi = &MirfHardwareSpi;

Mirf.init();

Mirf.payload = 1;

Mirf.channel = 19;

Mirf.config();


Mirf.setTADDR((byte *)«serv1»);


//сигнальное сообщение о начале работы

data[0]=7;

Mirf.send(data);

delay(200);

}


void loop()

{

if (Serial.available()) //Если данные готовы к считыванию

{

active=Serial.read(); // Запись данных в переменную

}


if (active=='2')

{

data[0]=2;

}


if (active=='3')

{

data[0]=3;

}


if (active=='4')

{

data[0]=4;

}


if (active=='5')

{

data[0]=5;

}


if (active=='6')

{

data[0]=6;

}


Mirf.send(data); //Отсылаем данные

while(Mirf.isSending()); // Ждём пока данные отсылаются

}




Программа управления.

Есть одна интересная штука — Processing. Синтаксис такой же как в Arduino, только вместо void loop() там расположился void draw(). Но она становилась ещё более интересной в моей ситуации с библиотекой processing Serial, которая позволяет работать с сериал-портом. Прочитав уроки на сайте Spurkfun`а, я поигрался с миганием светодиода на подключенной к компьютеру ардуинке по клику мышки. После этого я написал программу управления роботом с клавиатуры. Прилагаю код управления с помощью стрелок. В нём, в принципе, ничего необычного нет.


Программа управления машинкой
import processing.serial.*;

import cc.arduino.*;

Serial myPort;

PFont f=createFont(«LetterGothicStd-32.vlw», 24);


void setup()

{

size(360, 160);

stroke(255);

background(0);

textFont(f);


noCursor();


String portName = «XXXX»; // Сюда нужно написать имя вашего порта

myPort = new Serial(this, portName, 19200);

}


void draw() {

if (keyPressed == false)

{

clear();

myPort.write('6');

println(«6»);

}

}


void keyPressed()

{

// 10 — enter

// 32 — probel

// 37/38/39/40 — keys

clear();


fill(255);

textAlign(CENTER);

//text(keyCode, 180, 80);


switch(keyCode)

{

case 37:

text(«Edem vlevo», 180, 80);

myPort.write('1');

break;


case 38:

text(«Edem pryamo», 180, 80);

myPort.write('2');

break;


case 39:

text(«Edem vpravo», 180, 80);

myPort.write('3');

break;


case 40:

text(«Edem nazad», 180, 80);

myPort.write('4');

break;


default:

text(«Takoy kommandi net», 180, 80);

myPort.write('6');

break;

}

}




Программа приёмника.

Инициализация этой программы отличается от инициализации программы передатчика буквально одной строчкой. Ключевая команда в бесконечном цикле Mirf.getData(data). Дальше полученная команда сравнивается с числами, которым соответствуют какие-либо действия робота. Ну а дальше робот действует точно по командам. Прилагаю код программы приёмника машинки.


Программ машинки
#include

#include

#include

#include

#include

void setup()

{

Serial.begin(9600);


pinMode(13, OUTPUT); //LED


Mirf.csnPin = 10;

Mirf.cePin = 9;

Mirf.spi = &MirfHardwareSpi;

Mirf.init();

Mirf.payload = 1;

Mirf.channel = 19;

Mirf.config();

Mirf.setRADDR((byte *)«serv1»);

}


void loop()

{

byte data[1];


if(!Mirf.isSending() && Mirf.dataReady())

{

Mirf.getData(data);

Serial.println(data[0]);

}


switch (data[0])

{

case 1:

motors(-100, 100); // поворачиваем влево

break;


case 2:

motors(100, 100); // едем прямо

break;


case 3:

motors(100, -100); // поворачиваем вправо

break;


case 4:

motors(-100, -100); // едем назад

break;


default:

motors(0, 0); // стоим

break;

}


delay(50);

}




Заключение.

Что из этого всего вышло:

http://ift.tt/1y8dFoK


Этого робота я сделал для «Клаустрофобии». Они проводят квесты в реальности в разных городах, и как раз для одного из таких квестов организаторам понадобился радиоуправляемый робот-сапер. Мне понравилось. Это, конечно, ущербно, т.к. на фоне управления с помощью встроенных в ноутбук средств связи, но зато своё, сделанное весьма быстро и без особых проблем. Надеюсь эта статья поможет сделать нечто подобное, а, может, даже сложнее. Тут уж кому что захочется.


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Комментариев нет:

Отправить комментарий