Управление роботом-пылесосом iRobot Roomba с помощью Arduino


Как уже отмечалось в статье про разборку робота-пылесоса iRobot Roomba,
у данных роботов, выведен консольный разъём mini-DIN-7, через который можно управлять роботом.
консольный разъём mini-DIN-7, через который можно управлять роботом

Узнать его распиновку можно в документах iRobot® Roomba® Serial Command Interface (SCI) Specification
или
iRobot® Roomba® Open Interface (ROI) Specification.

Распиновка консольного разъёма iRobot Roomba
Распиновка консольного разъёма iRobot Roomba
Как видим, на разъём выведены 2 линии питания от батареи робота, две линии земли и
три информационных линии, работающие на TTL уровнях (5В):
Rx, Tx, DD.
Первые две линии — это линии приёмника и передатчика UART, которые можно просто
подключать к линиям передатчика и приёмника нашего контроллера или через
соответствующий преобразователь уровней (например, MAX232) к последовательному порту ПК, а линия DD используется чтобы «разбудить» робота или изменить скорость работы последовательного соединения.
Её можно подключить к любому цифровому пину контроллера или, через преобразователь MAX232, к линии RTS последовательного порта ПК.

Принципиальная схема переходника на базе популярной микросхемы преобразователя RS232-TTL — MAX232

Обратите внимание, что питание микросхемы преобразователя осуществляется от батареи робота, после преобразования его к 5В при помощи интегрального стабилизатора.

В простом варианте, можно обойтись без такого преобразователя и подключить контроллер Arduino прямо к консольному разъёму робота, обычными проводками.

Arduino Pin 0 (Rx)  ——> Roomba Pin 4 (Tx)
Arduino Pin 1 (Tx)  ——> Roomba Pin 3 (Rx)
Arduino Pin 2  ——> Roomba Pin 5 (Device Detect)
Arduino Gnd ——> Roomba GND Pin 6/7

Даже питание на контроллер Arduino можно взять от батареи робота, выведенной на этот разъём, главное, чтобы оно проходило через преобразователь питания контроллера:

Arduino Vin ——> Roomba +16V Pin 1/2

Однако, всё же намного удобнее собрать переходник.
Для этого просто возьмём протошилд, набор UART(TTL)->RS232 на микросхеме MAX232 и набор интегрального стабилизатора на базе MC7805.
У меня разъёма для mini-DIN-7 под рукой не оказалось, но от какой-то видеокарты нашёлся разъём под S-Video — mini-DIN 9-pin

— как видите, он вполне подходит, учитывая что два центральных пина просто зайдут в центральное углубление разъёма на роботе.

Остаётся только расковырять разъём и припаять к нему 5-жильный шлейф, а на другом конце шлейфа можно использовать BLS-гнездо с контактами 2.54мм. Т.о., остаётся на протошилде запаять гребёнку пинов PLS, в которую будет удобно подключаться наш шлейф от робота.
я сделал такую распиновку:

1. Vcc
2. Rx
3. Tx
4. DD
5. GND

Так же, я добавил дополнительные джамперы на схему, чтобы этот шилд можно было использовать не только для общения роботом и ПК, но и для общения между роботом и Arduino, или Arduino и ПК через последовательный порт:
при его подключении к контроллеру требуется нуль-модемное соединение: приёмник контроллера к передатчику робота, а при общении контроллера и ПК через преобразователь уровней — прямое.
А кроме того, добавил джампер, чтобы в варианте шилда, питать контроллер Arduino через стабилизатор шилда (т.е. 5V заводятся через джампер на соответствующий пин питания 5V).

Уровни RS-232 выведены на стандартный 9-пиновый разъём (как на компьютерных материнских платах), поэтому можно использовать стандартный переходник от компьютера

Однако, у таких переходников на выходе разъём типа DB-9M (Male — по-нашему — «папа»), а у переходников USB-COM разъём такой же, а значит, чтобы их соединить нужно использовать два разъёма DB-9F (Female — по-нашему — «мама»), напрямую соединённые между собой (я использовал удобнейший провод типа МГТФ).
Т.е. соединяем пины 2 (Tx), 3 (Rx), 5 (GND) и 7(RTS).
Обычно, достаточно всего 3 линии — Tx, Rx, GND. Линия RTS нужна только чтобы управлять линией DD (Device Detect) робота.

