14. Interface and Application¶
Overview¶
This week, I made a interface for controling my servos for my final project using an httml web interface on the esp32c3.
Group Work¶
This week me and my partner Andrew compared to interfacing softwares. I chose to look at MIT app. It was a simple program for making interfaces but I could see myself implementing my web server into it for a more semless controler.
Learing about interfaces¶
I have already had previous experience using the esp32 web servers since I had used one for a porject in school a few months prior. Heres a link to that experiance. Because of that, I was able to make an interface quickly for controlling a servo. I used my output board to test out my interface. I wanted to try out processing origanlly to try and learn something new but when I tried to download it this popped up:
Because of that I decided to make another web server on httml using the esp32c3 on my output board. Heres what the board looked like for refrence:
Heres what the interface looks like:
Code¶
#include <WiFi.h>
#include <ESP32Servo.h>
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";
Servo myServo;
const int servoPin = 3; // Servo on GPIO 3
WiFiServer server(80);
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.println("Connecting to WiFi...");
}
Serial.print("Connected. IP: ");
Serial.println(WiFi.localIP());
myServo.setPeriodHertz(50); // Standard 50Hz servo
myServo.attach(servoPin, 500, 2400); // Calibrate for your servo
myServo.write(90); // Start centered
server.begin();
}
void wagTail() {
for (int i = 0; i < 2; i++) {
myServo.write(60); // Move to one side
delay(200);
myServo.write(120); // Move to the other side
delay(200);
}
myServo.write(90); // Return to center
}
void loop() {
WiFiClient client = server.available();
if (client) {
String req = client.readStringUntil('\r');
client.flush();
if (req.indexOf("angle=") != -1) {
int angleIndex = req.indexOf("angle=") + 6;
int angle = req.substring(angleIndex).toInt();
angle = constrain(angle, 0, 180);
myServo.write(angle); // Move servo to mapped angle
}
if (req.indexOf("/wag") != -1) {
wagTail();
}
String html = R"rawliteral(
<html><head>
<style>
body { text-align: center; font-family: sans-serif; }
#joystick {
width: 200px; height: 200px;
border: 2px solid #555;
border-radius: 50%;
margin: 30px auto;
position: relative;
touch-action: none;
}
#stick {
width: 50px; height: 50px;
background: #2196F3;
border-radius: 50%;
position: absolute;
top: 75px; left: 75px;
touch-action: none;
cursor: pointer;
}
button {
padding: 10px 20px;
font-size: 16px;
margin-top: 20px;
}
</style>
</head><body>
<h2>ESP32-C3 Servo Joystick</h2>
<div id="joystick"><div id="stick"></div></div>
<button onclick="fetch('/wag')">🐶 Wag Tail</button>
<script>
const joystick = document.getElementById("joystick");
const stick = document.getElementById("stick");
const radius = 100;
const center = { x: radius, y: radius };
let dragging = false;
function updateStick(clientX, clientY) {
const rect = joystick.getBoundingClientRect();
const dx = clientX - rect.left - center.x;
const dy = clientY - rect.top - center.y;
const dist = Math.min(Math.sqrt(dx * dx + dy * dy), radius - 25);
const angleRad = Math.atan2(dy, dx);
const angle360 = (angleRad * 180 / Math.PI + 360) % 360;
const mapped = Math.round(angle360 / 2); // 360° → 180°
fetch("/?angle=" + mapped);
const x = center.x + dist * Math.cos(angleRad) - 25;
const y = center.y + dist * Math.sin(angleRad) - 25;
stick.style.left = `${x}px`;
stick.style.top = `${y}px`;
}
function resetStick() {
stick.style.left = "75px";
stick.style.top = "75px";
fetch("/?angle=90");
}
// Mouse
stick.addEventListener("mousedown", e => { dragging = true; e.preventDefault(); });
document.addEventListener("mousemove", e => { if (dragging) updateStick(e.clientX, e.clientY); });
document.addEventListener("mouseup", () => { if (dragging) { dragging = false; resetStick(); } });
// Touch
stick.addEventListener("touchstart", e => { dragging = true; e.preventDefault(); });
document.addEventListener("touchmove", e => { if (dragging) updateStick(e.touches[0].clientX, e.touches[0].clientY); });
document.addEventListener("touchend", () => { if (dragging) { dragging = false; resetStick(); } });
</script>
</body></html>
)rawliteral";
client.print("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n");
client.print(html);
client.stop();
}
}
Video¶
Test with Simple Code¶
Final Code Test¶
Reflection¶
This week was very easy for me. I didnt really have any trouble with setting up the interface. If time permits, I hope to make a better interface using the ESP RainMaker interface instead since it can be made much cleaner and polished but first I need to get the core concept of my final done.