Skip to content

Final Project

Project Sketch

I’m designing an interactive learning activity where LEDs briefly light up in white to form a specific shape—such as a number or letter—and then turn off. The user’s task is to replicate that shape by touching the correct points, each equipped with a touch sensor. As the user touches each correct point, its LED turns green to indicate progress. If the user taps an incorrect point, the corresponding LED blinks red, and a small screen displays “Incorrect.”

The process is similar to an interactive “Connect the Dots” game, encouraging users to recall and recreate the shape from memory. When the correct sequence of points is touched, the screen will display a “Correct” message. If not, the shape will be shown again, and the user gets another chance. This cycle repeats until the shape is completed successfully.

The goal of this project is to help young children learn how to write numbers and letters through engaging, hands-on practice that combines memory, coordination, and feedback-based learning.

Final Project Plan

For Midterm Review, I was instructed to create a Bill of Materials and a Gantt chart to create a plan for my final project.

Tentative Materials

This list of materials is still ongoing and so far only includes items I have already started integrating into my design.

Material Quantity Description Cost In Lab Link
ESP32S3 1 ESP32S3 microcontroller $15.00 Yes Amazon
LEDs 36 6x6 RGB LED matrix Yes
Jumper Wires 50 Assorted jumper wires Yes
Soldering Wire 1 Lead-free solder wire Yes
1/8” Wood 1 Wood for mounting and structure Yes
LCD1602 Display 1 16x2 character LCD display for simple text output using GPIO ~$7.00 Yes Amazon
220Ω Resistors 6 220Ω resistors for LED matrix Yes

Tentative Gantt Chart

This is definitely subject to change, but here is my tentative gantt chart:

Weeks

I worked on my final project these weeks:

Computer-Aided Design Week

Input Week

Output Week

Application and Interface Programming Week

System Integration Week

Application and Implications Week

Invention, Intellectual Property, and Income Week

Designing Project in Fusion 360

I chose to design my final project in Fusion 360 because I have some prior experience from previous engineering classes and from watching and doing around most of Kevin Kennedy’s Learn Fusion 360 in 30 Days YouTube tutorials. They were very helpful, and I was very grateful to have done them.

First, I needed to design the inner part of my project that houses the LEDs, touch, sensors, and the main area where the user writes. I started by making the outisde of this inner housing. I made a sketch on the bottom plane in the shape of a square, extruded it, made a sketch on top of it, and then extruded a hole into to make it hollow. Using parameters was very, very important, and I used parameters in most, if not all, of my dimensions. Parameters allow dimensions to be stored in essentially variables, so if you change the value, it changes the value in all the places that variable is used. For example, I used the parameter board_height to set the height of the board. Later, when I finished the project, I was able to go back and change the height of the board easily by changing the value of the parameter in just one place. For each part of the project, I made sure to make a new component. Making new components was helpful when changing the appearance and keeping the design organized.

This is the finished outer part of my project with the appearance changed.

Next, I had to create the holder for my LED matrix. I made another new component to do this, but it was nested under the inner housing component. When adjusting the height of the LED holder, I learned that you need to select move bodies or it will just pull the face up. I struggled for a little bit trying to figure out why it kept stretching my LED holder up instead of moving the whole thing. I then asked ChatGPT what size LED it would recommend, and it said 5 mm, so my next goal was to create a matrix of 5 mm circles evenly spaced out on the LED holder. This task turned out to be a lot harder than I initially expected because I could not figure out how to evenly space the circles throughout the square. The first thing I tried was creating a circle in the top right corner of the square and then using a rectangular pattern to spread them out the distance of the square. I also had to figure out how to change the direction of the patetrn so that the circles appeared in the square. I had to select the top edge and the left edge of the square I believe to make this happen.

I realized I needed some sort of groove so that the LED holder would be able to fit in the box and not be all the way at the bottom. I made a sketch on one of the inner walls of the box and made a rectangle, extruded it, and then mirrored that to the other three sides. This is the groove on one side of the box before I mirrored it:

There are both grooves:

Next, I had to design the holder for my touch sensors. I copied the LED component I had and used Paste New under my Housing component to duplicate the LED holder for my Touch Sensor Holder. I wanted to keep the LED holes in my Touch sensor holder, so the LEDs light does not get blocked, but I needed to add another hole next to each LED hole for the wiring of the touch sensors. I repeated the Rectangular Pattern steps, Construction Lines, and Equal Constraints that I had to do for the LED holes and quickly added another set of holes for the wiring.

The last thing I needed to do was add the semi-transparent top to my project design. I initiall tried to create a new component to do this, but I could not get the constraints to be completed in the new sketch, so I made the top in the Housing component instead. I got the sketch to work first try and then extruded my rectangle by -1 mm and changed the appearance to a mostly clear glass.

