Skip to content

Instantly share code, notes, and snippets.

@timcsy
Last active May 12, 2025 06:45
Show Gist options
  • Save timcsy/4206cc5c315f4beecc8bd4b562ffef35 to your computer and use it in GitHub Desktop.
Save timcsy/4206cc5c315f4beecc8bd4b562ffef35 to your computer and use it in GitHub Desktop.
#include <WiFi.h>
#include <WebServer.h>
#include <ESP32Servo.h>
// 請在此設定你的 WiFi 資訊
const char* ssid = "基地台名稱";
const char* password = "基地台密碼";
// 建立 WebServer 物件,監聽 80 埠
WebServer server(80);
// 定義伺服馬達接腳(依照你的接線調整)
const int servoPin1 = 0;
const int servoPin2 = 1;
const int servoPin3 = 2;
const int servoPin4 = 3;
// 建立四個伺服馬達物件
Servo servo1;
Servo servo2;
Servo servo3;
Servo servo4;
void setup() {
Serial.begin(115200);
Serial.println();
// 連接 WiFi,基地台無密碼
WiFi.begin(ssid);
// 連接 WiFi,基地台有密碼
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.print("WiFi connected! IP address: ");
Serial.println(WiFi.localIP());
// 連接伺服馬達,並預設設定為 90 度(安全起見)
servo1.attach(servoPin1);
servo2.attach(servoPin2);
servo3.attach(servoPin3);
servo4.attach(servoPin4);
servo1.write(90);
servo2.write(90);
servo3.write(90);
servo4.write(90);
// 設定 HTTP 路徑:
// 根目錄 "/" 傳回控制網頁
server.on("/", HTTP_GET, handleRoot);
// /servo?num=x&angle=y 來控制第 x 隻伺服馬達轉到 y 度
server.on("/servo", HTTP_GET, handleServo);
// 啟動 HTTP 伺服器
server.begin();
Serial.println("HTTP server started");
}
void loop() {
server.handleClient();
}
// 處理根目錄 "/" 請求,回傳 HTML 控制頁面
void handleRoot() {
String html = "<!DOCTYPE html><html><head><meta charset='UTF-8'><title>MeArm 控制</title>"
"<style>"
"body { font-family: Arial, sans-serif; background-color: #f0f0f0; text-align: center; }"
"h1 { color: #333; }"
".slider { width: 80%; }"
".servo-control { margin: 20px; }"
"</style>"
"</head><body>"
"<h1>MeArm v0.4 控制面板</h1>"
"<div class='servo-control'>"
"<label>Servo 1:</label>"
"<input type='range' min='0' max='180' value='90' class='slider' id='servo1' onchange='updateServo(1, this.value)'>"
"<span id='servo1Val'>90</span>"
"</div>"
"<div class='servo-control'>"
"<label>Servo 2:</label>"
"<input type='range' min='0' max='180' value='90' class='slider' id='servo2' onchange='updateServo(2, this.value)'>"
"<span id='servo2Val'>90</span>"
"</div>"
"<div class='servo-control'>"
"<label>Servo 3:</label>"
"<input type='range' min='0' max='180' value='90' class='slider' id='servo3' onchange='updateServo(3, this.value)'>"
"<span id='servo3Val'>90</span>"
"</div>"
"<div class='servo-control'>"
"<label>Servo 4:</label>"
"<input type='range' min='0' max='180' value='90' class='slider' id='servo4' onchange='updateServo(4, this.value)'>"
"<span id='servo4Val'>90</span>"
"</div>"
"<script>"
"function updateServo(servo, angle) {"
"document.getElementById('servo' + servo + 'Val').innerText = angle;"
"var xhr = new XMLHttpRequest();"
"xhr.open('GET', '/servo?num=' + servo + '&angle=' + angle, true);"
"xhr.send();"
"}"
"</script>"
"</body></html>";
server.send(200, "text/html", html);
}
// 處理 /servo 請求,根據參數控制指定伺服馬達
void handleServo() {
if (server.hasArg("num") && server.hasArg("angle")) {
int num = server.arg("num").toInt();
int angle = server.arg("angle").toInt();
// 限制角度範圍在 0 ~ 180 度
angle = constrain(angle, 0, 180);
switch (num) {
case 1:
servo1.write(angle);
break;
case 2:
servo2.write(angle);
break;
case 3:
servo3.write(angle);
break;
case 4:
servo4.write(angle);
break;
default:
break;
}
server.send(200, "text/plain", "OK");
} else {
server.send(400, "text/plain", "Missing parameters");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment