M5StickCでAlexaからサーキュレーターをオンオフする（サーボでスイッチ回す版）

#はじめに
こちらは[M5Stack Advent Calendar 2019](https://qiita.com/advent-calendar/2019/m5stack)の20日目の記事です。
最近M5Stack公式からスマートホームコンテストがあったので、家の何かをM5StickCから動かしてみようと思い、M5StickCから制御するためにサーボを取り付けて、Alexa経由でオンオフしてみました。

結果はこちらの動画のとおりです。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Alexaからサーキュレーターの電源がON/OFF出来るようになった😃<br>これでわざわざスイッチを回さなくてもよくなる。<a href="https://twitter.com/hashtag/M5StickC?src=hash&amp;ref_src=twsrc%5Etfw">#M5StickC</a> <a href="https://t.co/ySBu0u12be">pic.twitter.com/ySBu0u12be</a></p>&mdash; Katsu Shun (@katsushun89) <a href="https://twitter.com/katsushun89/status/1207700223344201729?ref_src=twsrc%5Etfw">December 19, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# サーボ購入
家のサーキュレーターは[ZEPEAL サーキュレーター ホワイト DKS-20W](https://www.amazon.co.jp/gp/product/B004UON8C4/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1)
という3000円ぐらいの安いやつなので、スイッチはダイヤル式になっています。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">スイッチを手で回した感じ <a href="https://t.co/IBUVLAw7Bc">pic.twitter.com/IBUVLAw7Bc</a></p>&mdash; Katsu Shun (@katsushun89) <a href="https://twitter.com/katsushun89/status/1207800561451487232?ref_src=twsrc%5Etfw">December 19, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


家にSG90という小さいサーボはあったんですが、これでこのスイッチを回すのはトルク的に厳しそうだったので、MG996Rというサーボを買いました。2000円はしませんでした。つよつよサーボです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302503/d29e85fd-fc7c-ae26-e059-c727705829e1.png)


# モデリング
Fusion360でもモデリングしました。
MG996Rの[モデリングデータ](https://www.thingiverse.com/thing:653101)はThingiverseにあったのでそれをダウンロードして使いました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302503/2c37e1a5-a7a1-4d63-17c9-25b4b9e958f9.png)


主に以下のパーツを作ります。
- サーボの先に取り付けてダイヤルを回す部分
- サーボ本体側をサーキュレータに固定する部分

ダイヤルを回す部分はモデリングしたら長さが合わなかったので、延長するパーツを追加しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302503/d567f0a9-a167-e522-ac46-469f8dd589cd.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302503/1d32f75b-70c3-dd37-cc54-6629d1d55e88.png)
取り付けようの穴をあけておきます。

サーキュレータに固定するために、サーキュレータの網状の間にツメをひっかけるようにしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302503/cc41cfbd-2c0f-64a4-c8ba-828d7a3b0f98.png)

ひっかける位置はこのように円形に繰り返す形で配置しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302503/19252612-38fc-4ef7-946f-4224fcb0d97a.png)

円形上パターンを使って、網上の部分の数で繰り返したらそれだけでできたのであとはその隙間にツメを入れるように押し出ししてあげました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302503/727fb99c-5acd-bc9a-1bdb-5e2d733c3979.png)

モデリング出来たので3Dプリンタでプリントします。

<img width="400" alt="80883965_2727715270619322_2743009528202133504_n.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302503/d603587b-8328-5836-ff0c-5c74fae77483.jpeg">

割愛していますが、モデリングは失敗して調整、再度プリントを繰り返しています。（今回は2回で出来ましたが、いつも何度かは調整しますね。一発ではほぼ出来ないですw）

サーボに取り付けます。
<img width="400" alt="79932494_476031733116915_5420106190472347648_n.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302503/88456fb1-7238-e64f-2f2f-12a0ef28c58a.jpeg">

<img width="400" alt="79881444_457750478218637_2695721422877097984_n.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302503/3bb22147-b300-cfbc-d0d2-18030a1e32fa.jpeg">


# サーボモータを回してみる
サーキュレータのスイッチの「切」と「中」に合わせるようにサーボの指示角度を調整します。

「切」：10度
「中」：40度
としました。

サーボのPINはM5StickCのGPIO26につなぎます。サーボの電源は電池ボックス(単三4個：6V）につなぎます。M5StickC、サーボ、電池ボックスのGND側のケーブルは繋ぎます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302503/26534d82-279c-b5cb-3add-69bb18a92bfe.png)

動作確認のために10秒単位でON/OFFしてみました。

