Skip to content

15 Interface and application programming

Assignment

  • Group assignment:
    • Compare as many tool options as possible.
    • Document your work on the group work page and reflect on your individual page what you learned.
  • Individual assignment:
    • Write an application for the embedded board that you made that interfaces a user with an input and/or output device(s).

Overview

This week I further integrated my earlier networking and output-device experiments into a browser-based LED control interface. The system consisted of three parts: the board-side firmware running on XIAO ESP32-C3, a local webpage served through Python, and a browser UI built with HTML / CSS / JavaScript. Together, they formed a complete path from webpage interaction to physical LED response.

The goal of this week was not simply to make a webpage, but to build a usable interaction layer for my final project. Compared with testing light behavior only from the embedded side, a browser interface is easier to extend and closer to how a real user would interact with the system.

During this process, I also clarified the role of each tool more clearly: VS Code was used to edit files locally, Codex helped generate and revise UI code, Arduino IDE was used to upload the firmware, Python only launched the local webpage, and the actual interface still ran in the browser through HTML / CSS / JavaScript. After that, the browser communicated with the board through its IP address to control the LED output.

Group Assignment

For the group assignment, we compared different interface options for connecting a user interface with an embedded system.

Interface Option Tools / Method Advantages Limitations
Serial Monitor Arduino Serial Monitor Simple and reliable for debugging Not suitable as a user-facing interface
Python Script Python + serial communication Useful for local testing and data reading Still more like a development tool than a final interface
Browser Interface HTML / CSS / JavaScript + HTTP API Easy to open, no app installation, works well for quick UI testing Needs Wi-Fi connection and correct CORS handling
WebSocket Interface Browser + WebSocket server Better for real-time interaction More complex than simple HTTP requests
Mobile App App-based control through Bluetooth or Wi-Fi More product-like and portable Higher development cost and more setup
HMI / Screen Interface Dedicated screen module Self-contained and does not need a computer Requires extra hardware and has less flexibility

From this comparison, I decided to use a browser-based interface with HTTP API for my individual assignment.

This was the most suitable option for my current stage because I needed a fast and flexible way to test the LED behavior. The browser interface allowed me to control the ESP32-C3 without building a full mobile app. It also helped me see the relationship between the webpage, HTTP requests, the board IP address, and the physical LED output.

The group comparison also helped me understand that different interface tools are useful at different stages. Serial Monitor and Python are good for debugging, but they are not real user interfaces. A mobile app or HMI screen may be better for a finished product, but for this week and my final project prototype, the browser interface was the most practical choice.

Individual assignment

Browser-Based LED Control Interface

This interface was not a standalone mini exercise, but part of the user interaction layer in my final project. The goal was to let the user control the lighting system directly from a browser instead of changing parameters only in code.

From the project perspective, this week completed the first integration of the UI layer + communication layer + output layer. Although the interface is still a prototype, the core interaction logic is already in place.

System Structure

1. Browser UI2. Local webpage3. Board connected to AP / Wi-Fi4. HTTP API on ESP32-C35. WS2812 LED strip

Figure 1. Browser interface, local webpage, network connection, and LED output working as one control flow.

Bill of Materials (BOM)

No. Component Qty Function
XIAO ESP32-C3 1 Main controller board
WS2812 LED strip 1 Visual output
USB cable 1 Power and upload
2.4 GHz AP / Wi-Fi 1 Network access for board communication
Computer with browser 1 Run the UI
Local Python server 1 Serve the webpage

Wiring / Electronics

  • WS2812 data pin → D1 / GPIO3
  • LED strip power → 5V
  • LED strip GND → board GND
  • LED count in code → 30

⚠️ Caution:

  • The board and LED strip must share the same ground.
  • The LED count must match the real strip length.
  • This project uses 2.4 GHz AP / Wi-Fi.

Network Setup: AP and Wi-Fi Connection

Besides the interface itself, network connection was also a core part of this week. The browser did not control the LED strip directly. Instead, it reached the board through the HTTP API provided over the local network.

The connection logic was:

  • the board first connected to the local AP / Wi-Fi
  • the serial monitor returned the board IP address
  • after the local webpage started, I entered this address in the browser
  • the browser sent requests to the board through that address
  • the board received the requests and updated the LED output

So the AP / Wi-Fi was not an extra detail, but the communication foundation between the webpage and the embedded board. Without joining the network and receiving a valid address, the UI could not continue to the control stage.

week1501.jpg

Summary: The board had to connect to the local AP / Wi-Fi and return a valid IP address before the browser UI could communicate with it.

File:

full ino download link

Development Workflow and Tool Roles

