Просте віддалене управління з комп'ютера роботом

    
Передмова або навіщо перекручуватися?
Здрастуй, Хабрахабр! Я сидів ввечері 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 <SPI.h>
# Include <Mirf.h>
# Include <MirfHardwareSpiDriver.h>
# Include <MirfSpiDriver.h>
# Include <nRF24L01.h>
 
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 <SPI.h>
# Include <Mirf.h>
# Include <MirfHardwareSpiDriver.h>
# Include <MirfSpiDriver.h>
# Include <nRF24L01.h>
 
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);
}
 
 
 
Висновок.
 
Що з цього всього вийшло:
 www.youtube.com/watch?v=K5ekFyph82U
 
Цього робота я зробив для «Клаустрофобії» . Вони проводять квести в реальності в різних містах, і якраз для одного з таких квестів організаторам знадобився радіокерований робот-сапер. Мені сподобалося. Це, звичайно, неповноцінне, т.к. на тлі управління за допомогою вбудованих в ноутбук засобів зв'язку, але зате своє, зроблене вельми швидко і без особливих проблем. Сподіваюся ця стаття допоможе зробити щось подібне, а, може, навіть складніше. Тут вже кому що заманеться.
 
 <habracut/>
    
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.