```cpp:M5StickC_circulator_switcher.ino
#include <M5StickC.h>
#include <Wire.h>
#include <ESP32Servo.h>

Servo servo1; // create four servo objects 
int32_t servo1_pin = 26;
const int32_t MIN_US = 500;
const int32_t MAX_US = 2400;

void setupServo(void)
{
  servo1.setPeriodHertz(50); // Standard 50hz servo
  servo1.attach(servo1_pin, MIN_US, MAX_US);
}

void setup() {
  // put your setup code here, to run once:
  M5.begin();

  Wire.begin(0,26);
  M5.Lcd.setRotation(3);
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(0, 0, 2);

  setupServo();
}

void loop() {
  const int16_t ROTATE_ANGLE = 40;
  const int16_t INITIAL_ANGLE = 10;
  static int16_t pos = INITIAL_ANGLE;
  static int16_t inc = ROTATE_ANGLE;
  servo1.write(pos);
  pos += inc;
  if(pos >= ROTATE_ANGLE) inc = -ROTATE_ANGLE;
  else if(pos <= INITIAL_ANGLE)  inc = ROTATE_ANGLE;
  Serial.println(pos);

  M5.Lcd.setCursor(0, 20, 2);
  M5.Lcd.printf("Angle: %d ", pos);

  delay(10000);
}
```

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">サーキュレーターのダイヤル式のスイッチをサーボで回すやつ出来たー！ <a href="https://t.co/2nBLlNDwWS">pic.twitter.com/2nBLlNDwWS</a></p>&mdash; Katsu Shun (@katsushun89) <a href="https://twitter.com/katsushun89/status/1207323938914623488?ref_src=twsrc%5Etfw">December 18, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


# Alexaから制御
Alexaからオンオフしてみます。
Espalexaというライブラリを使ってみようとしたんですが、一度Alexaのスマホアプリ側で認識したデバイス削除したらその後見つからなくなってしまったので、昔使ったことがあったfauxmoESPというライブラリを使ってみました。

```cpp:M5StickC_circulator_alexa_switcher.ino
#include <M5StickC.h>
#include <WiFi.h>
#include "fauxmoESP.h"
#include <Wire.h>
#include <ESP32Servo.h>
#include "config.h"

Servo servo1; // create four servo objects 
int32_t servo1_pin = 26;
const int32_t MIN_US = 500;
const int32_t MAX_US = 2400;

const int16_t HANDLE_POSITION_OFF = 10;
const int16_t HANDLE_POSITION_2   = 40;
const int16_t HANDLE_POSITION_ON  = HANDLE_POSITION_2;

void setupServo(void)
{
  servo1.setPeriodHertz(50); // Standard 50hz servo
  servo1.attach(servo1_pin, MIN_US, MAX_US);
  delay(10000);
  servo1.write(HANDLE_POSITION_OFF);
}

fauxmoESP fauxmo;

const int led_pin = 10;
const char *id_circulator = "circulator";

void setupWifi()
{
  WiFi.mode(WIFI_STA);
  Serial.printf("connecting to %s¥n", ssid);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.print(".");
    delay(100);
  }

  Serial.println();
  Serial.print("WiFi connected: ");
  Serial.println(WiFi.localIP());
}

void setup() {
  Serial.begin(115200);
  pinMode(led_pin, OUTPUT);
  digitalWrite(led_pin, HIGH);
  setupWifi();
  Wire.begin(0, servo1_pin);
  setupServo();

  fauxmo.createServer(true);
  fauxmo.setPort(80);
  fauxmo.enable(true);

  fauxmo.addDevice(id_circulator);

  fauxmo.onSetState([](unsigned char device_id, const char *device_name, bool state, unsigned char value){
    Serial.printf("Device #%d (%s) state: %s value: %d\n", device_id, device_name, state ? "ON" : "OFF", value);
    if (strcmp(device_name, id_circulator) == 0) {
      digitalWrite(led_pin, state ?LOW : HIGH);

      if(state){
        servo1.write(HANDLE_POSITION_ON);
      }else{
        servo1.write(HANDLE_POSITION_OFF);
      }
    }
  });
}

void loop() {
    fauxmo.handle();
}
```
```cpp:config.h
#pragma once

const char* ssid = "yourssid";
const char* password = "yourpass";

```

これで最初の動画のようにオンオフ出来ました。

# さいごに
Alexaからサーキュレーターの物理的なダイヤルスイッチをサーボで回してみました。
本当は、家の温度をセンシングして閾値以下になったら自動的に電源を入れるというのも作りたかったんですが、時間が間に合わなかったのでそれはまた出来たら別記事書きます。
サーボがあれば結構力づくで家のいろいろなものが動かせるので試してみてくださいー。