Сегодня мы решили начать новый проект: сборка и изучение Turtlebot.
Это устройство превосходно подходит для исследовательских задач в области робототехники, таких как SLAM, одометрия, PID-регулятор и т. п. Однако, как известно, IRobot Create, специально изготовленный для таких задач, в России достать невозможно. Поэтому приходится обходиться роботом-пылесосом — IRobot Roomba. Благо, для того, чтобы сделать из Roomba настоящий Turtlebot, потрудилось немало людей. Например, есть специальный стек под ROS для Roomba.
Однако, начнем мы не с ROS стека, а с прямого управления румбой с Arduino. Здесь подробно описано, как это сделать
Мы сделали подходящий кабель (про то, как его сделать, можно вычитать либо в SCI Roomba, либо здесь) для общения с румбой. Чтобы сделать такой провод, купите в магазине обычный Мin-Din кабель с 7-ю пинами и обрежьте один из его концов, а затем подключите их в Arduino так, как написано ниже.
У порта румбы 7 контактов — по два на питание и землю, обнаружение устройства (Device Detect — DD), RX и TX (см. на рисунке ниже). DD мы воткнули во 2й цифровой выход Ардуино, Rx и Tx — в первый и нулевой.
Однако позже, после обнаружения ошибки в считывании сенсоров, мы воткнули их в 10 и 11 пины (см. ниже). Питание подсоединили с питанием Arduino, а землю, соответственно, с землёй. Другой конец кабеля нужно подключить к соответствующему разъёму на Roomba (он находится под крышкой).
Однако, мы столкнулись с некоторыми проблемами:
Код, который приведён здесь предназначен для старой версии Arduino. Он использует такую встроенную переменную как BYTE, которой больше нет в Arduino. Для того чтобы передавать по Serial байты, необходимо использовать команду Serial.write() вместо Serial.print(). При этом, когда мы пишем Serial.write(0), возникает странная ошибка: компилятор не знает в качестве переменной какого типа выступает ноль. Для исправления этой ошибки просто прикастуйте 0 к переменной типа byte: Serial.write((byte)0);. После этого у нас заработали актуаторы. Румба стала передвигаться, куда мы ей скажем.
Однако сенсоры (бампер) так и не заработали. Стали вылавливать проблему дебагом. Поэтому пришлось перенести Rx и Tx для общения с Roomba на другие пины (10 и 11) при помощи библиотеки SoftwareSerial, чтобы по стандартным serial-пинам передавать информацию на Serial Monitor. Но, к моему удивлению, дебажить даже не пришлось, потому что это и оказалось решением проблемы.
Пришлось также немного повозиться со скоростью передачи данных (baud rate). По умолчанию Roomba общается на скорости 57600. Однако она настраивается на скорость 19200. Наша румба была на скорости 19200.
Вот итоговый код, который работает на нашей Roomba:
#include <SoftwareSerial.h>
/*
* RoombaBumpTurn
* --------------
* Implement the RoombaComm BumpTurn program in Arduino
* A simple algorithm that allows the Roomba to drive around
* and avoid obstacles.
*
* Arduino pin 10 (RX) is connected to Roomba TXD
* Arduino pin 11 (TX) is connected to Roomba RXD
* Arduino pin 2 is conencted to Roomba DD
*
* Updated 20 November 2006
* - changed mySerial.writes() to use single write((int)v) calls instead of
* character arrays until Arduino settles on a style of raw byte arrays
*
* Created 1 August 2006
* copyleft 2006 Tod E. Kurt <tod@todbot.com>
* http://hackingroomba.com/
*/
int ddPin = 2;
int ledPin = 13;
char sensorbytes[10];
SoftwareSerial mySerial(10,11);
#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
mySerial.begin(19200);
Serial.begin(9600);
/*
// [re]set baud rate to 57600
mySerial.write((int)129); // BAUD
mySerial.write((int)10); // 57600
delay(100);
*/
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
mySerial.write((int)128); // START
delay(50);
mySerial.write((int)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(bumpleft) {
spinRight();
delay(1000);
}
else if(bumpright) {
spinLeft();
delay(1000);
}
goForward();
}
void stopRoomba() {
mySerial.write((int)137); // DRIVE
mySerial.write((byte)0); // 0x0000== 0
mySerial.write((byte)0);
mySerial.write((byte)0);
mySerial.write((byte)0);
}
void goForward() {
mySerial.write((int)137); // DRIVE
mySerial.write((byte)0); // 0x00c8 == 200
mySerial.write((int)200);
mySerial.write((int)128);
mySerial.write((byte)0);
}
void goBackward() {
mySerial.write((int)137); // DRIVE
mySerial.write((int)255); // 0xff38 == -200
mySerial.write((int)56);
mySerial.write((int)128);
mySerial.write((byte)0);
}
void spinLeft() {
mySerial.write((int)137); // DRIVE
mySerial.write((byte)0); // 0x00c8 == 200
mySerial.write((int)200);
mySerial.write((byte)0);
mySerial.write((int)1); // 0x0001 == spin left
}
void spinRight() {
mySerial.write((int)137); // DRIVE
mySerial.write((byte)0); // 0x00c8 == 200
mySerial.write((int)200);
mySerial.write((int)255);
mySerial.write((int)255); // 0xffff == -1 == spin right
}
void updateSensors() {
mySerial.write((int)142);
mySerial.write((int)1); // sensor packet 1, 10 bytes
delay(100);
// wipe old sensor data
char i = 0;
while (i < 10) {
sensorbytes[i++] = 0;
}
i = 0;
while(mySerial.available()) {
//xbmySerial.writeln("rsd"); // reading sensor data
int c = mySerial.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;
}
}
В итоге, наша Roomba едет вперёд, пока не наткнётся на препятствие. После столкновения она оценивает, с какой стороны препятствие: если слева, поворачивает вправо; если справа, идет налево.
UPD:здесь также можно почитать о том, как запрограммировать Румбу при помощи Ардуино
Комментарии (3)
RSS свернуть / развернутьпрямо таки опередили меня :) всё никак руки не доходили выложить свою заметку про работу с
noonv
mishmash
по ROS, я
noonv
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.