WiFiアクセスポイントでデバイス間の近距離遠隔操作方法(AtomS3使用)

AtomS3 WiFiアクセスポイントで遠隔操作アイキャッチ

AtomS3は小型ながら液晶付きでWi-Fi通信までできて便利ですが、Bluetooth機能が無いのが残念・・・。
頻繁に使うものではないですが、近距離通信をするにはやっぱりBluetoothが便利です。

Wi-Fi機能はあるのでWi-Fi経由での遠隔操作はできますが、Wi-Fi環境のないところでも遠隔操作したい!
ということで、今回はWi-Fiアクセスポイント機能を使用した近距離遠隔操作の方法を詳しく紹介します。

動作確認用のWebアプリはChatGPTが書いてくれたので、これについても最後に紹介しています。


Arduinoコマンドを使用したアクセスポイントのプログラムについては、以下で詳しく紹介しています。

WiFi(アクセスポイント、サーバー)で近距離遠隔操作する方法(Arduinoプログラミング)
「ATOM LITE」を例にWiFiアクセスポイントに設定して、スマホ等から近距離遠隔操作を行う方法を紹介します。サーバーのリクエスト(要求)に対してレスポンス(応答)を返すという動作を利用して、簡単なプログラムで遠隔操作が実現できます。
スポンサーリンク

1.AtomS3/AtomS3 Liteとは

「AtomS3/AtomS3 Lite」とは「M5Stackテクノロジー社」のマイコンボードで小型ですが、シリアル通信はもちろんWi-Fiも使えます。「AtomS3」には液晶表示器もついています。

他にも本体正面ボタンが1個、赤外線LED(送信のみ)、入出力端子、GROVEコネクタ、USB Type-Cが搭載されています。基板剥き出しではなくケースに入っているので安心して使用できます。

拡張ユニットも豊富でこれらのユニットを接続すれば、SDカードやGPS、バーコードリーダー、スピーカー、リレー、RS-232C/RS-485/CAN等の通信を使用することができます。

これらの機能をプログラムで自由に使用することができるため、電子工作やプログラミング学習等に最適です。


「AtomS3/AtomS3 Lite」については、以下のリンクで詳しく紹介しています。

AtomS3 Liteの使い方、端子配列、初期設定をサンプルプログラムで詳しく紹介
Atom Liteの高機能版AtomS3 Liteの使い方を,端子配列,開発環境別の初期設定,Atom Liteとの違い等をサンプルプログラムで詳しく紹介します。
AtomS3の使い方、端子配列、開発環境、サンプルプログラムで詳しく紹介
プログラミング学習も電子工作もこれ1台でOK!コンパクトな設計に液晶画面,WiFi,シリアル通信,6軸センサまで搭載したAtomS3について詳しく紹介します。
スポンサーリンク

2.Wi-Fiアクセスポイントとは

Wi-Fiアクセスポイントとは、無線LAN(Wi-Fi)を使ってインターネットに接続するための機器です。

一般的には、有線のブロードバンド回線やルーターに接続し、無線でノートパソコンやスマートフォンなどの端末からインターネットに接続するために使用され、複数のアクセスポイントを設置して通信範囲を広げることも可能です。

今回使用する「AtomS3/AtomS3 Lite」もWi-Fi機能を利用して、アクセスポイントとして設定することができ、他のデバイスやブラウザ上からアクセスすることができます。
この機能を利用することで、アクセスポイントに設定したデバイスを遠隔操作することも可能になります。
スポンサーリンク

3.全体の構成・動作紹介

全体の構成と動作については以下のようになります。

親機として「AtomS3」をアクセスポイントに設定して、子機の「AtomS3 Lite」からWi-Fi接続します。(子機は複数あっても同じ操作ができます。)

親機の「AtomS3」にはリレーユニットを接続してお好みの機器をON/OFFできるようにしてあります。子機の「AtomS3 Lite」の本体ボタンを押すごとに「AtomS3」に接続したリレーがON/OFFします。

下画像の左が子機の「AtomS3 Lite」で、真ん中が親機の「AtomS3」、右がGroveコネクタに接続できる「リレーユニット」です。

AtomS3 WiFiアクセスポイントで遠隔操作