Вот что получилось:
Подключение к ПК

Подключение старой CraftDuino к роботу

С подключением разобрались. Осталось узнать как управлять роботом.
Нет ничего проще! В том же iRobot® Roomba® Open Interface (ROI) Specification приводится полное описание взаимодействия с роботом.
Управление идёт посылкой нужных команд.

Формат ROI (Roomba Open Interface):

[байт_кода_команды] <опциональные_байты_параметров>

Т.е., каждая команда задается одним байтом кода операции. Также, некоторые команды должны сопровождаться дополнительными байтами данных. Значение байтов данных оговаривается для каждой отдельной команды.
Roomba не будет отвечать на ROI-команды, когда она спит. Поэтому, робота сначала нужно «разбудить», установив на линии DD низкий уровень на 500 мс.

// будим робота
  digitalWrite(ddPin, HIGH);
  delay(100);
  digitalWrite(ddPin, LOW);
  delay(500);
  digitalWrite(ddPin, HIGH);
  delay(2000);

После пробуждения робота, на нём загорятся светодиодная подсветка кнопок и он будет готов принимать команды.
Первым делом, нужно послать команду Start.

Start
Код команды (Command opcode): 128
Число байт данных: 0
Запускает ROI.
Команда Старт, должна быть отправлена до любых других команд ROI.
Эта команда устанавливает ROI в пассивный режим (passive mode).
Пишем в порт: [128]
Код:

Serial.write(128);

Далее, так как мы хотим поуправлять нашим роботом-пылесосом, нужно заслать команду Control

Control
Код команды: 130
Число байт данных: 0
Позволяет пользователю управлять Roomba. Эта команда должна быть направлена
после команды Start и перед любой командой контроля ROI.
ROI должен быть в пассивном режиме, чтобы принять эту
команду.
Эта команда устанавливает ROI в пассивный режим (passive mode).
Пишем в порт: [130]
Код:

Serial.write(130);

Всё — можно рулить 🙂
Для упраления движением робота, используется команда Drive

Drive
Код команды: 137
Число байт данных: 4
Управляет колёсами Roomb-ы.
Принимает в качестве параметров 4 байта данных, которые интерпретируются, как два знаковых 16-битных значения.
Первые два байта задают среднюю скорость движения колеса в миллиметрах в секунду (mm/s).
Вторые два байта задают радиус в миллиметрах, на который Roomba должна повернуться.
Большой радиус позволяет роботу двигаться прямее, а маленький — поворачивать.
Положительная скороть и радиус приведут к движению прямо и влево.
При отрицательном радиусе, робот будет поворачивать вправо.
Особые случаи для поворота робота на месте или движении прямо:
Байты данных 1 и 2: Скорость (-500 – 500 mm/s)
Байты данных 3 и 4: Радиус (-2000 – 2000 mm)

Специальный случай: Прямо = 32768 = hex 8000
Повернуть на месте направо (clockwise) = -1
Повернуть на месте налево (counter-clockwise) = 1

Эта команда изменяет режим работы робота.
Пишем в порт: [137] [Velocity high byte][Velocity low byte] [Radius high byte][Radius low byte]

Пример:
Чтобы двигаться назад со скоростью -200 mm/s и поворачивать с радиусом 500mm,
следую отправить в порт следующую последовательность байт:
[137] [255] [56] [1] [244].
Скорость = -200 = hex FF38 = [hex FF] [hex 38] = [255] [56]
Радиус = 500 = hex 01F4 = [hex 01] [hex F4] = [1] [244]
Код:

  Serial.write(137);
  Serial.write(0xFF);
  Serial.write(0x38);
  Serial.write(0x01);
  Serial.write(0xF4);

Остаётся запрограммировать наш контроллер для выдачи подобных команд.
Возьмём готовый пример скетча для книги Hacking Roomba — RoombaBumpTurn.pde
и подредактируем его, чтобы робот двигался 2 секунды двигался прямо, а затем одну секунду поворачивал направо.
Так как, код скетча предназначен для версии Arduino IDE < 1.0, то его придётся подправить. Например, в коде используется

Serial.print(137, BYTE);

,которого больше нет в Arduino IDE > 1.0.
Эти методы нужно просто заменить на