This week involved two different layers: development tools and the runtime system.

Development tools

  • VS Code: local editing and file management
  • Codex: assistance with generating and revising UI code
  • Arduino IDE: uploading firmware to the ESP32-C3

Runtime system

  • server.py: launches the local webpage service
  • index.html: the actual browser-side UI
  • Board firmware: handles AP / Wi-Fi, API, and LED control
  • Board IP: the address used by the browser to send requests

So the real workflow of this week was:

1. Use VS Code / Codex to build UI2. Upload firmware with Arduino IDE3. Connect the board to AP / Wi-Fi4. Get the board IP5. Start server.py6. Open index.html in browser7. Enter board address8. Control LED through browser

Summary: VS Code and Codex were development tools, Python only served the webpage, HTML / CSS / JavaScript formed the actual browser UI, and the ESP32-C3 firmware handled AP / Wi-Fi connection, API communication, and LED control.

Interface Design

The current webpage was divided into two areas:

  • tutorial / instruction area
  • control area

The control area currently included:

  • Base URL input
  • Check State
  • ON / OFF / TOGGLE
  • Brightness slider
  • Color buttons
  • Scene switching
  • Breath Rate / Breath Depth

This structure worked well for development because it let me test buttons, sliders, and API mapping step by step.

Software / Logic

The browser sent fetch() requests to the board-side HTTP API.

After completing the AP / Wi-Fi connection and getting its IP address, the board received those requests and updated LED brightness, color, and mode.

API Endpoints

/api/state
/api/on
/api/off
/api/toggle
/api/brightness
/api/color
/api/scene
/api/breath

Code Understanding & Key Logic

Instead of only copying example code, I tried to understand how the browser, HTTP server, and LED rendering logic worked together.

The system can be divided into four main layers:

Browser UI
↓
HTTP Requests
↓
ESP32-C3 API Server
↓
LED Rendering Logic

The browser sends requests, the ESP32-C3 parses the API route, updates internal variables, and then refreshes the LED strip.


1. HTTP Route Handling

One important thing I learned was that the ESP32 does not automatically understand user actions.
The browser only sends an address such as /api/on or /api/brightness.

The firmware must manually bind each route to a function.

server.on("/api/on", HTTP_GET, handleOn);
server.on("/api/off", HTTP_GET, handleOff);
server.on("/api/brightness", HTTP_GET, handleBrightness);

2. Shared State Variables

Another key concept was "state". The LED strip behavior is controlled by variables stored inside the ESP32.

bool lightOn = false;
int brightnessValue = 100;
String colorName = "yellow";
String currentScene = "breathing";

The browser changes these values through API requests. Then the rendering function reads the current values and updates the LEDs. The webpage is not controlling LEDs directly.
It is modifying the internal state of the embedded system.


3. Non-blocking Animation Logic

At first, I used delay() inside the breathing animation. This caused the HTTP server to become unresponsive during animation playback. The browser could not update the LED state smoothly. I later changed the logic to use millis() timing.

if (millis() - lastAnimationFrameAt >= ANIMATION_FRAME_MS) {
    lastAnimationFrameAt = millis();
    renderLight();
}

This allowed the ESP32-C3 to continue processing network requests while animations were running.


4. Sine Wave Breathing Animation

The breathing effect is generated mathematically using the sin() function.

float wave = (sin(progress * TWO_PI) + 1.0f) * 0.5f;

The sine wave continuously moves between 0 and 1. That value is then multiplied by the brightness level. This creates a smooth breathing effect instead of sudden brightness jumps. I learned that animation behavior can be created through mathematical functions instead of hardcoded steps.


5. JSON Communication

The ESP32-C3 sends JSON data back to the browser after every request.

json += "\"brightness\":" + String(brightnessValue) + ",";
json += "\"scene\":\"" + currentScene + "\",";

The browser then updates the interface using the returned state. This helped me understand that the browser UI is acting like a "digital twin" of the hardware. The webpage is always trying to reflect the real embedded system state.


6. CORS Handling

During testing, the ESP32-C3 received the browser request, but the webpage still showed a network error. The problem was CORS. The local webpage and the ESP32-C3 IP address are treated as different origins by the browser. To solve this, I added CORS headers in the ESP32-C3 firmware.

server.sendHeader("Access-Control-Allow-Origin", "*");
server.sendHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
server.sendHeader("Access-Control-Allow-Headers", "*");

After adding these headers, the browser could read the JSON response from the ESP32-C3 correctly. This helped me understand that interface programming is not only about sending commands.
Browser security rules also affect whether the interface can communicate with the board.

