iRobot create2 (Arduino-Roomba)

が投稿

create 2を動かす方法とエンコーダーの値を取得する方法についてまとめる.

2017年度のアルバイト学生さんがまとめてくれた内容です。間違い等があるかも知れません。お気づきの点がございましたら、ご連絡下さい。

 

ルンバのマニュアル

http://www.irobotweb.com/-/media/MainSite/PDFs/About/STEM/Create/iRobot_Roomba_600_Open_Interface_Spec.pdf?la=en

このマニュアルを元にして説明していく.最新版のマニュアルがあるか確認すること.

システム構成

今回作成したシステムはこのようになっている.

 

基本的な仕組みとしては,arduinoが特定のデータをシリアル通信でルンバに送信,その後ルンバが特定の行動をする(動いたり,センサー値を返したり)

 

起動させる

ルンバを起動する.真ん中のCLEANボタンを押せば起動する.この時ボタンの色がオレンジだったらバッテリーが少ない,赤色だったらバッテリーが無い.

ルンバには3つのモードがある.マニュアル7pにあるようにpassive,safe,full modeがある.簡単に説明すると次のようになる.

  •  passive mode
    •  モーターを制御できないがセンサーの値は見ることができる. 基本となるモード
  • safe mode
    • 今回このモードでルンバを制御する. センサー値が見れてモーターも制御できる.しかしsafeとあるように,ある程度の安全装置が働く.
  • full mode
    • safe modeの安全装置を無くしたもの

充電させる

マニュアル7pをよく読むと,

Note that charging terminates when you enter Safe Mode, and Roomba will not power save.

Note that charging terminates when you enter Full Mode, and Roomba will not power save.

とある.つまりルンバがsafe mode とfull modeのときは,充電ドッグにおいても充電されない.充電させるには,passive modeに変更する必要がある.マニュアルp4, power savingにも同様の記述がある.

一番簡単にsafe mode からpassive modeに変更するには,ルンバを持ち上げれば良い.安全装置が働いてpassive modeになる.

 

arduinoとルンバの接続

参考[1]:

https://www.irobotweb.com/-/media/MainSite/PDFs/About/STEM/Create/Arduino_Tutorial.pdf?la=en

これを参考にしてarduinoとルンバのシリアルポートをつなぐ.

arduinoとルンバはソフトウェアシリアルで通信する.

参考[2]:http://www.musashinodenpa.com/arduino/ref/index.php?f=1&pos=92

シリアルポートにはVpwrがあるが,unregulatedとなっている(マニュアルp3).ルンバのバッテリー状態によって電圧が変動する.24 ~ 4 vぐらい変わったはず…  ルンバからの供給電圧には注意する必要がある.

ルンバのデフォルトのボーレートは115200である(マニュアル4p).

参考[1]に書いてあるように

iRobot Create 2 uses 115200 baud serial, by default. Unfortunately, any Arduino using an ATmega core cannot reliably reproduce 115200 baud. At 16 MHz, the best that an ATmega USART can do is either -3.5% or +2.1% error, which is not within spec (and it’s even worse at 8MHz). Therefore, we recommend the use of a lower baud rate, like 19200 baud.

したがってボーレートを変更させる必要がある.

 


#include ;

int rxPin = 10;
int txPin = 11;

SoftwareSerial Roomba(rxPin, txPin);

void setup() {
   Roomba.begin(115200);
}

となる.

ボーレートを変更

 


void wakeUp(void){ //起動
digitalWrite(ddPin, HIGH);
delay(100);
digitalWrite(ddPin, LOW);
delay(500);
digitalWrite(ddPin, HIGH);
delay(2000);
}

void setup() {
   Roomba.begin(115200);
   wakeUp(); //wake up Roomba
}

 

マニュアルp4, method2に書いてある通り,ボーレートを19200するためであるがうまく行かない…

しょうがないから,マニュアルp9を使ってボーレートを変える.


Roomba.begin(115200);

Roomba.write(byte(129));//change baud rate
Roomba.write(5);//9600に変更

Roomba.end();//一度きる
Roomba.begin(9600);//19200でスタート
Serial.println("roomba 9600 start");

safe modeに変更する