Serial.write(137)

RoombaBumpTurn-my.ino

/*
 * RoombaBumpTurn
 * --------------
 * Implement the RoombaComm BumpTurn program in Arduino
 * A simple algorithm that allows the Roomba to drive around
 * and avoid obstacles.
 *
 * Arduino pin 0 (RX) is connected to Roomba TXD
 * Arduino pin 1 (TX) is connected to Roomba RXD
 * Arduino pin 2      is conencted to Roomba DD
 *
 * Updated 20 November 2006
 * - changed Serial.prints() to use single print(v,BYTE) calls instead of
 *    character arrays until Arduino settles on a style of raw byte arrays
 *
 * Created 1 August 2006
 * copyleft 2006 Tod E. Kurt 
 * http://hackingroomba.com/
 */

int rxPin = 0;
int txPin = 1;
int ddPin = 2;
int ledPin = 13;
char sensorbytes[10];

#define bumpright (sensorbytes[0] & 0x01)
#define bumpleft  (sensorbytes[0] & 0x02)

void setup() {
//  pinMode(txPin,  OUTPUT);
  pinMode(ddPin,  OUTPUT);   // sets the pins as output
  pinMode(ledPin, OUTPUT);   // sets the pins as output
  Serial.begin(57600);

  digitalWrite(ledPin, HIGH); // say we're alive

  // wake up the robot
  digitalWrite(ddPin, HIGH);
  delay(100);
  digitalWrite(ddPin, LOW);
  delay(500);
  digitalWrite(ddPin, HIGH);
  delay(2000);
  // set up ROI to receive commands
  Serial.write(128);  // START
  delay(50);
  Serial.write(130);  // CONTROL
  delay(50);
  digitalWrite(ledPin, LOW);  // say we've finished setup
}

void loop() {
  digitalWrite(ledPin, HIGH); // say we're starting loop
  updateSensors();
  digitalWrite(ledPin, LOW);  // say we're after updateSensors
#if 0
  if(bumpleft) {
    spinRight();
    delay(1000);
  }
  else if(bumpright) {
    spinLeft();
    delay(1000);
  }
#endif
  goForward();
#if 1
  delay(2000);
  spinRight();
  delay(1000);
#endif
}

void goForward() {
  Serial.write(137);   // DRIVE
  Serial.write((byte)0x00);   // 0x00c8 == 200
  Serial.write(0xc8);
  Serial.write(0x80);
  Serial.write((byte)0x00);
}
void goBackward() {
  Serial.write(137);   // DRIVE
  Serial.write(0xff);   // 0xff38 == -200
  Serial.write(0x38);
  Serial.write(0x80);
  Serial.write((byte)0x00);
}
void spinLeft() {
  Serial.write(137);   // DRIVE
  Serial.write((byte)0x00);   // 0x00c8 == 200
  Serial.write(0xc8);
  Serial.write((byte)0x00);
  Serial.write(0x01);   // 0x0001 == spin left
}
void spinRight() {
  Serial.write(137);   // DRIVE
  Serial.write((byte)0x00);   // 0x00c8 == 200
  Serial.write(0xc8);
  Serial.write(0xff);
  Serial.write(0xff);   // 0xffff == -1 == spin right
}
void updateSensors() {
  Serial.write(142);
  Serial.write(1);  // sensor packet 1, 10 bytes
  delay(100); // wait for sensors
  char i = 0;
  while(Serial.available()) {
    int c = Serial.read();
    if( c==-1 ) {
      for( int i=0; i<5; i ++ ) {   // say we had an error via the LED
        digitalWrite(ledPin, HIGH);
        delay(50);
        digitalWrite(ledPin, LOW);
        delay(50);
      }
    }
    sensorbytes[i++] = c;
  }
} 

Вот что у меня получилось:

Чтобы остановить робота - его нужно приподнять от пола 😉

Красота! Что теперь можно с ним сделать? Да что угодно! Теперь роботу можно добавить "интеллекта" и управлять им с обычного ПК или какого-нибудь одноплатника типа BeagleBoard или Raspberry Pi. Превратить его в TurtleBot-а или что-нибудь другое. А можно использовать Bluetooth-модуль или Wi-Fi роутер под OpenWRT и управлять роботом дистанционно. Масса идей и простор для фантазии!

