41
32

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ルンバをM5 Atomでお手軽ハックしてラジコン化する

Last updated at Posted at 2021-03-07

ルンバのシリアルインタフェースにM5 Atom liteを接続してハックします

Atom liteを使用しますがUARTが使えるマイコンなら何でも大丈夫だと思います

色々な事ができるのですがまずルンバをラジコン化してみました

##使用するデバイス##

ATOM Lite - スイッチサイエンス
https://www.switch-science.com/catalog/6262/

image.png
M5Stackシリーズの中で最もコンパクトな開発モジュールで、サイズはわずか24 x 24 mmです。M5StickCに比べGPIOピンを多く持ち、小型の組み込みデバイス開発に適しています。メインコントローラとして、ESP32-PICO-D4チップを搭載しているので、Wi-FiとBluetooth、4 MBの内蔵SPIフラッシュメモリを利用できます。(スイッチサイエンスさんから引用)

M5シリーズの中で一番小さくて手軽なAtom liteを使用しました
Atom liteで出来るなら他のマイコンでも使えるだろうと思ったので

##ルンバとマイコンを接続する##

ルンバにはOpen Interface (OI)という規格があり仕様が公開されています

これは自分が所有してる600番系ルンバの仕様書です。バリエーションによっていくつかPDFがあるようです
iRobot Roomba 600 Open Interface Spec
https://www.irobotweb.com/~/media/MainSite/PDFs/About/STEM/Create/iRobot_Roomba_600_Open_Interface_Spec.pdf

下調べでこちらのサイトなどを参考にさせていただきました

ルンバの制御用USBシリアルケーブルを綺麗に作りたいときのメモ - cvl-robot's diary
https://cvl-robot.hateblo.jp/entry/2017/08/28/173943
ルンバにスピッツを演奏させてみた | curious4dev
http://curious4dev.mydns.jp/post-1463/

まずルンバの上ブタを外すとmini DIN7ピンのシリアルポートが出てきます
フタは爪で止まっているので壊さない程度に力づくで外しましょう

image.png

仕様書を見ると7がGND,4がTXD,3がRXDだと分かります

image.png

ジャンパケーブルを使ってマイコンと接続します
自分はAtom mateという基板を介して接続しましたがGPIOが上に向いてるマイコンだったら直接つないでもいいと思います

ATOM Mate - スイッチサイエンス
https://www.switch-science.com/catalog/6532/

注意:ルンバのRX,TXは5Vなので本来3.3VのAtom liteを接続するときはレベルシフタ、ロジックレベルコンバータを使いましょう!
ESP32は5Vトレラントじゃないはずなのになぜか壊れないのですがメーカー非推奨なので自己責任で

NTB0104 レベルシフタ ピッチ変換済みモジュール - スイッチサイエンス
https://www.switch-science.com/catalog/2351/

電源はルンバのVpwrの15vを降圧させるのが王道かと思いますが
USBかTailbat(Atom liteの下につながってる細長い奴)から供給しています

image.png

image.png

image.png

##ルンバと通信する##
仕様書に通信の仕様が載っているので設定を合わせればUARTで通信できます

基本的にはOPcodeに続いて必要ならDataByteを送信するだけという簡単なプロトコルになっています
ルンバを自由に操作するにはsefe modeに入れないといけないので
Start(128)の後にSafe(131)コマンドを送ります

image.png
image.png
image.png


void setup() {
  M5.begin();
 
  // UART通信設定
  Serial1.begin(115200, SERIAL_8N1, 25, 21);
  // start
  Serial1.write(128);
  delay(50);
  // safe mode
  Serial1.write(131);
  delay(50);
  Serial.println("inited");
}

Safe modeに入ったらあとはコマンドを送れば何でもできるのですが、
今回はラジコンとして操作して遊んでみるので吸引(144)と移動(146)のコマンドを使用します

Opcodeに続けてDataBytesを送ることで実行できます

参考にしたサイトではDataBytesの間にdelay入れてたけど自分の環境ではなぜか動作がおかしくなったので入れてませんが
上手く動かないようならdelayを入れてもいいかもしれません

image.png
image.png

void move(int16_t left, int16_t right) {
  // 移動
  Serial1.write(146);
  //   delay(20);
  Serial1.write((right & 0xFF00) >> 8);
  //   delay(20);
  Serial1.write(right & 0xFF);
  //   delay(20);
  Serial1.write((left & 0xFF00) >> 8);
  //   delay(20);
  Serial1.write(left & 0xFF);
}

void vacuum(bool on) {
  Serial1.write(144);
  //   delay(20);
  Serial1.write(on ? 100 : 0);
  //   delay(20);
  Serial1.write(on ? 100 : 0);
  //   delay(20);
  Serial1.write(on ? 100 : 0);
}