void startSafe(){ //startmodeに移行
Roomba.write(128); //start
Roomba.write(131); //safe mode
delay(100);//とりあえず入れる
//Serial.println("startsafe");
}

void setup() {
   Roomba.begin(115200);
   wakeUp(); //wake up Roomba
   startSafe(); // start roomba in safe mode
}

モーターを制御したいので,safe modeにする.”128″でルンバを(起動していなければ)起動してpassive modeに移る.”131″でpassive mode から safe modeに変更させる.(マニュアルp8,10)

 

passive modeに変更させる


void startPassive(){ //passivemodeに移行
Roomba.write(128); //start
delay(100);
//Serial.println("startPassive");
}

“128”を送信するだけで十分(マニュアルp8)

モーターを制御する

マニュアルp13,14に書いてある.


unsigned int hex_convert_to8_high(int a){
return (unsigned int)(a >> 8)&0x00FF;
};

unsigned int hex_convert_to8_low(int a){
return a^(hex_convert_to8_high(a) << 8);
};

unsigned int hex_convert_to16(int a, int b){
return (unsigned int)(a << 8)|(int)(b);
};

速度は2byteに分けて送らないといけない.hex_convert_to8_high()とhex_convert_to8_low()を用意して16bitを8bitずつ1byteに分けてる.hex_convert_to16()では1byte2つを2byteにする.


void roomba_send_num(int num){ //numを二つの8bitに変換してルンバに送信
   Roomba.write(hex_convert_to8_high(num));
   Roomba.write(hex_convert_to8_low(num));
};

めんどくさいのでこのような関数を用意した.


void roomba_drive_turn_counterclockwise(int num){ //反時計回り 引数は速さ
   Roomba.write(137);
   roomba_send_num(num); //Velocity 100mm/s
   roomba_send_num(1); //Radius 1
   //Serial.println("反時計回り");
   delay(100);
};

void roomba_drive_turn_clockwise(int num){ //時計回り 引数は速さ
   Roomba.write(137);
   roomba_send_num(num); //Velocity
   roomba_send_num(-1); //Radius
   //Serial.println("時計回り");
   delay(100);
};

void roomba_drive(int right, int left){ //直進
   Roomba.write(145);
   roomba_send_num(right); //Velocity right
   roomba_send_num(left); //Velocity left
   //Serial.println("直進");
   //delay(100);
   delay(10);
};
void roomba_drive_pwm(int right,int left){ //pwm -255 ~ 255
   Roomba.write(146);
   roomba_send_num(right); //pwm right
   roomba_send_num(left); //pwm left
   //Serial.println("pwm");
   delay(100);
};

void roomba_moter_stop(){ //モーターを止める
   Roomba.write(137);
   roomba_send_num(0); //Velocity 0mm/s
   roomba_send_num(0); //Radius 0 速度が0なのでなんでも良い
   //Serial.println("モーターを止める");
   delay(100);
};

マニュアルのように
[コード][Right velocity high byte] [Right velocity low byte] [Left velocity high byte] [Left velocity low byte]

となる.ちなみにルンバの最小速度は11mm/sである.

エンコーダーの読み取り

マニュアルp30,31に書いてある.ルンバからは1byte×2返ってくる.

左側のタイヤのエンコーダーの値をリクエストするには”142″ “43”を送信すれば良い.右側の場合は43を44にすれば良い

//left encoder をリクエスト
Roomba.write(byte(142));
Roomba.write(43); //left 43 right 44

//encoderの値を受信
enco_left_h = Roomba.read();//high
high enco_left_l = Roomba.read();//low
enco_left = hex_convert_to16(enco_left_h,enco_left_l);

 

ボーレートが高いと,データにノイズが入ってしまい,エンコーダーの値が正しく読み取れない.したがって9600のように低くする必要がある.

 

firmwareについて

firmware のバージョンによってバグあるらしいが(マニュアルp41),firmwareをバージョンアップする方法は調べた限りなさそう…

https://answers.ros.org/question/262720/how-to-upgrade-irobot-create_2-firmware-to-326/

ネジについて

マニュアルp6にネジについて書いてある.ルンバにはネジ穴があるがそれらは独自ネジである.しかしM3を無理やり入れれば入る.

参考資料

[1]http://www.instructables.com/id/Controlling-a-Roomba-Robot-With-Arduino-and-Androi/