AtomS3は小型ながら液晶付きでWi-Fi通信までできて便利ですが、Bluetooth機能が無いのが残念・・・。
頻繁に使うものではないですが、近距離通信をするにはやっぱりBluetoothが便利です。
Wi-Fi機能はあるのでWi-Fi経由での遠隔操作はできますが、Wi-Fi環境のないところでも遠隔操作したい!
ということで、今回はWi-Fiアクセスポイント機能を使用した近距離遠隔操作の方法を詳しく紹介します。
動作確認用のWebアプリはChatGPTが書いてくれたので、これについても最後に紹介しています。
Arduinoコマンドを使用したアクセスポイントのプログラムについては、以下で詳しく紹介しています。
1.AtomS3/AtomS3 Liteとは
2.Wi-Fiアクセスポイントとは
3.全体の構成・動作紹介
4.サンプルプログラム(親機:AtomS3)
5.サンプルプログラム(子機:AtomS3 Lite)
6.Wi-Fiアクセスポイント、サーバー設定プログラムの詳細
7.通信距離の確認
8.おまけ:ChatGPTが動作確認用Webアプリを書いてくれた
9.まとめ
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」については、以下のリンクで詳しく紹介しています。
2.Wi-Fiアクセスポイントとは
Wi-Fiアクセスポイントとは、無線LAN(Wi-Fi)を使ってインターネットに接続するための機器です。
一般的には、有線のブロードバンド回線やルーターに接続し、無線でノートパソコンやスマートフォンなどの端末からインターネットに接続するために使用され、複数のアクセスポイントを設置して通信範囲を広げることも可能です。
3.全体の構成・動作紹介
全体の構成と動作については以下のようになります。
親機として「AtomS3」をアクセスポイントに設定して、子機の「AtomS3 Lite」からWi-Fi接続します。(子機は複数あっても同じ操作ができます。)
親機の「AtomS3」にはリレーユニットを接続してお好みの機器をON/OFFできるようにしてあります。子機の「AtomS3 Lite」の本体ボタンを押すごとに「AtomS3」に接続したリレーがON/OFFします。
下画像の左が子機の「AtomS3 Lite」で、真ん中が親機の「AtomS3」、右がGroveコネクタに接続できる「リレーユニット」です。
電源を入れると「AtomS3」はアクセスポイントとして起動し、「SSID、パスワード、IPアドレス」が表示されます。
「AtomS3 Lite」はアクセスポイントに接続するとLEDが白色に点灯します。
「AtomS3 Lite」の本体ボタンを押すとリレーがONし「AtomS3 Lite」のLEDが青色に点灯します。(通信エラーの場合は「AtomS3 Lite」のLEDが赤色に点灯します。)
もう一度「AtomS3 Lite」の本体ボタンを押すとリレーがOFFし「AtomS3 Lite」のLEDがオレンジ色に点灯します。(通信エラーの場合は「AtomS3 Lite」のLEDが赤色に点灯します。)
親機の「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(通信成功)を返す
Serial.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を返す
Serial.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を返す
Serial.println("Relay OFF");
M5.Lcd.setCursor(5, 65); // 表示開始位置左上角(X,Y)
M5.Lcd.println("Relay OFF");
digitalWrite(OUTPUT_PIN0, LOW); // リレーOFF出力
}
// 初期設定 **************************************************
void setup() {
auto cfg = M5.config(); // 本体初期設定
AtomS3.begin(cfg, true);
Serial.begin(9600); // USBシリアル通信初期化
delay(1000); // シリアル出力開始待ち
Serial.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 << 16) | (g << 8) | 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(); // レスポンスデータを取得
Serial.printf("payload: %S\n", payload.c_str()); // レスポンスデータ表示
} else { // httpコードが200以外なら(通信失敗)
Serial.println("[POST]failed to send to server!!"); // エラー表示
}
http.end(); // http通信終了
return payload; // レスポンスデータを返す
}
// 初期設定 -------------------------------------------------
void setup() {
auto cfg = M5.config(); // 本体初期設定
AtomS3.begin(cfg, true);
Serial.begin(9600); // USBシリアル通信初期化
// Wi-Fi接続
WiFi.begin(ssid, password); // アクセスポイントへの接続開始
Serial.println("AP Search!"); // シリアル通信出力
while (WiFi.status() != WL_CONNECTED) { // 接続完了まで待機
delay(1000);
}
Serial.println("Connected to AP");
Serial.printf("Destination SSID= %S\n", ssid); // 接続先SSID
Serial.printf("Destination PASS= %S\n", password); // 接続先パスワード
Serial.print("IP= ");
Serial.println(WiFi.localIP()); // 自分のIPアドレス
AtomS3.dis.drawpix(dispColor(50, 50, 50)); // 本体LED色指定
}
// メイン ---------------------------------------------------
void loop() {
M5.update(); // ボタン状態初期化
// 本体ボタン処理
if (M5.BtnA.wasPressed()) { // ボタンが押されていれば
state = !state; // ボタン状態反転
String payload; // レスポンスデータ格納用
// リレーON指令処理
if (state == true) { // ボタン状態がtrueなら
Serial.println("POST Relay ON");
payload = httpPost("/on/"); // ポスト送信を実行しレスポンスを取得
if (payload == "200 Relay ON!") { // レスポンスデータが一致すれば
AtomS3.dis.drawpix(dispColor(0, 100, 200)); // 本体LED色指定(青)
} else { // 一致しなければエラー
AtomS3.dis.drawpix(dispColor(200, 0, 0)); // 本体LED色指定(赤)
}
}
// リレーOFF指令処理
if (state == false) { // ボタン状態がfalseなら
Serial.println("POST Relay OFF");
payload = httpPost("/off/"); // ポスト送信を実行しレスポンスを取得
if (payload == "200 Relay OFF!") { // レスポンスデータが一致すれば
AtomS3.dis.drawpix(dispColor(200, 100, 0)); // 本体LED色指定(オレンジ)
} else { // 一致しなければエラー
AtomS3.dis.drawpix(dispColor(200, 0, 0)); // 本体LED色指定(赤)
}
}
}
AtomS3.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アクセスポイントの設定方法については、以下のリンクで詳しく紹介しています。
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アクセスポインへの接続方法は、ローカル接続と同じで以下のリンクで詳しく紹介しています。
7.通信距離の確認
通信距離について、実際にどれくらい届くか確認してみました。
障害物のない直線距離では20〜30mは問題なく通信できそうでした。それ以上もいけましたが不安定です。
自宅で確認すると、家の構造にもよると思いますが、木造の家では隣の部屋や真上の部屋では問題なく通信できました。
隣の部屋の真上の部屋では、その部屋に入った途端通信できなくなりました。
8.おまけ:ChatGPTが動作確認用Webアプリを書いてくれた
今回制作したものをパソコン等のブラウザからリレーのON/OFFを行うためのWebアプリのプログラムを話題の「ChatGPT」に書いてもらいました。
まず、以下のように質問しました。
(今回使用したAIは無償の「ChatGPT-3 Text-davinci-003」です。)
回答は以下のようになりました。
<!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」にして保存してから開いてみましょう。
ブラウザで以下のようなページが表示されます。
パソコンの「Wi-Fi接続」をアクセスポイントに設定した「AtomS3」に接続して「ON/OFF」ボタンを押してみましょう。(パスワードはサンプルプログラムで設定した「11111111」です。)
リレーがON/OFFするのが確認できると思います。
「ChatGPT」を使用した「Arduinoコマンド」によるプログラミングについては、以下のリンクでも詳しく紹介しています。
9 .まとめ
Wi-Fiアクセスポイント機能を使用した近距離遠隔操作の方法を詳しく紹介しました。
近距離の遠隔操作にはBluetooth通信が便利ですが、Bluetooth通信機能のないデバイスでWi-Fi機能がある場合はWi-Fiアクセスポイントに設定して使うことで簡単に遠隔操作ができます。
アクセスポイントに設定したデバイスへは複数のデバイスからアクセスすることができますが残念ながら直接双方向通信することはできません。
しかし、定期的にアクセスポイントへリクエストを送り、アクセスポイントの状態をレスポンスとして確認することで擬似的に双方向通信のような動作をすることもできます。
これについてはサーバーについての理解が必要です。
この方法については、サーバーの動作と合わせて以下のリンクで詳しく紹介しています。
コメント