PR 記事には広告が含まれています
スポンサーリンク
Translate

スマートフォンでどこからでも燃えプロの「プレイボール」が発声できるようになりました

スポンサーリンク

Remote MoePro Synthesizer燃えプロシンセサイザーは、爆発的に売れたファミコンカセット「燃えろプロ野球」の音声を生で聞けてしまう画期的な装置です。その声をスマートフォンでリモート発声させることができました。

スポンサーリンク

まずはこちらをご覧ください

スマートフォンに表示された「PUSH」ボタンをタップすると、燃えプロシンセサイザーから「プレイボール」と、発声します。

仕組み

ESP32とスマートフォンは、それぞれ家庭内のWiFiに接続しています。

スマートフォンのブラウザで、ESP32のIPアドレスにアクセスすると、ボタンのWebページが表示されます。

スマートフォンでこのボタンをタップすると、ESP32のIOポート信号が出て、燃えプロシンセサイザーのボタンが押されたことと同等な状態にします。

燃えプロシンセサイザーから、そのボタンに対応した音声が再生される。

と言う仕組みです。

燃えプロシンセサイザーは、「プレイボール」だけでなく、カセットに内蔵された16種類全ての音声を再生することができます。

なので、配線とプログラム次第で、その音声もリモートで発生させることができるようになりますね。

スポンサーリンク

回路

燃えプロシンセサイザーのボタンは、全てそれぞれプルアップされており、ボタンを押されたことでGNDに接続され信号線がLowになることで、発声が開始されます。

そこで、ボタンの信号線のピンを、ESP32のマイコンのIOピンへ接続します。ただし、燃えプロシンセサイザーの電源電圧が4.5Vなのに対し、ESP32は3.3Vなので、直接つないでしまうと電圧が違うためあまり良くありません。そこでマイコンがLowになったときにだけ、ボタンがLowになるように、ダイオードを入れておきます。

信号線はESP32のIO22へ接続し、GNDはESP32のGNDへ接続します。

配線は、この2本だけとなります。

Remote MoePro Synthesizer

とっても、シンプルな配線です。

スポンサーリンク

プログラム

プログラムはArduinoで作りました。

#include <WiFi.h>

char* ssid = "SSID";
char* password = "PASSWORD";

WiFiServer server(80);
String header;
IPAddress ip;
int pin = 22;

void setup() {
  pinMode(pin, OUTPUT);
  Serial.begin(115200);

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(100);
  }
  Serial.println();
  ip = WiFi.localIP();
  Serial.println((String)"WiFi ok");
  Serial.print((String)"Server IP : ");
  Serial.println(ip);
  server.begin();
}

int pin_val;
int oldmillis = 0;
void loop() {
  WiFiClient client = server.available();
  if (client) {
    //Serial.println((String)"新しいお客様が来店しました");
    String now_line = "";
    while (client.connected()) {
      if (client.available()) {

        char read_client = client.read();
        //Serial.write(read_client);
        header += read_client;

        if (read_client == '\n') {

          if (now_line.length() == 0) {
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();

            client.println(
              (String)
              "<!DOCTYPE html>" + "\n" +
              " <html>" + "\n" +
              "   <head>" + "\n" +
              "    <meta charset=\"utf-8\">" + "\n" +
              "    <meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">" + "\n" +
              "    <style>" + "\n" +
              // ------ 上下左右 中央寄せスタイル ------
              "      .center {" + "\n" +
              "        position: absolute;" + "\n" +
              "        top: 0;" + "\n" +
              "        bottom: 0;" + "\n" +
              "        right: 0;" + "\n" +
              "        left: 0;" + "\n" +
              "        margin: auto;" + "\n" +
              "        width: 100px;" + "\n" +
              "        height: 100px;" + "\n" +
              "      }" + "\n" +
              // ------ ボタンスタイル 下サイトのを改変 ------
              // https://saruwakakun.com/html-css/reference/buttons
              "      .btn-circle-flat {" + "\n" +
              "        display: inline-block;" + "\n" +
              "        text-decoration: none;" + "\n" +
              "        background: #87befd;" + "\n" +
              "        color: #FFF;" + "\n" +
              "        width: 250px;" + "\n" +
              "        height: 250px;" + "\n" +
              "        line-height: 200px;" + "\n" +
              "        border-radius: 50%;" + "\n" +
              "        border: none;" + "\n" +
              "        text-align: center;" + "\n" +
              "        overflow: hidden;" + "\n" +
              "        font-size: 60px;" + "\n" +
              "        font-weight: bold;" + "\n" +
              "        text-shadow: rgba(0, 100, 255, 0.5) 5px 5px 0;" + "\n" +
              "      }" + "\n" +
              "      .btn-circle-flat:active {" + "\n" +
              "        background: #5ea5fd;" + "\n" +
              "      }" + "\n" +
              "    </style>" + "\n" +
              "    <script>" + "\n" +
              // ------ /pushをgetリクエストする関数 ------
              "      function push() {" + "\n" +
              "        let request = new XMLHttpRequest();" + "\n" +
              "        request.open('GET', '/push');" + "\n" +
              "        request.send(null);" + "\n" +
              "      }" + "\n" +
              "    </script>" + "\n" +
              "   </head>" + "\n" +
              "   <body>" + "\n" +
              "     <input class=\"center btn-circle-flat\" type=\"button\" value=\"PUSH\" onmousedown=\"push()\">" + "\n" +
              "   </body>" + "\n" +
              " </html>" + "\n"
            );
            client.println();

            if (header.indexOf("GET /push") >= 0) {
              digitalWrite(pin, LOW);
              oldmillis = millis();
            }

            break;
          } else {
            now_line = "";
          }
          //is \n
        } else if (read_client != '\r') {
          now_line += read_client;
        }
        //available
      }
      //while connected
    }
    header = "";
    client.stop();
    //Serial.println((String)"ありがとうございました〜");
    //no null
  }
  if (millis() - oldmillis > 100) {
    //pinを変更してから100ms経ったら
    digitalWrite(pin, HIGH);
  }
}

SSIDとPASSWORDをご自宅の無線LANの設定に合わせて、変更してください。

プログラムの流れはこうです。

  • 無線LANに接続します。
  • ESP32がWebサーバになりスマートフォンなどのブラウザから接続されるのを待ちます。
  • 接続があれば、Webサイトの表示データを送信し、ブラウザにボタンが表示されます。
  • ボタンのデザインはCSSで設定してあり、ボタンをタップすると、JavaScriptによってGETリクエストが発生するようになっています。
  • ESP32はGETリクエストを受信すると、IOピンをLowにして、100m秒後にHightにします。

この仕組みによって、ページのリロードなしに、短い時間間隔でボタンが何度も押せるようになります。

プログラムをコンパイルしてESP32に書き込みます。

スポンサーリンク

実行

実装すると、シリアルモニターに、ESP32のIPアドレスが表示されます。

そのIPアドレスを、スマートフォンのブラウザにあるURLに入力します。

Remote MoePro Synthesizer

すると、ブラウザに「PUSH」ボタンが表示されます。あとは押すだけ。

家のどこにいても、燃えプロの「プレイボール!」を発声できるようになりました。