Skip to content

14. Interface and Application Programming

Overview

This week, I focused on creating an interactive web-based interface to control a DC motor, building off of skills I developed earlier in the year. Since I had already learned how to create web interfaces and run local servers with the ESP32, I decided to expand on that knowledge by making a joystick-based controller.

I reused my custom board from Week 10, which was designed to control a DC motor using the L298N Mini motor driver. This time, I integrated it with a web interface hosted on an ESP32-C3, enabling wireless motor control over Wi-Fi.

Group Work

I worked with Noah Smith to complete our Group Work site. My job was to find the benefits of using a webserver and find any other important features for it.

Web Interface and UI Behavior

The user interface is a virtual joystick created in the browser using HTML and JavaScript. This joystick is a draggable knob inside a circle boundary. When the knob is moved, the browser registers the X and Y position values and sends them to the ESP32-C3 through a POST request.

UI Effects:

  • Moving the joystick up tells the motor to spin forward.
  • Moving it down commands the motor to go in reverse.
  • Letting go of the joystick sends a stop command, turning off the motor.

The joystick’s immediate responses is handled by JavaScript, which checks every 150 milliseconds whether the knob’s position has changed. If it has, the current X and Y values are sent through a POST request to the ESP.

Code Integration

The following code was uploaded to the ESP32-C3:

#include <Arduino.h>
#include <WiFi.h>
#include <ESPmDNS.h>

#define IN1_PIN 2
#define IN2_PIN 3

const char* ssid = "EngineeringStudent";
const char* password = "cls2024!";
const char* hostname = "maestro";

WiFiServer server(80);

int leftVal = 0;
int upVal = 0;

const char index_html[] PROGMEM = R"rawliteral(
// [HTML/JavaScript from previous section]
)rawliteral";

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

  pinMode(IN1_PIN, OUTPUT);
  pinMode(IN2_PIN, OUTPUT);
  digitalWrite(IN1_PIN, LOW);
  digitalWrite(IN2_PIN, LOW);

  WiFi.begin(ssid, password);
  Serial.print("Connecting");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500); Serial.print(".");
  }
  Serial.println("\nWiFi connected. IP: " + WiFi.localIP().toString());

  if (!MDNS.begin(hostname)) Serial.println("mDNS failed.");
  else Serial.println("mDNS responder started.");

  server.begin();
}

void handleGet(WiFiClient& client) {
  client.print("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n");
  client.print(index_html);
}

void handlePost(WiFiClient& client, String request) {
  String body = "";
  while (client.available()) body += char(client.read());

  int lIndex = body.indexOf("left=");
  int uIndex = body.indexOf("up=");

  if (lIndex != -1) {
    int amp = body.indexOf('&', lIndex);
    leftVal = body.substring(lIndex + 5, amp == -1 ? body.length() : amp).toInt();
  }
  if (uIndex != -1) {
    int amp = body.indexOf('&', uIndex);
    upVal = body.substring(uIndex + 3, amp == -1 ? body.length() : amp).toInt();
  }

  Serial.printf("Joystick - Left: %d | Up: %d\n", leftVal, upVal);

  if (upVal > 2) {
    digitalWrite(IN1_PIN, HIGH);
    digitalWrite(IN2_PIN, LOW); // motor forward
  } else if (upVal < -2) {
    digitalWrite(IN1_PIN, LOW);
    digitalWrite(IN2_PIN, HIGH); // motor backward
  } else {
    digitalWrite(IN1_PIN, LOW);
    digitalWrite(IN2_PIN, LOW); // motor stop
  }

  client.print("HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n");
}

void loop() {
  WiFiClient client = server.available();
  if (client) {
    String req = "";
    while (client.connected() && client.available()) {
      char c = client.read();
      req += c;
      if (req.endsWith("\r\n\r\n")) break;
    }

    if (req.startsWith("GET /")) handleGet(client);
    else if (req.startsWith("POST /")) handlePost(client, req);

    delay(10);
  }
}

Reflection

This project helped me connect web development with physical hardware control, making the motor respond directly to joystick input. I improved my skills in parsing HTTP POST requests and managing fast data communication over Wi-Fi. Debugging the interface clarified how important timing and input handling are for smooth operation. I was really excited when the motor moved for the very first time off of the web interface. It really felt like magic to be honest.


Last update: June 3, 2025