Fab Academy 2026 — Week 14

Interface
and Application Programming

A browser-based control interface for an ESP32-C3 servo motor system. The application allows the user to control motor position wirelessly using buttons served directly from the microcontroller.

Group assignment documentation
01 / intro

Introduction

The focus of Week 14 was Interface and Application Programming. For this assignment, I created a simple web-based user interface to control a physical output device. Instead of using a separate desktop or mobile application, the interface is hosted directly on the Seeed Studio XIAO ESP32-C3.

The ESP32-C3 connects to WiFi and works as a small web server. When the user opens the board IP address in a browser, a control page appears. From this page, the user can move a servo motor to fixed angles or enable an automatic sweep mode.

02 / objective

Assignment Objective

My objective was to build an interface that connects software interaction with physical hardware behavior. The interface should be simple, accessible from a browser, and able to send commands to the microcontroller without extra software installation.

In this work, the browser acts as the user interface, the ESP32-C3 acts as the application server, and the servo motor acts as the physical output controlled by the application.

03 / hardware

Hardware Used

FIG. 01 — Seeed Studio XIAO ESP32-C3 used as web server and controller

I used the Seeed Studio XIAO ESP32-C3 because it has built-in WiFi, a small form factor, and can be programmed using the Arduino IDE. This makes it suitable for creating small embedded web applications.

FIG. 02 — Servo motor used as the controlled physical device

The servo motor was selected as the output device because its movement can be easily observed. This makes it useful for testing whether the interface command is correctly received and translated into physical motion.

04 / interface

Interface Design

The application interface was designed as a simple web page with buttons for motor control. Each button sends a different HTTP request to the ESP32-C3. Based on the received request, the microcontroller changes the servo position.

The interface contains control options for:

Interface Button Request Action
/0Move servo to 0 degrees
90°/90Move servo to 90 degrees
180°/180Move servo to 180 degrees
Loop ON/loop_onStart automatic sweeping
Loop OFF/loop_offStop automatic sweeping

This structure helped me understand how a user interface can communicate with embedded hardware using simple web requests.

05 / wiring

Wiring

FIG. 03 — Wiring between ESP32-C3 and servo motor
Servo Wire Connection Function
RedVCCPower supply
BrownGNDCommon ground
YellowGPIO 8PWM control signal

GPIO 8 was used as the PWM signal pin for controlling the servo motor. The ESP32-C3 receives commands from the web interface and converts them into servo movement.

06 / application code

Application Code

The code combines three parts: WiFi connection, web server creation, and servo control. The ESP32-C3 listens for HTTP requests from the browser and performs the corresponding servo action.

Arduino / ESP32 Web Interface
#include <WiFi.h>
#include <ESP32Servo.h>

const char* ssid = "YOUR_WIFI_NAME";
const char* password = "YOUR_PASSWORD";

WiFiServer server(80);

Servo myservo;
int servoPin = 8;

bool loopMode = false;
int pos = 0;
bool forward = true;

void setup() {
  Serial.begin(115200);

  ESP32PWM::allocateTimer(0);
  myservo.setPeriodHertz(50);
  myservo.attach(servoPin, 1000, 2000);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.print("Connected. IP address: ");
  Serial.println(WiFi.localIP());

  server.begin();
}

void loop() {
  WiFiClient client = server.available();

  if (client) {
    String request = client.readStringUntil('\r');
    client.flush();

    if (request.indexOf("/0") != -1) {
      loopMode = false;
      myservo.write(0);
    }

    if (request.indexOf("/90") != -1) {
      loopMode = false;
      myservo.write(90);
    }

    if (request.indexOf("/180") != -1) {
      loopMode = false;
      myservo.write(180);
    }

    if (request.indexOf("/loop_on") != -1) {
      loopMode = true;
    }

    if (request.indexOf("/loop_off") != -1) {
      loopMode = false;
    }

    client.println("HTTP/1.1 200 OK");
    client.println("Content-type:text/html");
    client.println();

    client.println("<!DOCTYPE html>");
    client.println("<html>");
    client.println("<head>");
    client.println("<title>ESP32 Servo Interface</title>");
    client.println("<style>");
    client.println("body{font-family:Arial;text-align:center;background:#f4f4f4;padding:40px;}");
    client.println("h1{color:#333;}");
    client.println("button{padding:15px 25px;margin:10px;font-size:18px;border:none;border-radius:8px;background:#2563eb;color:white;}");
    client.println("button:hover{background:#1d4ed8;}");
    client.println(".card{background:white;padding:30px;border-radius:12px;max-width:500px;margin:auto;box-shadow:0 4px 12px rgba(0,0,0,0.1);}");
    client.println("</style>");
    client.println("</head>");
    client.println("<body>");
    client.println("<div class='card'>");
    client.println("<h1>Servo Motor Interface</h1>");
    client.println("<p>Control the servo motor using the buttons below.</p>");
    client.println("<a href='/0'><button>0 Degree</button></a>");
    client.println("<a href='/90'><button>90 Degree</button></a>");
    client.println("<a href='/180'><button>180 Degree</button></a>");
    client.println("<br>");
    client.println("<a href='/loop_on'><button>Loop ON</button></a>");
    client.println("<a href='/loop_off'><button>Loop OFF</button></a>");
    client.println("</div>");
    client.println("</body>");
    client.println("</html>");

    client.stop();
  }

  if (loopMode) {
    myservo.write(pos);

    if (forward) {
      pos++;
      if (pos >= 180) forward = false;
    } else {
      pos--;
      if (pos <= 0) forward = true;
    }

    delay(15);
  }
}
07 / testing

Testing the Interface

After uploading the code, I opened the Serial Monitor to check the IP address assigned to the ESP32-C3. Then I entered this IP address in a web browser connected to the same WiFi network.

When the web page loaded, I tested each button. The servo responded to the commands, confirming that the browser interface was successfully communicating with the microcontroller application.

08 / results

Results

The web interface successfully controlled the servo motor. The buttons for 0°, 90°, and 180° moved the servo to the selected positions, and the loop mode created a continuous sweeping motion.

This assignment helped me understand how interface design, application programming, and embedded hardware control can be connected together in one system.

09 / video

Video Demonstration

Servo motor controlled through browser-based interface