Сегодня мы решили начать новый проект: сборка и изучение 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* 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: здесь также можно почитать о том, как запрограммировать Румбу при помощи Ардуино
0 комментариев на «“Turtlebot — первые шаги”»
Спасибо, отличная работа!румбой 🙂
прямо таки опередили меня 🙂 всё никак руки не доходили выложить свою заметку про работу с
Спасибо! Сейчас копаемся с ROS. При получении результатов, выложим новую статью 🙂
здорово, желаю успехов! 🙂тут уже много насобирал. если будут вопросы — обращайтесь 😉
по ROS, я