arrow-right hamburger logo-mark social-facebook social-github social-twitter
2018.03.28

オフィス改善!物理スイッチの照明を遠隔操作でON/OFFしよう!

たくろーどん

オフィスなう。

お仕事は突然やってくる

こんにちは、宇宙エンジニアのたくろーどんです。

ある日、dotstudioのオフィスにて……。

※上司:ちゃんとく / 下僕部下:たくろーどん

ちゃんとく「デスクから動くのがめんどくさい……。」

たくろーどん「そうですねぇ。(おなかすいた)」

ちゃんとく「なんか電気のONとOFFを遠隔で操作できるデバイスつくってよ!」

たくろーどん「あっ、はい。かしこまりましたでございます。(きょうのごはんはカレーにしよう)」

そんなこんなで突然、ズボラなちゃんとくさんのために電気を遠隔でON/OFFできる装置をつくることになりました。

下記のようなイメージで、電気の物理スイッチを遠隔操作できるリモコンを目指して作ってみます。

実装

まず、物理スイッチを押す機構にはサーボモータを使います。

サーボモータは簡単に角度の制御ができるので、スイッチをON/OFFと切り替えて押すことに適しています。

サーボモータについては、dotstudioドキュメントの「PWM制御(サーボモータの仕組み)」や「遠隔消臭装置をつくって「気の利くナイスガイ」になろう!〜基本実装編〜│codeIQ」の記事などを参考にしてください。

実際に、スイッチが押せるようにサーボモータを取り付けてみます。サーボモータの取り付けもグルーガン職人の手にかかれば一瞬です。

※グルーガン(のりを温めて接着できる装置)は100均で手に入る最強アイテムです。 見た目の改善はあとで考えていきましょう。とりあえず動くことが大事です。

ちなみに回路図はこのようになっています。 今回はサーボモータを4つ繋げているので、Nefry BTからの電源供給が足りず、Nefry BTが再起動してしまうことがあります。そこでサーボモータとNefry BTの電源は分けることによって安定性を高めています。

では、次にプログラムです。

プログラム

今回は、Nefry BTのWebコンソール画面から遠隔操作できるようにしたいと思います。

Nefry BTのWebコンソール画面へは、Nefry BT自身のWi-Fiにつないでアドホックモードにするほか、Wi-Fi設定をして外部からアクセスすることができます。詳細は「Nefry BTのWi-Fiセットアップ」を参照してください。

Webコンソール画面には、Nefry.getWebServer()関数を使って機能追加することができます。少し試してみましょう。

以下のようにプログラムを書くと……

#include <Nefry.h>
void setup() {
  // on()の第一引数でURLを決める
  Nefry.getWebServer()->on("/welcome", [&]() {
    String content = F(
      // 表示するページをHTMLで記述する
      "<!DOCTYPE HTML><html><head><meta charset=\"UTF-8\">"
      "<title>Nefry Welcome</title>"
      "</head><body><div><h1>Nefry Welcome!</h1>"
      "<a href=\"/\">Back to top</a></div></body></html>");
    Nefry.getWebServer()->send(200, "text/html", content);
  });
  // setIndexLink('表示したいページ名', '指定したURL')でTOPページに表示される名前を決める
  Nefry.setIndexLink("welcomePage","/welcome");
}

void loop() {
}

Nefry BTのコンソール画面に「welcomePage」と追加され、クリックすると、「Nefry Welcome」と作成したHTMLページが表示されます。

これを応用して、「Light_on」というHTMLページにアクセスしたらサーボモータが回転するようにしてみます。

// /onというURLのページを作成
Nefry.getWebServer()->on("/on", [&]() {
  String content = F(
    // ページのHTMLを記述
    "<!DOCTYPE HTML><html><head><meta charset=\"UTF-8\">"
    "<title>NefryLight Switch</title>"
    "</head><body><div><h1>On</h1>"
    "<a href=\"/\">Back to top</a></div></body></html>"
  );

  // サーボモータを回転させる
  for(int i=90; i<=115; i++){
    ledcWrite(0,deg2pw(i, PWM_BITWIDTH));
  }
  delay(800);
  ledcWrite(0,deg2pw(90, PWM_BITWIDTH));

  Nefry.getWebServer()->send(200, "text/html", content);
});