Final without LED holder, touch sensor holder, or top:

Final with only LED holder:

Final:

All Parameters Used:

To see my full documentation of designing my final project in Fusion 360, you can visit my Computer-Aided Design page.

Touch Sensor

While brainstorming touch sensors, I came across this video, which I found very interesting because they made touch sensors out of common materials. I do not know if this woulf be the most practical for my final project though, but it could be a potential option if I can figure out how to make that work.

Another option I explored was this touch sensor that I found on Amazon for a relatively inexpensive price. If I chose this option, it would make it so that I would have a different touch sensor for every spot in the grid, which is a possibility.

During input week, I began to look into more options. Mr. Dubick recommended that I try using step response. I also was curious about capacitive touch sensors.

Step Response

The first sensor I tried to use was step response. Step response is Neil’s favorite form of input and Mr. Dubick recommended giving it a try, so I did. I was very confused by this sensor and spent hours trying to understand it, but I eventually decided that it would be worth looking for another sensor for my final project since step response code is so complicated. Because I already have prior coding knowledge, I chose a software-heavy final project, but the step response would be difficult to integrate into the project as a whole. To see my full PCB designing process, visit my Electronics Production page.

HW-139 Touch Sensor

I decided to try the HW-139 touch sensor next just to get a better idea of how touch sensors work. This sensor worked very well, but it seems unpractical for my final project because I am looking to make a 6x6 matrix, so I did not end up designing and milling a PCB for this sensor. However, I did several tests with breadboards and ended up using this sensor for machine week, so ultimately, I was glad that I learned how to use this sensor this week.

One thing that was cool about this sensor is that it is able to take input even through a material as thick as cardboard.

Here is a video of me testing this:

Standalone 5-Pad Capacitive Touch Sensor Breakout - AT42QT1070

Next, I found a Standalone 5-Pad Capacitive Touch Sensor Breakout - AT42QT1070 in the lab and decided to use that. I really enjoyed this sensor and will definitely be doing more work with it in the future for my final project. Milling the board for this was definitely tedious because I kept ripping traces and running into other issues. If I end up using this sensor, I will have to remill the PCB I designed, and I will probably make it double sided.

Without any code connected to it, the touch sensor lights up each of its built-in LEDs when the corresponding pad is touched. All it needs is a connection to power and ground. I used a Xiao RP2040 to program it.

I started out trying to program the touch sensor to just be able to recieve signal from one of the pads. My first big mistake was that I connected the wires on the wrong side of the sensor. I tried to connect the touch pads of the sensor to the Xiao RP2040 instead of the side with the built-in LEDs so one pad was just always being touched, which is not helpful.

Once I figured out this issue, the wiring came very easily.

This is the wiring I used:

This is my PCB design that I made slight alterations to every time I milled it:

Here is the PCB soldered and working:

ESP32-S3 Built-In Touch Sensor

During machine week, my group decided to use the built-in touch sensors on the Xiao ESP32-S3 which I did not even know existed, but I decided to try them for my final project because that would be easier than using multiple of the other types. It works very similarly to the Standalone 5-Pad Capacitive Touch Sensor Breakout - AT42QT1070, but it is able to be done using just one microcontroller, which is more efficient.

The ESP32-S3 ended up being a really good candidate for my final project because it has so many pins. I did the calculations, and using this microcontroller, I would have enough space to use 6 pins for my screen, 12 pins for my LED matrix, and 12 pins for my touch matrix. The ESP32-S3 also has web server capabilities, and I plan on incorporating a web server into my project, so that is another pro.

MPR121

I still plan on using the ESP32-S3 for the microcontroller in my project but the MPR121 will be more efficient for the touch capabilities since it has 12 touch pads.

I used this code to try and make sure both sensors were being recognized:

include

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

// Change pins if you’re using different SDA/SCL Wire.begin(10, 9); // SDA = GPIO21, SCL = GPIO22

Serial.println(“\nI2C Scanner Starting…”); }

