Skip to content

Week 14 — Code Files


Project 1 — Gesture Monitor

Arduino Code (ESP32-C3)

#include <WiFi.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

const char* ssid     = "DGI";
const char* password = "dgi@2024!";

WiFiServer server(8080);
WiFiClient client;

const int FLEX_PIN = A0;
const int BTN_PIN  = D1;

void setup() {
  Serial.begin(115200);
  pinMode(BTN_PIN, INPUT_PULLUP);

  Wire.begin(D4, D5);
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println("OLED not found!");
    while (true);
  }

  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("Connecting WiFi...");
  display.display();

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

  Serial.println("\nWiFi Connected!");
  Serial.println(WiFi.localIP());

  display.clearDisplay();
  display.setCursor(0, 0);
  display.println("WiFi Connected!");
  display.println(WiFi.localIP());
  display.display();
  delay(2000);

  server.begin();
  Serial.println("Server started!");
}

void loop() {
  // Accept new client
  if (!client || !client.connected()) {
    client = server.available();
    if (client) Serial.println("Client connected!");
  }

  int flexValue = analogRead(FLEX_PIN);
  int btnState  = digitalRead(BTN_PIN);

  String gesture = "BENDING";
  if (flexValue > 2000) gesture = "OPEN";
  else if (flexValue < 1500) gesture = "CLOSED";

  // OLED
  display.clearDisplay();
  display.setTextSize(1);
  display.setCursor(0, 0);
  display.println("Flex Value:");
  display.setTextSize(2);
  display.setCursor(0, 12);
  display.println(flexValue);
  display.setTextSize(1);
  display.setCursor(0, 35);
  display.println("Gesture:");
  display.setTextSize(2);
  display.setCursor(0, 45);
  display.println(gesture);
  display.display();

  // Send data directly over TCP
  if (client && client.connected()) {
    client.println(gesture + "," + String(flexValue) + "," + String(btnState));
  }

  delay(100);
}

Python Tkinter App

import tkinter as tk
import socket
import threading

ESP32_IP = "172.16.20.205"
PORT = 8080

class GestureApp:
    def __init__(self, root):
        self.root = root
        root.title("Vision Voice - Gesture Monitor")
        root.geometry("400x300")
        root.configure(bg="#1e1e2e")

        tk.Label(root, text="Vision Voice", font=("Arial", 20, "bold"),
                 bg="#1e1e2e", fg="#cba6f7").pack(pady=10)

        self.gesture_label = tk.Label(root, text="Gesture: --",
                                       font=("Arial", 16), bg="#1e1e2e", fg="#a6e3a1")
        self.gesture_label.pack(pady=5)

        self.flex_label = tk.Label(root, text="Flex Value: --",
                                    font=("Arial", 14), bg="#1e1e2e", fg="#89dceb")
        self.flex_label.pack(pady=5)

        self.btn_label = tk.Label(root, text="Button: --",
                                   font=("Arial", 14), bg="#1e1e2e", fg="#f38ba8")
        self.btn_label.pack(pady=5)

        self.status_label = tk.Label(root, text="Connecting...",
                                      font=("Arial", 10), bg="#1e1e2e", fg="#6c7086")
        self.status_label.pack(pady=10)

        self.running = True
        threading.Thread(target=self.read_stream, daemon=True).start()

    def read_stream(self):
        while self.running:
            try:
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                sock.settimeout(5)
                sock.connect((ESP32_IP, PORT))
                self.root.after(0, lambda: self.status_label.config(
                    text="Connected ✓", fg="#a6e3a1"))

                buffer = ""
                while self.running:
                    data = sock.recv(128).decode("utf-8", errors="ignore")
                    if not data:
                        break
                    buffer += data
                    while "\n" in buffer:
                        line, buffer = buffer.split("\n", 1)
                        line = line.strip()
                        parts = line.split(",")
                        if len(parts) == 3:
                            gesture, flex, btn = parts
                            btn_text = "PRESSED" if btn.strip() == "0" else "OPEN"
                            self.root.after(0, self.update_ui, gesture, flex, btn_text)

                sock.close()

            except Exception as e:
                self.root.after(0, lambda: self.status_label.config(
                    text="Reconnecting...", fg="#f9e2af"))
                import time; time.sleep(2)

    def update_ui(self, gesture, flex, btn_text):
        self.gesture_label.config(text=f"Gesture: {gesture}")
        self.flex_label.config(text=f"Flex Value: {flex}")
        self.btn_label.config(text=f"Button: {btn_text}")
        self.status_label.config(text="Connected ✓", fg="#a6e3a1")

