*注記*この記事で採用しているアレクサとのつなぎ方はうまく行かないことがあります。うまく行かなくとも当サイトの管理人にはクレームを言わないでください。もっと確実にAlexaとGoogleアシスタントに認識させて声でも動かせるようにするにはRaspberry Pi等の機器を間に入れる必要があるとの結論に達しております。それについてはNode-RED利用によるパソコン起動等の記事で説明しておりますのでそちらも参考ください。とにかくこのやり方はあまり好ましい結果を安定的に産まず、Alexa→Raspberry Pi(Node-RED→Blynkクラウド)→Blynkクラウド→ESP8266→ルンバというメッセージの流れがおすすめになります。*注記ここまで*
以前RoombaをBlynkというサービスから動かすことに成功したという記事をここのブログで公開した。
今回は同じくルンバをAlexaから動かすことに成功したという話でそのやり方について述べる。
Alexaから声で動かせるということはAlexaアプリのスケジュール機能も使って何曜日の何時から掃除するとかっていうのもできるわけで便利になったものだ。
免責事項
この記事を読んでそのまま真似するのは構いませんが機器破損またはその他の事故が起きても当ブログの管理者は責任を負わないのはもちろん、ちゃんと動かなくてもディープな質問等は受け付けないのでご承知おきください。
質問はわかることなら答えなくもないです。
【関連】
Blynkからは動かせた
関連記事を見ていただければわかるようにBlynkというクラウドサービスとESP8266ボードを連携させることでスマホ(Blynkアプリ)→Blynkクラウドサービス→ESP8266ボード→ルンバという流れで掃除をさせることができた。
しかし!
Blynkだと声で指示できない。IFTTTという別のサービスを使えばやってできないことはないがIFTTTというサービスには致命的な欠点があって無料アカウントだと3個までしかそういうレシピを登録できない。
すでに3個ぐらいなんか登録済みなので有料アカウントに変えなければ新しくレシピを増やせないし、かといって有料の会費が高すぎてとても使い倒せる自信がないので使いたくない。
よってなんとかIFTTTに頼らず、さらにBlynkにも頼らず声で操作(AlexaまたはGoogleHomeと連携)できないものかとひたすらYoutubeでAlexaとESP8266接続動画見続けること数ヶ月。
やっとわかった。というかわかってないけどコード完コピでできた。ww
必要な設備
必要な機器
必要な機器に関しては「Blynkからルンバ」の記事を参照してほしい。
そちらにある機器をそのまま使ってESP8266ボードのプログラムを書き換えるだけだ。
必要なソフトウェア
これも特に新しく必要なソフトウェアはない。
しかもAlexaと連携させるならAWS(AmazonWebService)とかに登録しなけりゃだめなんじゃね?って思っていたがそれも不要だ。
とにかくArduinoIDEというパソコンからの開発環境とボードともちろん旧型ルンバがあればよい。
参考コード
注意点
- ここの参考コードは参考サイトからの完コピを自分のルンバ用にアレンジしたものなので他の人のルンバでそのまま動くかというとそれはわからない。
- 多少コードを読んで理解して必要なところは変える必要があるかもしれない。
- 今後も動作改善のためにプログラムを書き換えることがあるがそのときには気が向いたらここのコードも更新することがあるだろうから時々この記事を見直してもらったほうが良いかもしれない。
- Serial.PrintまたはPrintlnはほぼコメントにしてあるのでデバッグ中はコメントを解除しておくと便利かもしれない
- これはPhilipsHueのスマートランプをエミュレートするライブラリを使っているらしいのでAlexaにはランプとして登録される
- ランプのON,OFF命令でルンバを起動と終了をコントロールしている
- ルンバが掃除終了してドックに戻ってもAlexaのステータスはOFFにはならない(と思う。まだ試してない)
- したがってAlexaからルンバ開始と終了の操作はできるが「ルンバが今どういう状態か?」というモニターはできない。ランプじゃないから。
- Blynkのときは掃除終了してドックに戻す命令が1回ではただの停止で2回同じ命令を出すとドックに戻ったがAlexaからだと1回でドックに戻った。このへんのルンバ命令仕様については謎であるが深堀りするつもりはない。
/*参考↓
*/
#ifdef ARDUINO_ARCH_ESP32
#include
#else
#include
#endif
#include
//指定されているオペレーションコードを設定
#define OP_START 128
#define OP_SAFE_MODE 131
#define OP_POWER 133
#define OP_CLEAN 135
#define OP_DOCK 143
#define Roomba Serial
#define R1 15
int pozor=4; //na roombe c.5 na mini d1 D2 pin probuzení
// prototypes
boolean connectWifi();
//callback functions
void firstLightChanged(uint8_t brightness);
// Change this!!
// WiFi Credentials
const char* ssid = "Your_SSID";
const char* password = "Your_Password";
// device names
String Device_1_Name = "任意のルンバ名称できればアルファベットで";
boolean wifiConnected = false;
Espalexa espalexa;
void led_blink(int OnSec,int OffSec,int n){
for(int i=0;i<n;i++){
digitalWrite(LED_BUILTIN, LOW);
delay(OnSec);
digitalWrite(LED_BUILTIN, HIGH);
delay(OffSec);
}
}
void wakeUp(){ //起動
digitalWrite(pozor, HIGH);
delay(100);
digitalWrite(pozor, LOW);
delay(500);
digitalWrite(pozor, HIGH);
delay(2000);
}
void startSafe(){ // Startコマンド(128)でOI開始 & Safe Modeにする(131)
Roomba.write(OP_START); //start
Roomba.write(OP_SAFE_MODE); //safe mode
delay(100);
}
void RoombaClean(){
led_blink(80,20,10);
wakeUp();
Roomba.write(OP_START); //comunication start
delay(20);
Roomba.write(OP_CLEAN);//clean
}
void RoombaToDock(){
led_blink(20,80,10);
wakeUp();
Roomba.write(OP_START); //comunication start
delay(20);
Roomba.write(OP_SAFE_MODE);//2021-12-28追加
delay(20);
Roomba.write(OP_DOCK); //dock
delay(10);
}
void setup(){
pinMode(pozor, OUTPUT);
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
pinMode(R1, OUTPUT);
// Initialise wifi connection
wifiConnected = connectWifi();
if (wifiConnected) {
// Define your devices here.
espalexa.addDevice(Device_1_Name, firstLightChanged); //simplest definition, default state off
espalexa.begin();
led_blink(500,500,4);
wakeUp();
startSafe();
} else {
while (1) { //
Serial.println("Cannot connect to WiFi. Please check data and reset the ESP.");
led_blink(50,50,10);
delay(2500);
}
}
}
void loop() {
espalexa.loop();
delay(1);
if (millis() >= 86400000) { // 86400000ミリ秒 = 1 日 = reset esp8266
ESP.reset();
}
}
//our callback functions
void firstLightChanged(uint8_t brightness)
{
//Control the device
if (brightness)
{
RoombaClean();
// Serial.println("Device1 ON");
}
else
{
RoombaToDock();
// Serial.println("Device1 OFF");
}
}
// connect to wifi – returns true if successful or false if not
boolean connectWifi()
{
boolean state = true;
int i = 0;
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
Serial.println("Connecting to WiFi");
// Wait for connection
// Serial.print("Connecting...");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
if (i > 20) {
state = false; break;
}
i++;
}
Serial.println("");
if (state) {
// Serial.print("Connected to ");
// Serial.println(ssid);
// Serial.print("IP address: ");
// Serial.println(WiFi.localIP());
}
else {
// Serial.println("Connection failed.");
}
return state;
}
Alexaとのリンク手順
デバイス接続
Alexaアプリを起動してデバイスの追加という操作をすると見つけましたという感じでコード内で定義しておいたルンバが登録される。
ルンバが照明の機器カテゴリーに入っているが気にしない。繰り返すがステータスの管理はできない。
定形アクションの定義で声で操作できるようにする
Alexaアプリのホーム画面から→右下にある[その他]→一覧内の[定形アクション]→右上にある[+]
定形アクション名 | 任意 |
実行条件を設定 | 音声→例:ルンバを起動して |
アクションを追加 | スマートホーム→すべてのデバイス→ルンバを選ぶ→電源ON/OFF |
明るさを指示できるオプションもあるがそこはプログラムコード内ではなにもするようになっていない。
明るさは0~255の範囲で指示できるので今後の発展として例えば半分の明るさに指定したらルンバが少し前に出て停止するということもできるだろう。
ルンバが普段手の届かない場所で待機しているようならルンバ内のゴミストッカーを掃除するために良い位置まで動かすという命令を動きに追加しておくと面白いかもしれない。
まとめとあとがき
とうとう旧型ルンバをAlexaから声で命令できるようにできて個人的にはかなりうれしい。
ただ起動はちゃんとできるが、途中で中断して戻したい時に何故かアレクサが「ルンバというデバイス又はグループが見つかりません」と返事をして戻せない。
放置していればいずれルンバが自分で戻るがまだ完璧とは言えない状況だ。
【関連】