void loop() { byte error, address; int nDevices = 0;

Serial.println(“Scanning I2C bus…”);

for (address = 1; address < 127; address++) { Wire.beginTransmission(address); error = Wire.endTransmission();

if (error == 0) {
  Serial.print("✅ I2C device found at 0x");
  if (address < 16) Serial.print("0");
  Serial.println(address, HEX);
  nDevices++;
}

}

if (nDevices == 0) { Serial.println(“❌ No I2C devices found. Check wiring!”); }

delay(3000); // Wait 3 seconds before scanning again }

It did not work for several hours before I finally realized the issue was in the sensor that I ordered. The ADD pin was purposefully bridged and that made it not work for anything other than the default GND connection. I used an exacto knife to fix this.

This code was able to read touch signals from two MPR121 sensors:

#include <Wire.h>
#include "Adafruit_MPR121.h"

Adafruit_MPR121 cap1 = Adafruit_MPR121();  // 0x5A
Adafruit_MPR121 cap2 = Adafruit_MPR121();  // 0x5C

uint16_t last1 = 0;
uint16_t last2 = 0;

void setup() {
  Serial.begin(115200);
  Wire.begin(10, 9);  // SDA, SCL

  if (!cap1.begin(0x5A)) {
    Serial.println("MPR121 0x5A not found");
    while (1);
  }

  if (!cap2.begin(0x5C)) {
    Serial.println("MPR121 0x5C not found");
    while (1);
  }

  Serial.println("MPR121s ready");
}

void loop() {
  uint16_t now1 = cap1.touched();
  uint16_t now2 = cap2.touched();

  for (int i = 0; i < 12; i++) {
    if ((now1 & (1 << i)) && !(last1 & (1 << i))) {
      Serial.print("0x5A pin "); Serial.print(i); Serial.println(" touched");
    }
    if (!(now1 & (1 << i)) && (last1 & (1 << i))) {
      Serial.print("0x5A pin "); Serial.print(i); Serial.println(" released");
    }

    if ((now2 & (1 << i)) && !(last2 & (1 << i))) {
      Serial.print("0x5C pin "); Serial.print(i); Serial.println(" touched");
    }
    if (!(now2 & (1 << i)) && (last2 & (1 << i))) {
      Serial.print("0x5C pin "); Serial.print(i); Serial.println(" released");
    }
  }

  last1 = now1;
  last2 = now2;
  delay(100);
}

Screen

I decided to use a LCD1602 screen for my final project because it can display 2 rows of text, and all I plan on my screen displaying is the character that is lit up in the LED matrix and “Correct!” or “Incorrect.” depending on the user’s response. I made sure the ESP32-S3 had enough pins for this, and once I was sure that it did, I began testing it. I found a very helpful YouTube video explaining how it works. I began programming the screen with a Xiao ESP32-S3 and then moved on to programming it with an ESP32-S3. I started out using a breadboard to program the screen, but I will be making a PCB for the final product.

Even with no code uploaded to it, the screen lit up, which is helpful because it helped me double check my wiring.

Here is the screen displaying a simple message:

This is the code I used:

#include <LiquidCrystal.h>

// Create an LCD object with the pin connections:
// LiquidCrystal(rs, enable, d4, d5, d6, d7)
LiquidCrystal lcd(2, 3, 6, 7, 8, 9);

void setup() {
  // Set up the LCD's number of columns and rows:
  lcd.begin(16, 2);

  // Print a message to the LCD
  lcd.setCursor(0, 0);  // Column 0, Row 0
  lcd.print("Hello, World!");

  lcd.setCursor(0, 1);  // Column 0, Row 1
  lcd.print("XIAO ESP32-S3");
}

void loop() {
  // Nothing to do in loop for static text
}

ChatGPT helped me make this test code, but I went on to test various messages and change the pinout of the screen to help ensure my knowledge of the code.

I also tried to create a simple web interface to display different numbers on the screen, which is one of the things I want my final screen to do. This was very successful as well. I will be improving this interface as I progress on my project to be more personalized and achieve the purpose of my project more accurately.

This is the simple test interface:

LED Matrix

I started out trying to understand how LED matrices work in Tinkercad and the Wokwi. This was very helpful and I gained a much better understanding of how LED matrices work after doing this. I started out using an Arduino in Tinkercad and the moved to using an ESP32-S3 in Wokwi and creating a test code. Ultimately, I want to create a 6x6 LED Matrix, but as of now, I have only tested a 3x3 matrix on a breadboard, but I will make my PCB for a 6x6 matrix.

The diagram and code on this article was a very helpful start for me.

Tinkercad 3x3 Matrix:

Tinkercad 6x6 Matrix:

In Tinkercad, out of curiosity, I also started exploring making a number in the matrix. I tried the number 3 and was pleased with the results.

Wokwi 3x3 Matrix with ESP32-S3:

After working in Wokwi, I moved on to make a 3x3 matrix using the ESP32-S3 on a breadboard. The breadboard is just a temporary test to try and connect several components of my project together before creating my final PCB.

Before connecting my screen, the matrix, and the web interface, I wanted to see if the matrix on its own would work. I set it up on a breadboard for testing purposes, and it was not very visually appealing but achieved its purpose. I initially ran into a wiring issue that led two LEDs to stay on all the time, but that was because one of the wires was supposed to be connected to the other leg of the LED.

This is my 3x3 matrix displaying a series of patterns that ChatGPT helped me come up with:

This is my 3x3 matrix turning all the LEDs on and then off:

Once I got the matrix working, I asked ChatGPT to help me come up with a code for a web server that has 3 different pattern option buttons. When a button is pressed the pattern name will display on the screen, and the LED matrix will show the pattern.

This is the code I used:

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

// ==== LCD with NEW pinout ====
LiquidCrystal lcd(39, 38, 37, 36, 35, 48);  // rs, e, d4, d5, d6, d7

// ==== LED Matrix ====
const int ROW_PINS[] = {16, 17, 18};  // Rows: anodes
const int COL_PINS[] = {42, 41, 40};  // Columns: cathodes
const int ROWS = 3;
const int COLS = 3;
const int REFRESH_DELAY = 1;

// ==== WiFi ====
const char* ssid = "SSID";
const char* password = "password";
WebServer server(80);

// ==== Patterns ====
byte patterns[][3] = {
  // Diagonal
  {B100, B010, B001},
  // Border
  {B111, B101, B111},
  // All On
  {B111, B111, B111}
};

const char* patternNames[] = {"Diagonal", "Border", "All On"};
const int NUM_PATTERNS = 3;
int currentPattern = 0;

void allOff() {
  for (int r = 0; r < ROWS; r++) digitalWrite(ROW_PINS[r], LOW);
  for (int c = 0; c < COLS; c++) digitalWrite(COL_PINS[c], HIGH);
}

void displayPattern(int index) {
  for (int row = 0; row < ROWS; row++) {
    allOff();
    digitalWrite(ROW_PINS[row], HIGH);
    for (int col = 0; col < COLS; col++) {
      if (bitRead(patterns[index][row], COLS - 1 - col)) {
        digitalWrite(COL_PINS[col], LOW);  // Turn LED on
      } else {
        digitalWrite(COL_PINS[col], HIGH); // Turn LED off
      }
    }
    delay(REFRESH_DELAY);
  }
}

// ==== Web Interface ====
String htmlPage = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
  <title>LED Matrix</title>
  <style>
    body { font-family: sans-serif; text-align: center; padding-top: 40px; }
    button {
      font-size: 24px; padding: 15px 30px;
      margin: 10px; border-radius: 8px; background-color: #007BFF;
      color: white; border: none;
    }
    button:hover { background-color: #0056b3; }
  </style>
</head>
<body>
  <h2>Select LED Pattern</h2>
  <a href="/pattern?index=0"><button>Diagonal</button></a>
  <a href="/pattern?index=1"><button>Border</button></a>
  <a href="/pattern?index=2"><button>All On</button></a>
</body>
</html>
)rawliteral";

// ==== Web Handlers ====
void handleRoot() {
  server.send(200, "text/html", htmlPage);
}

void handlePattern() {
  if (server.hasArg("index")) {
    int index = server.arg("index").toInt();
    if (index >= 0 && index < NUM_PATTERNS) {
      currentPattern = index;

      // Update LCD
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Pattern:");
      lcd.setCursor(0, 1);
      lcd.print(patternNames[index]);

      Serial.println("Pattern set to: " + String(patternNames[index]));
    }
  }
  server.sendHeader("Location", "/", true);
  server.send(302, "text/plain", "");
}

void setup() {
  Serial.begin(115200);
  lcd.begin(16, 2);
  lcd.print("Connecting WiFi");

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

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("IP:");
  lcd.setCursor(0, 1);
  lcd.print(WiFi.localIP());

  // Init matrix pins
  for (int r = 0; r < ROWS; r++) {
    pinMode(ROW_PINS[r], OUTPUT);
    digitalWrite(ROW_PINS[r], LOW);
  }
  for (int c = 0; c < COLS; c++) {
    pinMode(COL_PINS[c], OUTPUT);
    digitalWrite(COL_PINS[c], HIGH);
  }

  server.on("/", handleRoot);
  server.on("/pattern", handlePattern);
  server.begin();
}

void loop() {
  server.handleClient();
  displayPattern(currentPattern);
}

This was the result:

The screen is not very visible in that video, so this is an example of a message it was displaying:

This is what the web server was displaying:

This program was a form of proof of concept for me because my end product will be similar in that a web server displays several options and when the user selects an option, the option will appear on the screen and on the LED matrix.

Currently, I am working on a PCB for the 6x6 LED matrix and the LCD1602 screen using the ESP32-S3 microcontroller, which should be pretty simple since I already have it working on a breadboard. My next step will be figure out how to make the LED matrix a form of touch screen, preferably using the built-in touch pins on the ESP32-S3. I am also still working on understanding the code for web interfaces, and I have a pretty good understand the screen code and the LED matrix code.

Files

LED Holder

AI Help


Last update: June 6, 2025