Skip to content

14-Interface and Application Programming

Assignments

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)

Learning outcomes

Implement a User Interface (UI) using programming and explore protocols to communicate with a microcontroller board that you designed and made.

Have you answered these questions?

Linked to the group assignment page. Documented your process. Explained the UI that you made and how you did it. Explained how your application communicates with your embedded microcontroller board. Explained any problems you encountered and how you fixed them. Included original source code (or a screenshot of the app code if that’s not possible). Included a ‘hero shot’ of your application running & communicating with your board.

The road map i made for this week can be accesed here

Group Assignment

You can access our group assignment here

Reflection

This week’s group assignment gave me a clearer understanding of how a microcontroller can interact with a user through different interfaces. We looked at both the Arduino Serial Monitor and Tkinter, and seeing them side by side helped me understand how each one operates in its own way. They each come with their own advantages and limitations, and comparing them made it easier for me to decide which tool would be more suitable for future projects.

Individual Assignment

The goal of this assignment is to create a simple user interface that allows a user to interact with a custom microcontroller board. In this project, an ultrasonic distance sensor (HC-SR04) is connected to my custom PCB, and the measured distance is displayed in real time through a web-based interface hosted directly on the microcontroller.

Instead of using the Serial Monitor as the primary interface, this project implements a lightweight web server UI that can be accessed through a standard web browser. This approach provides an intuitive and platform-independent interface while clearly demonstrating how the board communicates with a user interface using Wi-Fi and HTTP, without the need for external software or applications.

For this project, I implemented a web-based user interface hosted directly on the microcontroller. The interface communicates with an ultrasonic distance sensor (HC-SR04) and displays:

  • Live distance readings
  • A continuously updated distance log
  • A control button to clear the log

The web interface is accessed through a browser using the board’s IP address, allowing interaction without additional software.

PCB Used in This Assignment

The PCB used in this assignment was designed and fabricated during a previous electronics assignment.

You can find the full PCB design and fabrication documentation here

The board includes:

Microcontroller

UART communication pins

Power regulation suitable for sensor interfacing

Electronics & Components Used

Component Description
Custom PCB Microcontroller board designed for Fab Academy projects
HC-SR04 Ultrasonic distance sensor
Jumper Wires For connections
Breadboard (optional) For easy wiring during testing

Wiring Diagram

Connections:

HC-SR04 Pin PCB Pin
VCC 5V
GND GND
Trig D6
Echo D5

Optional LED:

LED Pin PCB Pin
Anode D4
Cathode GND

Code

Prompt for chatgpt - write a code for me to create a webserver with UI which programs my Xiao board, with a Wi-Fi antenna, and my ultrasonicsensor. The webserver should be able to create a log which displays the distance traked by the ultrasonic . (does this even implements UI though?) the hardware is d5 for echo d6 for trig

#include <WiFi.h>
#include <WebServer.h>

// -------- WiFi credentials --------
const char* ssid = "vivo V40";
const char* password = "tc140140";

// -------- Ultrasonic pins --------
const int trigPin = 6;   // D6
const int echoPin = 5;   // D5

// -------- Web server --------
WebServer server(80);

// -------- Distance logging --------
String distanceLog = "";
unsigned long lastMeasure = 0;
const unsigned long interval = 2000; // 2 seconds

// -------- Ultrasonic distance function --------
long getDistance() {
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  long duration = pulseIn(echoPin, HIGH, 30000); // timeout 30ms
  if (duration == 0) return -1; // no echo
  return duration * 0.034 / 2; // cm
}

// -------- Web UI --------
String webPage() {
  return R"rawliteral(
<!DOCTYPE html>
<html>
<head>
  <title>XIAO Ultrasonic Logger</title>
  <style>
    body {
      font-family: Arial;
      background: #0f0f0f;
      color: #f0f0f0;
      text-align: center;
    }
    h1 { color: #00ffcc; }
    #distance {
      font-size: 2.2em;
      margin: 20px;
    }
    textarea {
      width: 90%;
      height: 200px;
      background: #111;
      color: #00ff66;
      border: 1px solid #333;
    }
    button {
      margin-top: 10px;
      padding: 10px 20px;
      font-size: 1em;
    }
  </style>
  <script>
    setInterval(() => {
      fetch("/distance")
        .then(res => res.text())
        .then(d => {
          document.getElementById("distance").innerHTML = d + " cm";
        });

      fetch("/log")
        .then(res => res.text())
        .then(l => {
          document.getElementById("log").value = l;
        });
    }, 2000);

    function clearLog() {
      fetch("/clear");
      document.getElementById("log").value = "";
    }
  </script>
</head>
<body>
  <h1>Ultrasonic Distance Tracker</h1>
  <div id="distance">-- cm</div>
  <h3>Distance Log</h3>
  <textarea id="log" readonly></textarea><br>
  <button onclick="clearLog()">Clear Log</button>
</body>
</html>
)rawliteral";
}

// -------- Web handlers --------
void handleRoot() {
  server.send(200, "text/html", webPage());
}

void handleDistance() {
  long d = getDistance();
  if (d < 0) server.send(200, "text/plain", "No echo");
  else server.send(200, "text/plain", String(d));
}

void handleLog() {
  server.send(200, "text/plain", distanceLog);
}

void handleClear() {
  distanceLog = "";
  server.send(200, "text/plain", "Cleared");
}

// -------- Setup --------
void setup() {
  Serial.begin(115200);
  delay(1000);

  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);

  Serial.println("Connecting to WiFi (hidden SSID mode)...");

  WiFi.mode(WIFI_STA);
  WiFi.disconnect(true);
  delay(200);

  // Hidden SSID connection
  WiFi.begin(ssid, password, 0, NULL, true);

  unsigned long startTime = millis();
  while (WiFi.status() != WL_CONNECTED &&
         millis() - startTime < 20000) {
    Serial.print(".");
    delay(500);
  }

  Serial.println();

  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("WiFi connected");
    Serial.print("IP Address: ");
    Serial.println(WiFi.localIP());
  } else {
    Serial.println("WiFi failed. Check hotspot.");
    return;
  }

  server.on("/", handleRoot);
  server.on("/distance", handleDistance);
  server.on("/log", handleLog);
  server.on("/clear", handleClear);

  server.begin();
  Serial.println("Web server started");
}

// -------- Loop --------
void loop() {
  server.handleClient();

  if (millis() - lastMeasure > interval) {
    long d = getDistance();
    if (d >= 0) {
      distanceLog += String(d) + " cm\n";
    }

    if (distanceLog.length() > 2000) {
      distanceLog = distanceLog.substring(1000);
    }

    lastMeasure = millis();
  }
}

Code explination

This code sets up an ESP32 (or compatible board like the XIAO ESP32) as a Wi-Fi–connected ultrasonic distance logger with a web interface. It measures distance using an ultrasonic sensor connected to the trig and echo pins every 2 seconds, logs the measurements in memory, and serves a webpage where users can see the current distance and a log of previous readings. The board connects to a hidden Wi-Fi network, runs a simple HTTP server, and provides endpoints to retrieve the current distance (/distance), the distance log (/log), and to clear the log (/clear). The loop continuously handles web requests while updating the distance log in the background.

The web interface is generated by the webPage() function, which returns a complete HTML page as a raw string. This page displays the current distance in a

with id distance and the full distance log in a read-only