電源を入れると「AtomS3」はアクセスポイントとして起動し、「SSID、パスワード、IPアドレス」が表示されます。
「AtomS3 Lite」はアクセスポイントに接続するとLEDが白色に点灯します。

AtomS3 WiFiアクセスポイントで遠隔操作

「AtomS3 Lite」の本体ボタンを押すとリレーがONし「AtomS3 Lite」のLEDが青色に点灯します。(通信エラーの場合は「AtomS3 Lite」のLEDが赤色に点灯します。)

AtomS3 WiFiアクセスポイントで遠隔操作

もう一度「AtomS3 Lite」の本体ボタンを押すとリレーがOFFし「AtomS3 Lite」のLEDがオレンジ色に点灯します。(通信エラーの場合は「AtomS3 Lite」のLEDが赤色に点灯します。)

AtomS3 WiFiアクセスポイントで遠隔操作

親機の「AtomS3」にパソコン等から接続し、IPアドレス「192.168.4.1」にアクセスすると上画像のように「Access!」が表示されます。
(Wi-F-接続先のSSIDは「ATOMS3-01」パスワードは「11111111」です。)

4.サンプルプログラム(親機:AtomS3)

親機の「AtomS3」のサンプルプログラムは以下のようになります。

※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。

#include <M5AtomS3.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <HTTPClient.h>

WebServer server(80); // サーバー設定、ポート80(デフォルト)で接続
HTTPClient http;      // HTTPクライアントを実現するためのクラス

// ピン番号設定
#define OUTPUT_PIN0 2 // 出力ピン

// アクセスポイント設定
const char ssid_AP[] = "ATOMS3-01"; // SSID
const char pass_AP[] = "11111111";  // パスワード(8文字以上)

//変数宣言
bool state = false; // 本体ボタン状態格納用

// 関数 *********************************************************
// wifi接続実行 --------------------------------------------
void StartAP() {
  // アクセスポイント開始関数
  WiFi.softAP(ssid_AP, pass_AP);  // ソフトAP設定
  // アクセスポイントのアドレス初期値「192.168.4.1」を変更する場合は以下で指定
  // IPAddress ip(192, 168, 4, 3);            // IPアドレスを指定
  // IPAddress gateway(192, 168, 4, 1);       // ゲートウェイを指定
  // IPAddress subnet(255, 255, 255, 0);      // サブネットマスクを指定
  // WiFi.softAPConfig(ip, gateway, subnet);  // IPアドレスを設定

  // WiFi接続結果表示
  M5.Lcd.fillScreen(0);     // 表示クリア
  M5.Lcd.setTextFont(2);    // フォント
  M5.Lcd.setCursor(0, 0);   // 表示開始位置左上角(X,Y)
  M5.Lcd.print(" SSID= ");  // SSID表示
  M5.Lcd.println(ssid_AP);
  M5.Lcd.print(" PASS= ");  // パスワード表示
  M5.Lcd.println(pass_AP);
  M5.Lcd.print(" IP= ");    // IPアドレス表示
  M5.Lcd.println(WiFi.softAPIP());
}

// ルート(IPアドレス)アクセス時の応答関数 -----------------------------------
void handleRoot() {
  server.send(200, "text/html", "200 Root Access!");  // レスポンス200(通信成功)を返す
  USBSerial.println("Access!");
  M5.Lcd.setCursor(5, 65);            // 表示開始位置左上角(X,Y)
  M5.Lcd.println("    Access!    ");  
}
// エラー(Webページが見つからない)時の応答関数
void handleNotFound() {
  server.send(404, "text/plain", "404 Not Found!"); // 404エラーを返す
}

// (IPアドレス)/on アクセス時の応答関数
void relayOn() {
  server.send(200, "text/html", "200 Relay ON!");   // レスポンス200を返す
  USBSerial.println("Relay ON");
  M5.Lcd.setCursor(5, 65);          // 表示開始位置左上角(X,Y)
  M5.Lcd.println("Relay ON   ");
  digitalWrite(OUTPUT_PIN0, HIGH);  // リレーON出力
}
// (IPアドレス)/off アクセス時の応答関数
void relayOff() {
  server.send(200, "text/html", "200 Relay OFF!");  //レスポンス200を返す
  USBSerial.println("Relay OFF");
  M5.Lcd.setCursor(5, 65);          // 表示開始位置左上角(X,Y)
  M5.Lcd.println("Relay OFF");
  digitalWrite(OUTPUT_PIN0, LOW);   // リレーOFF出力
}

