【PlatformIO × Cline】Seeed Studio XIAO ESP32S3で始める!Wi-Fi経由のブラウザLED制御ハンズオン備忘録
はじめに
Seeed Studio XIAO ESP32S3を使って、Wi-Fi経由でスマートフォンのブラウザから内蔵LED(または外部ピン)をON/OFF制御するWebサーバーを構築しました。
今回は、VS Codeの拡張機能である PlatformIO と、AIコーディングアシスタントの Cline を活用して、効率的に開発を進めた手順を備忘録として残します。
1. 開発環境の構築
まずは、ESP32S3の開発を行えるようにVS CodeおよびPlatformIOの環境を整えます。
動作環境
-
マイコンボード: Seeed Studio XIAO ESP32S3 (
seeed_xiao_esp32s3) - IDE: Visual Studio Code
- フレームワーク: PlatformIO (Arduino)
- AI支援: Cline (Google Gemini API連携)
プロジェクトの初期設定 (platformio.ini)
PlatformIOでプロジェクトを作成し、platformio.ini に以下の設定を行います。
[env:seeed_xiao_esp32s3]
platform = espressif32
board = seeed_xiao_esp32s3
framework = arduino
monitor_speed = 115200
2. 実装コード (src/main.cpp)
Wi-Fiに接続し、ポート80で簡易的なHTTPサーバーを立ち上げるコードです。ブラウザからのアクセスに応じてLEDのピン出力を切り替え、操作画面(HTML)を返します。
/**
* @file main.cpp
* @brief Seeed Studio XIAO ESP32S3 Wi-Fi Web Server LED Controller
*/
#include <Arduino.h>
#include <WiFi.h>
#include <WebServer.h>
// Wi-FiのSSIDとパスワード
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";
// ポート80でHTTPサーバーを初期化
WebServer server(80);
// LEDピンの定義(内蔵LED、またはD0ピンなどに変更可能)
const int ledPin = LED_BUILTIN;
// スマホで見やすいスタイリッシュなHTML画面を生成する関数
String getHTML(bool ledState) {
String html = "<!DOCTYPE html>\n";
html += "<html lang=\"ja\">\n";
html += "<head>\n";
html += " <meta charset=\"UTF-8\">\n";
html += " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n";
html += " <title>XIAO ESP32S3 LED Control</title>\n";
html += " <style>\n";
html += " body { font-family: 'Helvetica Neue', Arial, sans-serif; background-color: #f4f7f6; color: #333; text-align: center; margin: 0; padding: 20px; }\n";
html += " .container { max-width: 400px; margin: 40px auto; background: #ffffff; padding: 30px; border-radius: 12px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); }\n";
html += " h1 { font-size: 22px; color: #2c3e50; margin-bottom: 20px; }\n";
html += " .status-box { font-size: 18px; margin: 20px 0; padding: 15px; border-radius: 8px; font-weight: bold; }\n";
html += " .on-status { background-color: #e8f8f5; color: #1abc9c; border: 1px solid #a3e4d7; }\n";
html += " .off-status { background-color: #fadbd8; color: #e74c3c; border: 1px solid #f5b7b1; }\n";
html += " .btn-group { display: flex; gap: 15px; margin-top: 25px; }\n";
html += " .btn { flex: 1; padding: 15px 0; font-size: 18px; font-weight: bold; text-decoration: none; border-radius: 8px; color: white; transition: 0.2s; box-shadow: 0 2px 5px rgba(0,0,0,0.15); }\n";
html += " .btn-on { background-color: #2ecc71; }\n";
html += " .btn-on:hover { background-color: #27ae60; }\n";
html += " .btn-off { background-color: #e74c3c; }\n";
html += " .btn-off:hover { background-color: #c0392b; }\n";
html += " .footer { margin-top: 30px; font-size: 12px; color: #95a5a6; }\n";
html += " </style>\n";
html += "</head>\n";
html += "<body>\n";
html += " <div class=\"container\">\n";
html += " <h1>XIAO ESP32S3 Web Control</h1>\n";
if (ledState) {
html += " <div class=\"status-box on-status\">LED 状態: ON (点灯)</div>\n";
} else {
html += " <div class=\"status-box off-status\">LED 状態: OFF (消灯)</div>\n";
}
html += " <div class=\"btn-group\">\n";
html += " <a href=\"/led/on\" class=\"btn btn-on\">ON</a>\n";
html += " <a href=\"/led/off\" class=\"btn btn-off\">OFF</a>\n";
html += " </div>\n";
html += " <div class=\"footer\">Seeed Studio XIAO ESP32S3 Web Server</div>\n";
html += " </div>\n";
html += "</body>\n";
html += "</html>\n";
return html;
}
// ルート("/")アクセス時のハンドラー
void handleRoot() {
bool ledState = (digitalRead(ledPin) == HIGH);
server.send(200, "text/html", getHTML(ledState));
}
// ONボタン押下時 ("/led/on") のハンドラー(※HIGH/LOWは必要に応じて反転)
void handleLedOn() {
digitalWrite(ledPin, HIGH);
Serial.println("Web操作: LEDをONにしました");
server.sendHeader("Location", "/");
server.send(303);
}
// OFFボタン押下時 ("/led/off") のハンドラー
void handleLedOff() {
digitalWrite(ledPin, LOW);
Serial.println("Web操作: LEDをOFFにしました");
server.sendHeader("Location", "/");
server.send(303);
}
void setup() {
Serial.begin(115200);
delay(1000);
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW);
Serial.println();
Serial.print("Wi-Fiに接続中: ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("Wi-Fi 接続成功!");
Serial.print("IPアドレス: http://");
Serial.println(WiFi.localIP());
server.on("/", handleRoot);
server.on("/led/on", handleLedOn);
server.on("/led/off", handleLedOff);
server.begin();
Serial.println("HTTPサーバーを起動しました。");
}
void loop() {
server.handleClient();
}
3. 実装・検証の流れとポイント
-
AI(Cline)を活用したコード生成
VS Code上でCline(Actモード)を使い、要件を伝えるだけでplatformio.iniやsrc/main.cppの雛形を自動生成・ファイル編集させました。 -
ボードへの書き込みとシリアル確認
PlatformIOの「Upload」でXIAO ESP32S3に書き込みを行い、シリアルモニター(115200bps)でIPアドレス(例:[http://192.168.11.11](http://192.168.11.11))を確認しました。 -
スマホからのアクセスと動作確認
マイコンと同じWi-Fiネットワークに接続したスマートフォン等のブラウザからIPアドレスを入力し、綺麗にデザインされたUIからLEDの点灯・消灯をリモート制御できることを確認しました。
おわりに
AIアシスタント(Cline)を組み合わせることで、ボイラープレートコードの記述や環境設定にかかる時間を大幅に短縮し、スムーズにIoTデバイスのWebサーバー実装を行うことができました。今後はセンサー値のグラフ化や外部ピンの制御などにも応用していきたいと思います。