root = tk.Tk()
app = GestureApp(root)
root.mainloop()

Project 2 — Servo Controller

Arduino Code (ESP32-C3)

#include <WiFi.h>
#include <ESP32Servo.h>

const char* ssid     = "DGI";
const char* password = "dgi@2024!";

WiFiServer server(8888);
WiFiClient client;

Servo myServo;
const int SERVO_PIN = D0;

void setup() {
  Serial.begin(115200);
  myServo.attach(SERVO_PIN);
  myServo.write(90);

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

  Serial.println("\nWiFi Connected!");
  Serial.println(WiFi.localIP());
  server.begin();
}

void loop() {
  if (!client || !client.connected()) {
    client = server.available();
    if (client) Serial.println("Client connected!");
  }

  if (client && client.connected() && client.available()) {
    String line = client.readStringUntil('\n');
    line.trim();
    int degree = line.toInt();
    if (degree >= 0 && degree <= 180) {
      myServo.write(degree);
      Serial.println("Moving to: " + String(degree));
    }
  }
}

Python Tkinter App

import tkinter as tk
import socket
import threading

ESP32_IP = "172.16.20.205"
PORT = 8888

class ServoApp:
    def __init__(self, root):
        self.root = root
        root.title("Servo Controller")
        root.geometry("400x350")
        root.configure(bg="#1e1e2e")

        self.sock = None
        self.connected = False

        tk.Label(root, text="Servo Controller", font=("Arial", 20, "bold"),
                 bg="#1e1e2e", fg="#cba6f7").pack(pady=15)

        tk.Label(root, text="Enter Degree (0 - 180):",
                 font=("Arial", 12), bg="#1e1e2e", fg="#cdd6f4").pack()

        self.degree_entry = tk.Entry(root, font=("Arial", 16), width=8,
                                      justify="center", bg="#313244", fg="#cdd6f4",
                                      insertbackground="white")
        self.degree_entry.pack(pady=10)
        self.degree_entry.bind("<Return>", lambda e: self.send_degree())

        self.slider = tk.Scale(root, from_=0, to=180, orient="horizontal",
                                length=300, bg="#1e1e2e", fg="#cdd6f4",
                                highlightbackground="#1e1e2e", troughcolor="#313244",
                                activebackground="#cba6f7",
                                command=self.slider_moved)
        self.slider.set(90)
        self.slider.pack(pady=5)

        tk.Button(root, text="Move Servo", font=("Arial", 13, "bold"),
                  bg="#cba6f7", fg="#1e1e2e", padx=20, pady=8,
                  command=self.send_degree).pack(pady=10)

        self.status_label = tk.Label(root, text="Connecting...",
                                      font=("Arial", 10), bg="#1e1e2e", fg="#6c7086")
        self.status_label.pack()

        threading.Thread(target=self.connect, daemon=True).start()

    def connect(self):
        try:
            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.sock.settimeout(5)
            self.sock.connect((ESP32_IP, PORT))
            self.connected = True
            self.root.after(0, lambda: self.status_label.config(
                text="Connected ✓", fg="#a6e3a1"))
        except Exception as e:
            self.root.after(0, lambda: self.status_label.config(
                text=f"Error: {e}", fg="#f38ba8"))

    def send_degree(self):
        try:
            degree = int(self.degree_entry.get())
            if 0 <= degree <= 180:
                self._send(degree)
            else:
                self.status_label.config(text="Enter 0 to 180!", fg="#f38ba8")
        except ValueError:
            self.status_label.config(text="Numbers only!!", fg="#f38ba8")

    def slider_moved(self, val):
        if self.connected:
            self._send(int(val))

    def _send(self, degree):
        try:
            self.sock.sendall(f"{degree}\n".encode())
            self.status_label.config(text=f"Moved to {degree}° ✓", fg="#a6e3a1")
            self.slider.set(degree)
            self.degree_entry.delete(0, tk.END)
            self.degree_entry.insert(0, str(degree))
        except Exception as e:
            self.connected = False
            self.status_label.config(text="Disconnected! Restart app.", fg="#f38ba8")

root = tk.Tk()
app = ServoApp(root)
root.mainloop()