##コントローラで操作する##
コントローラとしての送信機についてはスマホのバーチャルパッドやジャイロで操作したりといろいろあると思いますが
いろいろ試した結果物理コントローラが最適だと思ってます(異論は認める)
小学生に操作させてみると動かす対象に目が行ってしまうので手元がおろそかになって思い通りに動かせないんですよね

皆さんはPS3コントローラにこだわる必要はないと思いますのでBlynkとかM5StickCのジャイロとか好きな方法で動かしてください

そして物理コントローラにもBLE HIDとかBT classicいろいろあるのですが入手性と安定性を重視してPS3コントローラを使用します

ライブラリマネージャからインストールできるので手軽です
詳しくはこちらの記事を参照してください

ESP32(M5StickC)をPS3コントローラで操作する - Qiita
https://qiita.com/coppercele/items/0724b0b951868044223b

十字ボタンで移動、スタートボタンで吸引開始、セレクトボタンで吸引停止という動作にするとこのような実装になります

#include <Arduino.h>
#include <M5Atom.h>
#include <Ps3Controller.h>

void move(int16_t left, int16_t right) {
  Serial1.write(146);
  //   delay(50);
  Serial1.write((right & 0xFF00) >> 8);
  //   delay(50);
  Serial1.write(right & 0xFF);
  //   delay(50);
  Serial1.write((left & 0xFF00) >> 8);
  //   delay(50);
  Serial1.write(left & 0xFF);
}

void vacuum(bool on) {
  Serial1.write(144);
  //   delay(50);
  Serial1.write(on ? 100 : 0);
  //   delay(50);
  Serial1.write(on ? 100 : 0);
  //   delay(50);
  Serial1.write(on ? 100 : 0);
}

bool up;
bool down;
bool right;
bool left;

void notify() {
  if (Ps3.event.button_up.select) {
    Serial.println("Released the select button");
    vacuum(false);
  }

  if (Ps3.event.button_up.start) {
    Serial.println("Released the start button");
    vacuum(true);
  }

  if (Ps3.event.button_down.up) {
    Serial.println("Started pressing the up button");
    up = true;
  }
  if (Ps3.event.button_up.up) {
    Serial.println("Released the up button");
    up = false;
  }

  if (Ps3.event.button_down.right) {
    Serial.println("Started pressing the right button");
    right = true;
  }
  if (Ps3.event.button_up.right) {
    Serial.println("Released the right button");
    right = false;
  }

  if (Ps3.event.button_down.down) {
    Serial.println("Started pressing the down button");
    down = true;
  }
  if (Ps3.event.button_up.down) {
    Serial.println("Released the down button");
    down = false;
  }

  if (Ps3.event.button_down.left) {
    Serial.println("Started pressing the left button");
    left = true;
  }
  if (Ps3.event.button_up.left) {
    Serial.println("Released the left button");
    left = false;
  }
  // ナナメ
  if (up && right) {
    move(100, 50);
    return;
  }
  if (up && left) {
    move(50, 100);
    return;
  }
  if (down && right) {
    move(-100, -50);
    return;
  }
  if (down && left) {
    move(-50, -100);
    return;
  }

  if (up) {
    move(100, 100);
    return;
  }
  if (down) {
    move(-100, -100);
    return;
  }
  if (right) {
    move(50, -50);
    return;
  }
  if (left) {
    move(-50, 50);
    return;
  }
  // 何も押されてなければ停止
  move(0, 0);
}

void onConnect() { Serial.println("Connected!."); }
void onDisconnect() { Serial.println("Disconnected!."); }
void setup() {
  //   Serial.begin(115200);
  M5.begin();
  Serial1.begin(115200, SERIAL_8N1, 25, 21);
  // start
  Serial1.write(128);
  delay(50);
  // safe mode
  Serial1.write(131);
  delay(50);
  Serial.println("inited");

  // PS3コントローラ設定
  // notifyで動作
  Ps3.attach(notify);
  Ps3.attachOnConnect(onConnect);
  Ps3.attachOnDisconnect(onDisconnect);
  // 接続するESP32のBLEアドレスに変更する
  Ps3.begin("00:01:02:03:04:05:06");
}

void loop() {
  delay(1);
}

おそらく思ってるより簡単にルンバをハックできると思います
音楽を演奏したりAlexaで清掃モードに入れたりなんてこともできるのでいろいろ楽しみましょう!(゚∀゚)

M5StickC赤外線リモコンをAlexaに対応させよう - Qiita
https://qiita.com/coppercele/items/8c962dabadf33d52709b

41
32
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
41
32

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?