What I Learned

  • HTTP requests can become a control layer for physical devices.
  • APIs separate the interface from the hardware logic.
  • State variables help the ESP32-C3 remember the current LED behavior.
  • millis() is more suitable than delay() for responsive systems.
  • JSON allows synchronization between browser and hardware.
  • CORS is necessary when a local webpage communicates with an ESP32 IP address.
  • Mathematical functions like sin() can generate natural animation behavior.

AI-Assisted Development

During the browser UI development, I used Codex to help generate and organize the interface code. The AI-supported part mainly included page structure, control layout, and the basic frontend logic for calling the API.

Before asking Codex to generate the UI, I first provided the actual system constraints, including hardware, software, network connection method, and required functions.

Hardware / Software / Language Context Given to Codex

Category Details
Hardware XIAO ESP32-C3, WS2812, LED count = 30, data pin = D1 / GPIO3, 5V, shared GND, 2.4 GHz AP / Wi-Fi
Embedded-side software Arduino IDE
UI-side software Local webpage served by Python
Languages / Technologies HTML, CSS, JavaScript, fetch(), HTTP API
Functions required ON / OFF / TOGGLE, brightness, color, scene, breathing mode, state checking

Example Prompts Given to AI

I used AI mainly to generate the first version of the local webpage interface and to debug the browser-to-board communication problem. I gave the AI the real hardware setup and the API routes first, instead of asking it to design a generic webpage.

Create a clean local web interface for an ESP32-C3 LED controller. The page should use plain HTML, CSS, and JavaScript, and send HTTP GET requests to /api/on, /api/off, /api/toggle, /api/brightness, /api/color, /api/scene, /api/breath, and /api/state. The hardware is a XIAO ESP32-C3 controlling a 30-LED WS2812 strip through D1 / GPIO3. The interface should include a base URL input, ON/OFF buttons, brightness slider, color buttons, breathing mode controls, and a status panel.

What Codex Helped With

  • Building the initial UI structure
  • Organizing buttons, sliders, and input layout
  • Mapping frontend controls to /api/...
  • Speeding up the HTML / CSS / JavaScript prototype

week1502.jpg

What I Defined and Verified Myself

  • Provided the real hardware platform and wiring conditions
  • Uploaded the board firmware and completed AP / Wi-Fi connection
  • Retrieved the board communication address
  • Started the local webpage and tested the interaction flow
  • Verified that the webpage actually controlled the physical LED strip
  • Corrected the LED count and the embedded-side breathing logic

Summary: Codex accelerated the UI prototyping process, but the final result still depended on hardware setup, AP / Wi-Fi connection, API integration, and real-device testing completed by myself.

Testing

1. AP / Wi-Fi Connection Test

I first checked whether the board could connect to the local AP / Wi-Fi and return an IP address.

The board connected reliably to 2.4 GHz and returned a usable address for browser access; 5 GHz did not work.

2. Local Webpage Test

After starting server.py, I opened the local webpage in the browser and checked whether the interface loaded correctly.

The local webpage launched correctly and worked as the browser-side control interface.

3. Browser-to-Board Communication Test

I entered the board address in the webpage and tested whether buttons and sliders could trigger the board API correctly.

ON, OFF, brightness, and color control could already be executed through the browser.

4. LED Output Test

After changing the LED count from 12 to the actual 30, I tested the whole strip again.

After correcting the parameter, the full LED strip responded properly.

5. Breathing Mode Test

At first, breathing mode only changed the webpage state, so I later added the embedded-side logic.

Breathing mode can now be synchronized to the physical LED output.

Problems & Solutions

Problem Solution
The board could not connect to 5 GHz Wi-Fi I switched to 2.4 GHz AP / Wi-Fi.
The browser showed a network error I added CORS headers in the ESP32-C3 firmware.
Only part of the LED strip responded I changed NUM_LEDS to 30.
Breathing mode only changed the webpage state at first I added breathing animation logic on the ESP32-C3 side.
The workflow was easy to confuse I separated the development tools from the runtime system.

Reflection

This week I tested a browser-based interface for controlling the ESP32-C3 and LED strip.

AI and Codex helped me quickly generate a visually clean webpage, which was useful for early testing. I could focus on checking whether the buttons, sliders, API routes, and LED output worked.

At the same time, I noticed that the generated webpage code became quite large. It worked for this stage, but it may be difficult to maintain if I keep adding more functions directly.

For the next version, I need to simplify the structure and separate the main parts more clearly: API communication, UI controls, state display, and final project behavior.

This test gave me a working browser-to-hardware control layer. Next, I can connect it with the pressure sensor input and the 24V COB LED strip system.