// TOPページに「Ligth_on」と表示する
Nefry.setIndexLink("Light_on","/on");

上記のプログラムを4つのサーボモータそれぞれに割り当て、最終的なプログラムの全体はこのようになります。

#include <Nefry.h>
#include"esp32-hal-ledc.h"
#define PWM_BITWIDTH 16

int deg2pw(int deg, int bit){
    double ms = ((double) deg - 90.0) * 0.95 / 90.0 + 1.45;
    return (int) (ms / 20.0 * pow(2, bit));
}

void setup() {
  Serial.begin(115200);
  ledcSetup(0,50,PWM_BITWIDTH);
  ledcSetup(1,50,PWM_BITWIDTH);
  ledcSetup(2,50,PWM_BITWIDTH);
  ledcSetup(3,50,PWM_BITWIDTH);
  ledcAttachPin(A0,0);
  ledcAttachPin(A1,1);
  ledcAttachPin(D0,2);
  ledcAttachPin(D1,3);

  Nefry.getWebServer()->on("/on", [&]() {
    String content = F(
      "<!DOCTYPE HTML><html><head><meta charset=\"UTF-8\">"
      "<title>NefryLight Switch</title>"
      "</head><body><div><h1>On</h1>"
      "<a href=\"/\">Back to top</a></div></body></html>");

    for(int i=90; i<=115; i++){
      ledcWrite(0,deg2pw(i, PWM_BITWIDTH));
    }
    delay(800);
    ledcWrite(0,deg2pw(90, PWM_BITWIDTH));

    Nefry.getWebServer()->send(200, "text/html", content);
  });
  Nefry.setIndexLink("Light_on","/on");

  Nefry.getWebServer()->on("/off", [&]() {
    String content = F(
      "<!DOCTYPE HTML><html><head><meta charset=\"UTF-8\">"
      "<title>NefryLight Switch</title>"
      "</head><body><div><h1>off</h1>"
      "<a href=\"/\">Back to top</a></div></body></html>");

    for(int i=90; i>=65; --i){
      ledcWrite(0,deg2pw(i, PWM_BITWIDTH));
    }
    delay(800);
    ledcWrite(0,deg2pw(90, PWM_BITWIDTH));

    Nefry.getWebServer()->send(200, "text/html", content);
  });
  Nefry.setIndexLink("Light_off","/off");

//////////////////////////////////////////////////////////////
  Nefry.getWebServer()->on("/on2", [&]() {
    String content = F(
      "<!DOCTYPE HTML><html><head><meta charset=\"UTF-8\">"
      "<title>NefryLight Switch</title>"
      "</head><body><div><h1>On</h1>"
      "<a href=\"/\">Back to top</a></div></body></html>");

    for(int i=90; i<=115; i++){
      ledcWrite(1,deg2pw(i, PWM_BITWIDTH));
    }
    delay(800);
    ledcWrite(1,deg2pw(90, PWM_BITWIDTH));

    Nefry.getWebServer()->send(200, "text/html", content);
  });
  Nefry.setIndexLink("Light_on_2","/on2");

  Nefry.getWebServer()->on("/off2", [&]() {
    String content = F(
      "<!DOCTYPE HTML><html><head><meta charset=\"UTF-8\">"
      "<title>NefryLight Switch</title>"
      "</head><body><div><h1>off</h1>"
      "<a href=\"/\">Back to top</a></div></body></html>");

    for(int i=90; i>=65; --i){
      ledcWrite(1,deg2pw(i, PWM_BITWIDTH));
    }
    delay(800);
    ledcWrite(1,deg2pw(90, PWM_BITWIDTH));

    Nefry.getWebServer()->send(200, "text/html", content);
  });
  Nefry.setIndexLink("Light_off_2","/off2");

  //////////////////////////////////////////////////////////////
  Nefry.getWebServer()->on("/on3", [&]() {
    String content = F(
      "<!DOCTYPE HTML><html><head><meta charset=\"UTF-8\">"
      "<title>NefryLight Switch</title>"
      "</head><body><div><h1>On</h1>"
      "<a href=\"/\">Back to top</a></div></body></html>");

    for(int i=90; i<=115; i++){
      ledcWrite(2,deg2pw(i, PWM_BITWIDTH));
    }
    delay(800);
    ledcWrite(2,deg2pw(90, PWM_BITWIDTH));

    Nefry.getWebServer()->send(200, "text/html", content);
  });
  Nefry.setIndexLink("Light_on_3","/on3");

  Nefry.getWebServer()->on("/off3", [&]() {
    String content = F(
      "<!DOCTYPE HTML><html><head><meta charset=\"UTF-8\">"
      "<title>NefryLight Switch</title>"
      "</head><body><div><h1>off</h1>"
      "<a href=\"/\">Back to top</a></div></body></html>");

    for(int i=90; i>=65; --i){
      ledcWrite(2,deg2pw(i, PWM_BITWIDTH));
    }
    delay(800);
    ledcWrite(2,deg2pw(90, PWM_BITWIDTH));

    Nefry.getWebServer()->send(200, "text/html", content);
  });
  Nefry.setIndexLink("Light_off_3","/off3");

  //////////////////////////////////////////////////////////////
  Nefry.getWebServer()->on("/on4", [&]() {
    String content = F(
      "<!DOCTYPE HTML><html><head><meta charset=\"UTF-8\">"
      "<title>NefryLight Switch</title>"
      "</head><body><div><h1>On</h1>"
      "<a href=\"/\">Back to top</a></div></body></html>");

    for(int i=90; i<=125; i++){
      ledcWrite(3,deg2pw(i, PWM_BITWIDTH));
    }
    delay(800);
    ledcWrite(3,deg2pw(90, PWM_BITWIDTH));

    Nefry.getWebServer()->send(200, "text/html", content);
  });
  Nefry.setIndexLink("Light_on_4","/on4");

  Nefry.getWebServer()->on("/off4", [&]() {
    String content = F(
      "<!DOCTYPE HTML><html><head><meta charset=\"UTF-8\">"
      "<title>NefryLight Switch</title>"
      "</head><body><div><h1>off</h1>"
      "<a href=\"/\">Back to top</a></div></body></html>");

    for(int i=90; i>=65; --i){
      ledcWrite(3,deg2pw(i, PWM_BITWIDTH));
    }
    delay(800);
    ledcWrite(3,deg2pw(90, PWM_BITWIDTH));

    Nefry.getWebServer()->send(200, "text/html", content);
  });
  Nefry.setIndexLink("Light_off_4","/off4");

}

void loop() {
}

これで、Nefry BTのコンソール画面から遠隔でサーボモータを制御できるようになりました。 また、Nefry.getWebServer()関数を使うことで、HTMLを書く要領でコンソール画面をカスタマイズすることができます。

試してみる

たくろーどん「ちゃんとくさん、遠隔操作できる仕組みが完成しました!早速試してみてください。」

ちゃんとく「やった!さっそくデスクからポチっとな」

たくろーどん「おぉ、これで遠隔で電気のON/OFF操作は完璧ですね!」

ちゃんとく「便利になったけど、SSIDの命名センスがすごい

※Nefry BTのSSIDは変更することができる。「Nefry BTのSSIDを変更する」を参照。

たくろーどん「満足してもらえたようで嬉しいです。」

終わりに

このようにdotstudioではお仕事が急にやってくるので柔軟な対応が求められます。ヘマをすると何がおこるかわからないので、今回は首の皮一枚つながりました。

遠隔でデバイスを操作するには、今回のようにNefry BTのコンソール画面を応用する他にも、スマホアプリから操作できるようになる「Blynk」を使ったり、リアルタイム通信を簡単に実現できる「Milkcocoa」を使ったりと、いろいろな方法があります。

ぜひみなさんも試してみてはいかがでしょうか?