// 初期設定 **************************************************
void setup() {
  M5.begin(true, true, false, false); // AtomS3初期設定(LCD,UART,I2C,LED)
  USBSerial.begin(9600);              // シリアル通信初期設定
  delay(1000);
  USBSerial.println("AtomS3 Wi-Fi softAP!");  // シリアル出力

  // 液晶初期設定
  M5.Lcd.fillScreen(0);       // 表示クリア
  M5.Lcd.setRotation(2);      // 画面向き設定(USB位置基準 0:上/ 1:左/ 2:下/ 3:右)
  M5.Lcd.setTextFont(4);      // フォント
  M5.Lcd.setTextColor(WHITE, BLACK);  // 文字色,背景色

  // 本体をアクセスポイントに設定
  StartAP();  // アクセスポイント開始関数呼び出し

  // サーバー設定
  server.on("/", handleRoot);         // ルートアクセス時の応答関数を設定
  server.on("/on/", relayOn);         // /onアクセス時の応答関数を設定
  server.on("/off/", relayOff);       // /offアクセス時の応答関数を設定
  server.onNotFound(handleNotFound);  // Webページが見つからない時の応答関数を設定
  server.begin();                     // Webサーバー開始

  // 出力設定
  pinMode(OUTPUT_PIN0, OUTPUT);   // 外部出力
  digitalWrite(OUTPUT_PIN0, LOW); // 出力初期化

  M5.Lcd.setTextFont(4);  // フォント変更
}

// メイン *********************************************************
void loop() {
  server.handleClient();  //クライアントからのアクセス確認
  delay(100); // 遅延時間
}

5.サンプルプログラム(子機:AtomS3 Lite)

子機の「AtomS3 Lite」のサンプルプログラムは以下のようになります。

※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。

#include <M5AtomS3.h>     // ヘッダーファイル準備(別途FastLEDライブラリもインストール)
#include <WiFi.h>
#include <HTTPClient.h>

HTTPClient http;  // HTTPクライアントを使用するための準備

// FastLEDライブラリでフルカラーLEDを使用する設定
CRGB dispColor(uint8_t r, uint8_t g, uint8_t b) {
  return (CRGB)((r << 8) | (g << 16) | b);
}
// 変数宣言
const char ssid[] = "ATOMS3-01";    // 接続先アクセスポイントのSSID
const char password[] = "11111111"; // 接続先アクセスポイントのパスワード
String ap_url = "192.168.4.1";      // POST先IPアドレス
bool state = false;   // 本体ボタン状態保持用

// POST処理関数 ***********************************************
String httpPost(String add_url) {
  String payload;                         // レスポンスデータ格納用
  http.begin("http://" + ap_url + add_url); // http通信を送信先アドレスを指定して開始
  int httpCode = http.POST("");           // 指定したアドレスへPOST実行(送信データがあればここで指定)
  if (httpCode == HTTP_CODE_OK) {         // httpコードが200なら通信成功
    payload = http.getString();           // レスポンスデータを取得
    USBSerial.printf("payload: %S\n", payload.c_str()); // レスポンスデータ表示
  } else {                                // httpコードが200以外なら(通信失敗)
    USBSerial.println("[POST]failed to send to server!!");  // エラー表示
  }
  http.end(); // http通信終了

  return payload; // レスポンスデータを返す
}

// 初期設定 -------------------------------------------------
void setup() {
  M5.begin(false, true, false, true); // 初期化(液晶, USBシリアル, I2C[38,39], LED)
  USBSerial.begin(9600);              // USBシリアル通信初期化

  // Wi-Fi接続
  WiFi.begin(ssid, password);             // アクセスポイントへの接続開始
  USBSerial.println("AP Search!");
  while (WiFi.status() != WL_CONNECTED) { // 接続完了まで待機
    delay(1000);
  }
  USBSerial.println("Connected to AP");
  USBSerial.printf("Destination SSID= %S\n", ssid);     // 接続先SSID
  USBSerial.printf("Destination PASS= %S\n", password); // 接続先パスワード
  USBSerial.print("IP= ");
  USBSerial.println(WiFi.localIP());  // 自分のIPアドレス

  M5.dis.drawpix(dispColor(50, 50, 50));  // 本体LED色指定
}