а у Вас какие есть идеи? 🙂

PS. Уважаемый mishmash несколько опередил меня и выложил свои заметки по управлению Roomb-ой, так что с одной стороны эта статья выступает в роли дублирования материала и я уже не хотел её публиковать, но с другой стороны тема настолько интересная и захватывающая, что, думаю, оно того стоит.
Как звучит: "хакинг бытовых роботов при помощи Arduino"!
Помните в старом "Судья Дредд" бывший преступник "взламывал" роботов? Да... будущее уже наступило 😉

продолжение следует...

Ссылки
Build a Roomba Serial Tether
Add scheduling to Roomba 532 via Arduino
http://en.wikipedia.org/wiki/Mini-DIN_connector
http://ru.wikipedia.org/wiki/S-Video
iRobot® Roomba® Serial Command Interface (SCI) Specification

По теме
Turtlebot - первые шаги
Новогоднее исследование ADSL-роутера на базе Linux - 0x6 - последовательный порт

Автор: Vladimir (noonv), 2011-2012

Эксклюзивно для robocraft.ru
копирование на другие ресурсы и публикация
без разрешения автора запрещены.


0 комментариев на «“Управление роботом-пылесосом iRobot Roomba с помощью Arduino”»

  1. Нужно сделать веб-интерфейс управления роботом + веб-камеру, и за 5 рублей продавать доступ — убери мою комнату и заплати за это деньги! :)))

    • :)))
      Если серьёзно, мы думали об этом, только без уборки. Это, по сути, робот телеприсутсвтия. Его уже сейчас можно реализовать при помощи ROS через ssh. В ближайшем будущем, думаю, сделаем нечто подобное.

  2. Доброго дня суток! А кто подскажет, возможно ли управление более старой моделью румбы, у меня roomba floor vac и консольного разъема на ней нет (( но на мамке есть свободный 4 х контактный разъем, только хз как подключить ((

  3. Это все здорово, Но все мимо кассы.
    По сути вопроса: для roomba единственное что надо сделать — это изменить алгоритм уборки. Смотрю как он хаотично носиться и тыкается по углам и думаю что с разработчиками что то явно не так. Для построения виртуальной карты помещения даже зрения не надо. Сначала построить периметр а потом пылесосить внутри этого периметра постепенно сдвигаясь к центру помещения. Препятствия тоже можно на этой карте перемещениями вычислить. И неплохо бы было хранить эту карту в памяти пылесоса.

    • 1.лет 6 назад было видео и тестирование, где показали что такой рандомный метод чистки лучше, но возможно все подстроили что бы оправдаться.
      2.энкодеры накапливают ошибку, стукаться об стены что бы найти ее еще больше копит ошибку, + одно колесо может проехать по чему то не ровному и тп. мой маленький опыт показал что энкодеров мало(
      3. хранить карту нет смысла, т.к. в следующий раз пылесос может начать не со своего прежнего места, или обтановка в комнате может изменится.
      ps мой румба работает после нескольких разборок\сборок уже больше 5 лет(с перерывами), один раз только аккум с али заказывал. и текущим алгоритмом доволен

Добавить комментарий

Arduino

Что такое Arduino?
Зачем мне Arduino?
Начало работы с Arduino
Для начинающих ардуинщиков
Радиодетали (точка входа для начинающих ардуинщиков)
Первые шаги с Arduino

Разделы

  1. Преимуществ нет, за исключением читабельности: тип bool обычно имеет размер 1 байт, как и uint8_t. Думаю, компилятор в обоих случаях…

  2. Добрый день! Я недавно начал изучать программирование под STM32 и ваши уроки просто бесценны! Хотел узнать зачем использовать переменную типа…

3D-печать AI Android Arduino Bluetooth CraftDuino DIY IDE iRobot Kinect LEGO OpenCV Open Source Python Raspberry Pi RoboCraft ROS swarm ИК автоматизация андроид балансировать бионика версия видео военный датчик дрон интерфейс камера кибервесна конкурс манипулятор машинное обучение наше нейронная сеть подводный пылесос работа распознавание робот робототехника светодиод сервомашинка собака управление ходить шаг за шагом шаговый двигатель шилд

OpenCV
Робототехника
Будущее за бионическими роботами?
Нейронная сеть - введение