Wi-Fiなし旧型ルンバをスマホからリモート操作でIoTを実現する方法について述べている記事。
サーボをくねくねと動かして気を良くした自分はいよいよルンバかなということでやってみた。
ぶっちゃけちゃうともうわかっちゃったので手順さえ踏めば誰でもできるよといえる。
【関連】
初期型Wi-Fiなしルンバのリモート操作に至る発端
興味なかったら飛ばしてください。
Raspberry Piの応用例として
Raspberry Pi楽しいですよね。
いろいろRaspberry Piの応用について書かれたサイトを見ているうちに旧型ルンバでもIOポートがあってIoT化できるという記事を見かけたわけだ。
それならやりごたえあるし実際にすごく実用的なのでやりたい。
ではルンバをリモートで操作できるようにできたらどんな機能を付けたいかというと、
- カメラ
- スケジュールで掃除開始
- 部屋の間取り覚える(実現方法は不明)
- アレクサやGoogleとの連携プレー(IFTTTは有料うんこだから却下)
といったところ。これらはかなり贅沢な機能だから素人としては、とりあえず掃除開始だけでもつけられれば十分と考える。
手持ちルンバのスペック
同じようなことを考える人のために我が家のWi-Fiなし旧型ルンバのスペックも述べておく。
- ルンバ型番は620
- Wi-Fi機能ない
- リモコンあるけど効かない(SwitchBotから操作しようと画策もした)
- リモコン操作機能は多少ある
もうかれこれ10年前に買ったものでまだバッテリーを変えたりして現役ビンビンだ。
実現への調査項目
「ルンバ Raspberry Pi」などで検索
無数の参考サイト
以下に列挙しておく
- ロボット掃除機のルンバを思い通りに動かしてみよう|4009
- Roomba voice control with Alexa and Belkin-Wemo emulator(Belkinエミュレーターのライブラリは今では無効になっていて使えないらしい)
- 試行錯誤な日々: いろんなArduinoのシリアルを関数の引数として使う方法
- ルンバを Raspberry Pi でコントロールする – たるこすの日記
- ルンバをESP32でBluetooth通信で動かす方法 | UEC Media Design Lab
- MZ Platformとフィジカルコンピューティング
- Roomba Gets Alexa Support With An ESP8266 Stowaway | Hackaday
- Raspberry Pi 3にRobot Operating System(ROS)をインストール | TomoSoft
- Ubuntu 16.04 LTS + ROS のインストール (RaspberryPi)
- Raspberry Pi 3用ROSインストール済みUbuntu Server 16.04.3 LTS | 上田隆一の仕事とか
- Raspberry Piでルンバをハックする | ファブリカコミュニケーションズ
- raspberrypiからルンバを操作する(1) | WASP株式会社
- raspberrypiからルンバを操作する(2) | WASP株式会社
- raspberrypiからルンバを操作する(4) | WASP株式会社
- ルンバIO仕様書(英語)
- ルンバの制御用USBシリアルケーブルを綺麗に作りたいときのメモ – cvl-robot’s diary
- ESP8266 と Blynk を使ってサーボモータを制御 : 徒然.make
- ESP8266 – WeMOS D1 mini – ch340
- Arduino IDE にESP8266のボードをインストールする。 – Mira&Luna’s nursery lab
Raspberry Piによる当初の実現手順構想
- Raspberry PiにUbuntu(LinuxOSの一種)入れる
- Raspberry PiにROS(ロボットOS)入れる
- Raspberry Piってシリアル出力ポートがないらしいのでルンバに命令送るにはシリアル変換ボードが必要とのこと
- なんか相互通信して命令だす
- ハードル高すぎ
- ROSのインストールを何度やってもどこかしらでエラーになって最後までノーエラーで到達できない
- 自分のスキルレベルでは到底エラー除去などできるはずもない
- あきらめる
という感じで数行でまとめてしまっているがいろいろパターンを変えて数週間かけて多少の知見は得たものの何も実利を得ていないという結果。
ESP8266等のマイコンボードでもできるらしい
そのころ同時並行的にESP8266マイコンボードでサーボを動かしてBlynkサービスも使ってコントロールできるようになったのでこっちのボード使えないかと調べる。
Raspberry Piに比べたら結構かんたんそうで、ROSなんて入れる必要ないのはもちろん、簡単なコマンドをいくつか送るだけで実現している実例を見かける。
特にさきほど参考サイトでも紹介したこことか、ここのYouTubeの人のはかなりかんたんそうなコード進行。ただし前者のサイトはコードがまともに紹介されてないので実例があるというだけで参考にならない。
ルンバの仕様書は英語のみ
前述参考サイトのひとつにも入れてあるけど、→これ(ルンバIO仕様書(英語))が英語だから理解するのに少々難儀する。
やっぱり若いうちには勉強しておかないとやりたいことがまともにできなくなるよって一例。
とはいえ今は翻訳サービスが充実しているからそんなに障害にもならんけど。
Wi-Fiなし旧型ルンバをリモートで動かす手順
能書きが長かったがいよいよ本題。
必要なハード
- AliExpressで買えるマイコンボードESP8266(またはESP32でも可かと思われる。いやたぶん可能)
AliExpressで買った。技適についてはノーコメントとする。不安な人はAmazonまたは秋月電子で探してください。 - 直流変圧器
ルンバのバッテリーからマイコンボードに供給する電気をもらうが、ルンバのちょっと高い電圧をESP8266用に少し下げるボード。秋月電子で売ってたけどAmazonでは同じものはなさそう。
OKL-T/6-W12N-C使用 最大6A 小型高効率DCDCコンバーター可変電源キット(降圧): 組立キット(モジュール) 秋月電子通商-電子部品・ネット通販
▼Amazonでおそらく同等機能のものが3個で1000円程度で売られているから複数のルンバを操作したいとか旧型ルンバを仕入れて改造してWi-Fi対応にしてビジネスしたいとかだったらこっちのほうがお得かも。
HiLetgo 3個セット 5A DC-DCステップダウン調整可能電源モジュール降圧コンバータ 4~38V 電源アウトプット1.25-36V [並行輸入品]
¥1,050(2021/12/12 21:24時点の価格)
平均評価点:
>>楽天市場で探す
>>Yahoo!ショッピングで探す - その他代用可能な部品
ブレッドボード・・・再利用を考えず埋め込むorぶっつけ本番イケイケなら不要
ジャンプワイヤー・・・ブレッドボードに刺して使うワイヤー
ルンバへのつなげ方
絵心ないから一応言葉で付け足すと、左のボードは下にMicroUSBポートをおいて見た図である。
【追記】7ピンのプラグを買ってつけたので色を備忘録として残しておく。
コード色 | ||
電圧変換基板のIN+ | ルンバの電源ピン(2個のいずれか) | 赤 |
電圧変換基板のINー | ルンバのGNDピン | 黒 |
電圧変換基板のOUT+→ | ESP8266のGND(2個のいずれか) | |
電圧変換基板のOUTー→ | ESP8266の3.3V | |
ESP8266のTXD0ピン(=GPIO1)→ | ルンバのRXDピン | 灰 |
ESP8266のGNDピン(いずれか)→ | ルンバのGNDピン(2個のもう片方) | 茶 |
ESP8266のGPIO4(D2)ピン→ | ルンバのBRCピン | 白 |
▼一旦分解してスリーブの中にコードを通してからはんだ付けする。
▼スリーブの一番上のコード保護の部分は切り落とした。じゃないと背が高くなりすぎる。
▼最終的にはこんな感じにできあがってなんとなくコンパクト。
▼最終的には100均ケースにうまく仕込んでこんなふうにコンパクトにできた。一見するとルンバの上になにかプラケースが乗ってるだけにしか見えない。カムフラージュする必要ないけど。
スマホ側での準備
Blynkアプリを使うが以前別の記事でBlynkアプリの設定について触れたのでここでは割愛する。
注意点としてはプログラムコード内のV0とかV1という仮想ピンとスマホ画面での仮想ピンの番号をあわせる。
処理の流れ
スマホでBlynkアプリで操作
例えばスマホのBlynk画面にボタン1とボタン2と用意しておく。
ボタン1には掃除開始のV0を当てはめ、ボタン2にはドックへ戻るV1を当てはめる。
▼左のV3~V5が今回つくったボタン上の2個は前回のサーボ用。右画像がそのうちのV3の機能を展開したところ。とくに変わったことはしていない。
ルンバへの命令の例
たとえば掃除開始ボタン→ルンバが掃除開始なら下記のようなコードを送る。
最初に通信開始コードを送る:128
Serial.write(128);
次に掃除開始コード送る:135
Serial.write(135);
さらにドックボタンを押すと掃除を中断してドックに戻るということができるのが下記コード
掃除中に送る:143
Serial.write(143);
こんなコードだけ見たってそれをどうやって実装するんじゃ?ってところが知りたいことだよね。でも実際ほぼこれらを組み合わせるだけで実現できた。
ほかにもコマンドあるけどハマりたくないからそれだけで良し
掃除開始とドックに戻るさえできればよしとする。
ほかのマニアックな人達はルンバを自由自在にリモート操作して前進、後退、右、左とか音楽を再生させたりとかして楽しいみたいだけど俺はそんなのぜんぜん興味なくてQOL上げるのが目的。
だから遠隔で掃除命令さえ出せれば最低限OKで、欲をいえばスケジュールによる掃除開始、もっと欲をいえば間取り記憶とかあるけどさすがにそこまでは無理。ましてや自由に操るとかいうのは方向性が違う。
備忘録
いろいろ調べていく中で「そういうことか」と学んだことがらをここに書いておく。
- スリープしていると開始コマンド128を送っても無効だった(スリープとはルンバ620でいえば中央のランプが消灯している状態)
- スリープから起こすにはルンバのBRCポートにハイ&ロー信号を送ると目覚めるらしい
開始コマンド128とスリープから起こすデジタル出力はどっちが先?って思うけどポートが違うから一律ではなくスリープから起こすにはBRCポートに送るし、スリープしてないときは最初にRXDポートに128を送るってこと。←間違ってるかわからん。 - ESP8266のシリアル送信ピンはGPIO1でおそらくどのESP8266ボードも同じ
だからSerial.write(nn)ってコマンドするだけでルンバに命令を送れる。ラズベリーパイでせっせことROS入れてやるのなんてオーバースペックも甚だしい。さらになにかやる(間取り記憶とか)なら別だけど。 - alexaに認識させるエミュレーターライブラリは数年前まで使えてたが今は無効。そういうサイトで見本コードがあったから入れてみて散々動かしてみたけどうんともすんとも言わなかった理由があったわけ。時間の無駄だった。
- ESP8266の電源はモバイルバッテリー繋げてる人いるけどルンバから取れる
ただし→3.3Vに降圧すること - シリアル通信のボーレートは115200で基本いく
- ドック以外の場所でのスリープ中にはコマンド効かない
起こす呪文が前述のBRCポートに信号送るっぽい
▼以下その他の引用。
- ピン1(, 2):電源供給に使うピン。ルンバの充電状況によって出てくる電圧値が異なるので、レギュレータを挟んで5Vに整えてからESP32の5Vピンにつなぐ。(PCとESP32 を有線でつなぐ場合は、つながない)
- ピン3:ルンバへのインプット。ESP32からの波形をそのまま入れてもよい(HIGHと認識される最低電圧が2.0Vのため)し、トランジスタなどでレベル変換して5Vの波形にしてから入れてもよい。
- ピン4:ルンバからのアウトプット。抵抗を挟むなどして5Vから3.3Vに落とし、ESP32に入れる。
- ピン5:ボーレート変更用のピン。Sleep状態からルンバを起こすのにも使う。ピン3と同様に、ESP32から3.3Vの波形をそのまま入れるか、5Vにレベル変換して入れる。
- ピン6(, 7):グラウンド。ESP32のGNDピンとつなぐ。
▼最終的にほぼ完コピさせてもらった人の動画。ソースコードは公開されていなかったので概要欄からリクエストしてリンクを送ってもらった。ソースコードも公開されていた。
ソースコード(スケッチ)
基板への書き込み等についてはこちらの記事でさらっと述べているので多少は参考になるかもしれません。
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#define Roomba Serial
int pozor=4; //na roombe c.5 na mini d1 D2 pin probuzení
// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "あなたのBlynkトークン";
// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "あなたの環境のSSID";
char pass[] = "あなたの環境のパスワード";
// This function will be called every time Slider Widget
// in Blynk app writes values to the Virtual Pin 1
void led_blink(int OnSec,int OffSec,int n){
for(int i=0;i<n;i++){
digitalWrite(LED_BUILTIN, LOW); // turn the LED on (HIGH is the voltage level)
delay(OnSec); // wait for a second
digitalWrite(LED_BUILTIN, HIGH); // turn the LED off by making the voltage LOW
delay(OffSec); // wait for a second
}
}
void wakeUp(void){ //スリープから起こす
digitalWrite(pozor, HIGH);
delay(100);
digitalWrite(pozor, LOW);
delay(100);
digitalWrite(pozor, HIGH);
delay(500);
}
// virtual pin 0 = CLEAN
BLYNK_WRITE(V3){
int pinValue = param.asInt();
if (pinValue == 1){
led_blink(20,10,2);
wakeUp();
Roomba.write(128); //comunication start
delay(10);
Roomba.write(135);//clean
}
}
// virtual pin 1 = DOCK
BLYNK_WRITE(V4){
int pinValue = param.asInt();
if (pinValue == 1){
led_blink(90,10,4);
wakeUp();
Roomba.write(128); //comunication start
Roomba.write(143); //dock
delay(10);
}
}
// virtual pin 2 = SPOT
/*BLYNK_WRITE(V6)
{
int pinValue = param.asInt();
if (pinValue == 1){
led_blink(20,10,5);
Roomba.write(134); //spot
delay(10);
}
}*/
// virtual pin 3 = pause
BLYNK_WRITE(V5){
int pinValue = param.asInt();
if (pinValue == 1){
led_blink(90,10,2);
Roomba.write(133);//pause
delay(10);
}
}
void setup(){
pinMode(pozor, OUTPUT);
pinMode(LED_BUILTIN, OUTPUT);
Roomba.begin(115200);
Blynk.begin(auth, ssid, pass);
// You can also specify server:
//Blynk.begin(auth, ssid, pass, "blynk-cloud.com", 8442);
//Blynk.begin(auth, ssid, pass, IPAddress(192,168,1,100), 8442);
led_blink(500,500,4);
}
void loop(){
led_blink(10,1990,1);
Blynk.run();
if (millis() >= 86400000) { //1日1回リセットしますとのこと
ESP.reset();
}
}
なぜかソースコードのネストのスペースが自動で消えてしまいいちいち入れても消えるからくじけたので読みにくいがおそらくPV少ないだろうからあまり気にしないことにする。
ちょっとだけ解説を入れておくと、
wakeup()関数でBRCポートにハイローとかって信号を打ち込んでるけど効いてるのか効いてないのか不明。
ただこのコードをコピペしてエラーなくコンパイルできればルンバは動くんじゃないかって思う。
新しい知見(シーケンス整理)
一応メモ残しておく。
ドックで充電中に送るコマンドシーケンスとドックから出ているときで送るコマンドシーケンスで一時同じものを送ってしまって動かなくなってしまったことがあった。
ドックにいるときに送るシーケンスは
- デジタルピンにHIGH→LOW→HIGHと0.1秒間隔で送る
- シリアル128を送る(パッシブモードへ移行)
- シリアル135を送る(掃除開始)
ドックから離れているとき(掃除中)に送る終了シーケンスは
- ドックにいるときの1と同じ
- ドックにいるときの2と同じ
- シリアル131を送る(セーフモードへ移行)
- シリアル143を送る(帰還命令)
ドックから離れているとき(掃除中)に送る停止シーケンスは
- ドックにいるときの1と同じ
- ドックにいるときの2と同じ
- シリアル131を送る(セーフモードへ移行)
- シリアル150を送る(一時停止)
ドックから離れているとき(停止中)に送る帰還命令シーケンスは掃除中の終了シーケンスと同じ。
つまりドックにいるときだけはシリアル131を送らない。
動画もどうぞ
【関連】