// メイン ---------------------------------------------------
void loop() {
  M5.update();  // ボタン状態初期化
  // 本体ボタン処理
  if (M5.Btn.wasPressed()) {  // ボタンが押されていれば
    state = !state;           // ボタン状態反転
    String payload;           // レスポンスデータ格納用
    // リレーON指令処理
    if (state == true) {      // ボタン状態がtrueなら
      USBSerial.println("POST Relay ON");
      payload = httpPost("/on/");               // ポスト送信を実行しレスポンスを取得
      if (payload == "200 Relay ON!") {         // レスポンスデータが一致すれば
        M5.dis.drawpix(dispColor(0, 100, 200)); // 本体LED色指定(青)
      } else {                                  // 一致しなければエラー
        M5.dis.drawpix(dispColor(200, 0, 0));   // 本体LED色指定(赤)
      }
    }
    // リレーOFF指令処理
    if (state == false) {     // ボタン状態がfalseなら
      USBSerial.println("POST Relay OFF");
      payload = httpPost("/off/");              // ポスト送信を実行しレスポンスを取得
      if (payload == "200 Relay OFF!") {        // レスポンスデータが一致すれば
        M5.dis.drawpix(dispColor(200, 100, 0)); // 本体LED色指定(オレンジ)
      } else {                                  // 一致しなければエラー
        M5.dis.drawpix(dispColor(200, 0, 0));   // 本体LED色指定(赤)
      }
    }
  }
  M5.dis.show();  // 本体フルカラーLED出力
  delay(100);     // 遅延時間
}

6.Wi-Fiアクセスポイント、サーバー設定プログラムの詳細

デバイスをWi-Fiアクセスポイントとして設定するには以下のように「SSID」と「パスワード」を設定して、初期設定の中で「WiFi.softAP(ssid_AP, pass_AP)」を実行するだけです。

// アクセスポイント設定
const char ssid_AP[] = "ATOMS3-01"; // SSID
const char pass_AP[] = "11111111";  // パスワード(8文字以上)

// 初期設定
void setup() {
  WiFi.softAP(ssid_AP, pass_AP);    // アクセスポイントとして設定
}

アクセスポイントに設定したデバイスのアドレスは初期値で「192.168.4.1」となります。
アドレスを変更するには以下のように指定します。

// アクセスポイントのアドレスを「192.168.4.3」にする場合は以下で指定
  IPAddress ip(192, 168, 4, 3);            // IPアドレスを指定
  IPAddress gateway(192, 168, 4, 1);       // ゲートウェイを指定
  IPAddress subnet(255, 255, 255, 0);      // サブネットマスクを指定
  WiFi.softAPConfig(ip, gateway, subnet);  // IPアドレスを設定

サーバーとして設定するプログラムを親機の「AtomS3」のサンプルプログラムから抜粋すると以下のようになります。

初期設定の中で「server.on(“接続先アドレス”, 実行関数)」を設定することで「接続先アドレス」にアクセスがあった時に実行される「実行関数」を設定します。

接続先アドレス」の「”/“」はルートアドレスでここでは「http://192.168.4.1/」を表します。

