iRobot create2 (Arduino-Roomba)

が投稿

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

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

ルンバのマニュアル

システム構成

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

  • 基本的な仕組みとしては,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]:

  • これを参考にして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 <SoftwareSerial.h>
int rxPin = 10;//rxのピン番号
int txPin = 11;//txのピン番号
int ddPin = 5; //参考[1]のBRC
SoftwareSerial Roomba(rxPin, txPin);
void setup() {
    Roomba.begin(115200);//とりあえずは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); 
}
  • 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);
};


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

# エンコーダーの読み取り

- マニュアルp30,31に書いてある.ルンバからは1byte×2返ってくる. 
- 左側のタイヤのエンコーダーの値をリクエストするには142 43を送信すれば良い.右側の場合は43を44にすれば良い

```c
//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について

ネジについて

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

参考資料

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