以下のサンプルプログラムの抜粋では「” /on/ “(http://192.168.4.1/on/)」にアクセスがあった場合は「relayON()」が実行され、「” /off/ “」にアクセスがあった場合は「relayOff()」が実行されます。

// ルート(IPアドレス)アクセス時の応答関数 -----------------------------------
void handleRoot() {
  server.send(200, "text/html", "200 Root Access!");  // レスポンス200(通信成功)を返す
  USBSerial.println("Access!");
  M5.Lcd.setCursor(5, 65);            // 表示開始位置左上角(X,Y)
  M5.Lcd.println("    Access!    ");  
}
// エラー(Webページが見つからない)時の応答関数
void handleNotFound() {
  server.send(404, "text/plain", "404 Not Found!"); // 404エラーを返す
}

// (IPアドレス)/on アクセス時の応答関数
void relayOn() {
  server.send(200, "text/html", "200 Relay ON!");   // レスポンス200を返す
  USBSerial.println("Relay ON");
  M5.Lcd.setCursor(5, 65);          // 表示開始位置左上角(X,Y)
  M5.Lcd.println("Relay ON   ");
  digitalWrite(OUTPUT_PIN0, HIGH);  // リレーON出力
}
// (IPアドレス)/off アクセス時の応答関数
void relayOff() {
  server.send(200, "text/html", "200 Relay OFF!");  //レスポンス200を返す
  USBSerial.println("Relay OFF");
  M5.Lcd.setCursor(5, 65);          // 表示開始位置左上角(X,Y)
  M5.Lcd.println("Relay OFF");
  digitalWrite(OUTPUT_PIN0, LOW);   // リレーOFF出力
}

// 初期設定 -----------------------------------------------
void setup() { 
  server.on("/", handleRoot);         // ルートアクセス時の応答関数を設定
  server.on("/on/", relayOn);         // /onアクセス時の応答関数を設定
  server.on("/off/", relayOff);       // /offアクセス時の応答関数を設定
  server.onNotFound(handleNotFound);  // Webページが見つからない時の応答関数を設定
  server.begin();                     // Webサーバー開始
}

アクセスポイントに設定したサーバーにリクエストを送信するには、子機の「AtomS3-Lite」のサンプルプログラムから抜粋すると以下のようになります。

http.begin(“送信先アドレス”)」で送信先アドレスを指定して「http.POST(“”)」でリクエストを送信します。

http.begin("http://192.168.4.1/"); // http通信を送信先アドレスを指定して実行
http.POST("");  // 指定したアドレスへPOST実行(送信データがあれば「""」の代わりにデータを指定)


アクセスポイントに設定したアドレスへのリクエストだけでなく、何かデータを送信する場合には以下の例のように「http.POST(“”)」の「“”」の代わりにデータを指定します。

// データ送信例
String data = "key1=value1&key2=value2"; // 送信するデータ
http.begin("http://192.168.4.1/");
http.addHeader("Content-Type", "application/x-www-form-urlencoded"); // データ形式を指定
int httpResponseCode = http.POST(data);

Wi-Fiアクセスポイントの設定方法については、以下のリンクで詳しく紹介しています。

WiFi(アクセスポイント、サーバー)で近距離遠隔操作する方法(Arduinoプログラミング)
「ATOM LITE」を例にWiFiアクセスポイントに設定して、スマホ等から近距離遠隔操作を行う方法を紹介します。サーバーのリクエスト(要求)に対してレスポンス(応答)を返すという動作を利用して、簡単なプログラムで遠隔操作が実現できます。

Wi-Fiアクセスポインへの接続方法は、他のプログラムでもよく使用していますがアクセスポイントの「SSID」と「パスワード」を設定して、初期設定の中で「WiFi.begin(ssid, pass)」を実行するだけです。実行したら接続が完了するまで「whileループ」で待機します。

// Wi-Fi接続設定
const char ssid[] = "ATOMS3-01";    // 接続先アクセスポイントのSSID
const char password[] = "11111111"; // 接続先アクセスポイントのパスワード

// 初期設定
void setup() {
  WiFi.begin(ssid, password);             // アクセスポイントへの接続開始
  USBSerial.println("AP Search!");
  while (WiFi.status() != WL_CONNECTED) { // 接続完了まで待機
    delay(1000);
  }
}

Wi-Fiアクセスポインへの接続方法は、ローカル接続と同じで以下のリンクで詳しく紹介しています。

WiFi(ローカル接続、サーバー)で遠隔操作する方法(Arduinoプログラミング)
Wi-Fi通信でスマホから遠隔操作を行う方法を詳しく紹介。サーバーの仕組みを利用することで簡単にブラウザからの遠隔操作が実現できます。ATOM LITE使用

7.通信距離の確認

通信距離について、実際にどれくらい届くか確認してみました。
障害物のない直線距離では20〜30mは問題なく通信できそうでした。それ以上もいけましたが不安定です。

自宅で確認すると、家の構造にもよると思いますが、木造の家では隣の部屋や真上の部屋では問題なく通信できました。
隣の部屋の真上の部屋では、その部屋に入った途端通信できなくなりました。

直線距離で障害物がなければ、20〜30mの通信ができそうです。
壁等の障害物があると通信距離はかなり短くなるようでした。

8.おまけ:ChatGPTが動作確認用Webアプリを書いてくれた

今回制作したものをパソコン等のブラウザからリレーのON/OFFを行うためのWebアプリのプログラムを話題の「ChatGPT」に書いてもらいました。

まず、以下のように質問しました。
(今回使用したAIは無償の「ChatGPT-3 Text-davinci-003」です。

ブラウザにボタンを2つ配置して、ONボタンを押したら「http://192.168.4.1/on/」へアクセス、OFFボタンを押したら「http://192.168.4.1/off/」へアクセスするコードを書いて

回答は以下のようになりました。

<!DOCTYPE html>
<html>
  <head>
    <title>ON/OFF buttons</title>
    <script>
      function turnOn() {
        var xhttp = new XMLHttpRequest();
        xhttp.open("GET", "http://192.168.4.1/on/", true);
        xhttp.send();
      }

      function turnOff() {
        var xhttp = new XMLHttpRequest();
        xhttp.open("GET", "http://192.168.4.1/off/", true);
        xhttp.send();
      }
    </script>
  </head>
  <body>
    <button onclick="turnOn()">ON</button>
    <button onclick="turnOff()">OFF</button>
  </body>
</html>

いつもなら「JavaScript」では「FetchAPI」を使うところですが、こっちの方がシンプルですね(汗)
次からは、コレ使いますw

このコードをメモ帳等に貼り付けてファイル名を「test.html」のように拡張子を「.html」にして保存してから開いてみましょう。
ブラウザで以下のようなページが表示されます。

AtomS3遠隔操作用Webアプリby ChatGPT

パソコンの「Wi-Fi接続」をアクセスポイントに設定した「AtomS3」に接続して「ON/OFF」ボタンを押してみましょう。(パスワードはサンプルプログラムで設定した「11111111」です。)
リレーがON/OFFするのが確認できると思います。

特にエラーもなく1回で動作するプログラムをChatGPTが書いてくれました。
最近はこれぐらいで驚くことも無くなってきましたがw
聞き方だけちゃんと指示してやれば、質問に対して正確な回答を返してくれます。
便利な時代になりましたね^^
ChatGPTは現状では自信満々に間違った回答をしてくることもあるので、最終的には自分でコードを微調整することも多いです。
「AtomS3」のような最新のデバイスは、まだ学習データが無いため、端子番号等の間違いが多く、自分で書いた方が早い印象です。

「ChatGPT」を使用した「Arduinoコマンド」によるプログラミングについては、以下のリンクでも詳しく紹介しています。

Arduinoプログラミング初心者必見!ChatGPTがもたらす新しい可能性
ChatGPTがプログラミングの考え方を変えました「こんなプログラムを書いて」と聞けばコード作成から説明、エラーの指摘までしてくれる。ChatGPTがもたらす新しい可能性を探ってみたいと思います。

9 .まとめ

Wi-Fiアクセスポイント機能を使用した近距離遠隔操作の方法を詳しく紹介しました。

近距離の遠隔操作にはBluetooth通信が便利ですが、Bluetooth通信機能のないデバイスでWi-Fi機能がある場合はWi-Fiアクセスポイントに設定して使うことで簡単に遠隔操作ができます。

アクセスポイントに設定したデバイスへは複数のデバイスからアクセスすることができますが残念ながら直接双方向通信することはできません。

しかし、定期的にアクセスポイントへリクエストを送り、アクセスポイントの状態をレスポンスとして確認することで擬似的に双方向通信のような動作をすることもできます。

これについてはサーバーについての理解が必要です。
この方法については、サーバーの動作と合わせて以下のリンクで詳しく紹介しています。

WiFi遠隔操作Arduinoコマンドでブラウザベースのスマホ、PCリモートコントローラの紹介
ブラウザベースで遠隔操作、リアルタイムデータ通信を行う方法をコピペ用サンプルプログラムを使って紹介します。 サーバー機能を利用して「JavaScript」の「fetch」を使うことでデータの送受信を行います。

コメント

タイトルとURLをコピーしました