0%

About Me

You found me! I am Annie Li. My research focuses on Reinforcement Learning and Bayesian Optimization in Large Language Models (LLMs) and machine control, and I am especially interested in how humans collaborate with AI in areas such as prosthetics and fabrication, where machines extend human ability.

This site documents my progress in MAS.836 How to Make (Almost) Anything taught by Neil Gershenfeld through 14 weekly projects and a final project, with notes written to be clear enough to fully reproduce my work step by step. I am reachable through email: annieliy@mit.edu.

feature 1 feature 2


“Run toward the hardest problems. This approach has helped me to learn a tremendous amount from both success and failure.”
“We're so excited about technology. We can help turn the impossible into the possible.”
—— Lisa Su
“The people who are crazy enough to think they can change the world are the ones who do.”
—— Steve Jobs

Final Project — Marauder’s Map of MIT

Finished milled PCB

The MIT Hackers Map! Tells you all the official and unofficial places you're at by live tracking. Maybe your professor is watching you... In the future, I aim try to integrate features that tracks people, e.g. a proximity alert of your professor!

System Overview

The system continuously scans nearby Wi-Fi access points, compares their BSSIDs and signal strengths against known location fingerprints, and maps the result to a specific MIT building or landmark. Once a location is detected, the TFT screen updates with a customized message and visual effect.

  • Microcontroller: Seeed XIAO ESP32S3
  • Output device: 2.8" SPI TFT display (ILI9341)
  • Input source: Ambient Wi-Fi signals (RSSI + BSSID)
  • Interface: Visual text + animation on TFT
System overview diagram

System architecture: ESP32 scans Wi-Fi → infers location → updates TFT output.

System overview diagram

Set up with 2.8" SPI TFT display.

System overview diagram

PCB board.

System overview diagram

Schematic again for Seeed XIAO ESP32S3 driving 2.8" SPI TFT display (ILI9341).

Finished milled PCB

TFT display soldered onto board, check finals week for my location tracking code!!

Finished milled PCB

Location display.

Location Detection via Wi-Fi Fingerprinting

Instead of using GPS or cloud-based geolocation APIs, I implemented Google API (outdoors) + a local Wi-Fi fingerprinting approach(indoors), which works reliably indoors and does not require external services.

Each location (e.g. Building 38, Killian Court, Media Lab) is represented by a small set of known Wi-Fi access point BSSIDs. When the ESP32 detects one or more of these BSSIDs above a signal strength threshold, it infers the corresponding location.

Wi-Fi scanning code snippet

Arduino logic for scanning nearby Wi-Fi networks and matching BSSIDs. In this section for example, Building 38 is identified by the strong and consistent networks of EECS Shop and EECS Lab.

Wi-Fi scanning code snippet

Arduino logic for displaying matched position using boolean.

This approach allowed me to create a flexible, expandable location system: adding a new building only requires collecting its Wi-Fi fingerprints and defining a new detection function.

Files

TFT Output Design

The TFT display acts as the primary user-facing output device. When a location is detected, the screen displays a welcoming message, the user’s presence, and a themed visual effect.

Different locations trigger different color schemes and animations, reinforcing the idea of a “living map” that reacts to the environment.

TFT displaying location message

TFT display showing a detected location and custom message.

For example:

  • ✅Building 38: Green text with matrix-style animation
  • 🍀Killian Court: Formal welcome message and dome-inspired effects
  • 🧠Media Lab: Glitch effects and high-contrast visuals
  • 🎃Easter eggs: Fun proximity alerts (e.g. “Police Car on the Dome”)

Live Location Tracking!!

In the demo video below, I walk through different parts of campus while the device dynamically updates its output based on the detected location.

I added some effects such as Matrix Rain, Glitch Effect, Pulsing dome so it looks cool! Check out the final display effect below:

Interaction Flow

  1. The ESP32 continuously scans nearby Wi-Fi networks
  2. Strong signals are filtered and matched against known fingerprints
  3. A location is inferred based on detected BSSIDs
  4. The TFT screen updates with location-specific text and animations
  5. If no match is found, the system remains in an “unknown location” state
Finished milled PCB

I 3D printed MIT letters and painted them with Acrylic colors.

Finished milled PCB

My outer device uses 3D print parts as set up.

Finished milled PCB

Final shape of device coming together.

Finished milled PCB

HTMAA Convention - Annie's stand & all semester highlights!

Midterm Review Content + Plans & Task Status before Midterm

Project Direction: A compact handheld device that displays your approximate MIT location on a small OLED screen. The microcontroller (ESP32S3) receives simple coordinate or building-number data from a phone and prints phrases like "You are near Building 26" or "East Campus" or "Lobby 10".

What it Does

MIT Hacker's Map System Diagram

Progress So Far

Next Steps (Before Final)

MIT Hacker's Map 3D print Phone Device

Hardware Overview

Status: Core architecture decided. OLED tested. BLE communication pathway defined. Ready for PCB design, enclosure modeling, and firmware.

Week 1 — Computer-Controlled Cutting

Group assignment: documentation and group work for this week

Vinyl Cutting

Quick stickers to celebrate MAS.863! I traced the course marks and icons, tuned stroke weights for vinyl, and cut them as high-contrast decals.

I experimented with ChatGPT to generate initial vinyl sticker mockups PNGs. Then I vectorized them and adjusted paths in inkscape in Inkscape, and prepare them for the vinyl cutter. Through this process, I learned the importance of clean outlines, kerf considerations, and simplifying shapes for weeding.

Vinyl sticker reference artwork
Reference artwork used for the vinyl traces.
Vinyl stickers after cutting
Final cut & not yet weeded stickers.

Process of tracing and preparing the design in Inkscape.

Process

  1. Software & Setup. Import the design into the vinyl-cutter software; connect the cutter to power and your computer.
  2. Load Vinyl. Feed the roll; choose Roll on the machine; align so the pinch rollers sit on the grit rollers.
  3. Adjust Blade. Set blade depth so it cuts the vinyl but leaves the paper backing intact.
  4. Send Design. Send the job from software. Set pixels to 200 (≥ 72; adjust as needed), click Calculate, then Connect to the cutter and start the cut.
  5. Unload & Apply. Remove the sheet, weed the excess, apply application tape, then transfer to the surface.

Learning from Mistakes

In the bottom left corner, I made a vinyl cutter beginner mistake during designing the sticker "Parametric Design". To get the final product, I have to remove the little squares inside the net like structure bit by bit... Therefore, use simple shapes & straight lines for vinyl cutter design.

And there you have it; the final weeded product!

Final vinyl stickers after cutting and weeding
Final cut & weeded stickers (ready for transfer).

Files

Laser Cutting

w1 pic 1 w1 pic 2 w1 pic 3

Laser Cut — Idea

Mid-Autumn Festival Style Lantern

Laser Kerf Characterization

We tested power/speed and measured kerf; our press-fit offset was +0.18 mm.

Parametric Press-fit Kit

  • Material: 3 mm cardboard
  • Parameters: thickness, tab_width, angle
  • Multiple assemblies: cube, lantern, lantern without handle
  • Extra: living-hinge arc panel (not flat) (didn't get to it this time; will try next time!)

Project Demo

Week 1 laser-cut design layout from Fusion 360

My laser-cut design layout design notes.

Week 1 laser-cut design layout from Fusion 360

Laser-cut design layout with parameters labeled from Fusion 360.

Design Process

I parameterized all pieces around thickness, tab_width, and the overall panel width. The side panels are mirrored; the front and back share geometry; and all slots subtract 2 × thickness from the internal clearances. Tabs are evenly spaced and sized to press-fit with the measured kerf offset (+0.18 mm).

I iterated through test cuts to tune slot_clearance for cardboard springiness, then finalized the handle, base, and top.

Project Demo — design → cut → assembly (Week 1)

First Time Laser Cutting - Bringing 2D Designs into 3D Reality

I have some previous experience designing 3D shapes in CAD, but I had never actually built them in real life. This was my first time using a laser cutter, and I was instantly hooked—I couldn’t stop wanting to learn more. (Shout out to Jesse for his amazing teaching style; I didn’t zone out for a single moment!) I’m officially addicted now.

I initially set my slot width to slightly more than 2 mm (2.94 mm), based on recommendations from my research[2]. But when I went to the makerspace and measured the actual cardboard thickness, I become concerned that the slots might not fit properly with the tabs.

I joined Tushar and Mariam for my first time laser cutting. We helped each other in the laser cut process (such as Tushar’s magnificent use of the Blue laser engraving) and in CAD (such as slot width, cardboard thickness, and kerf)!

First Time Reaction

I was fascinated by how the laser cutter decided its path—it seemed to cut here and there instead of following one continuous line. Small fires and little bursts of smoke appeared from time to time, yet the cutter moved with incredible precision. It was mesmerizing to watch!

Laser Cutting

Big shout out to J e s s e , for walking me through the laser cutter & safety training detail by detail, and watching me do the whole process while giving instructions!

Quick Steps

  1. Wear safety glasses.
  2. Plug in the USB drive.
  3. Open the USB and locate your .svg or .dxf file.
  4. Open InkscapeNew document.
  5. File → Import… and choose the file from the USB.
  6. Select all (/Ctrl + A) and scale to fit the page. Use /Ctrl + mouse wheel to zoom.
  7. Set stroke color by intent:
    • Red — Cut through
    • Blue — Engrave / score
  8. Print (/Ctrl + P) → click More settings.
    Material: Cardboard
  9. Set Power and Speed (Please see Test Result Notes below). Hit Apply and OK, then Print.
  10. Put material in laser cutter. Set XY home by bringing the icon to the edge of pattern, check inside the laser cutter to see if the laser is out of material margin.
  11. Optional Focusing: Place focal tool on the material. Manually lower the laser head or raise the machine's bed until the nozzle gently touches the top of the focus tool by pressing Ʌ/V on laser cutter to adjust for Z-Axis Height(If there are people using the laser cutter before you, no need to adjust Z Height). Remove the focus tool from under the nozzle.
  12. Last Check: Gas Assist and Laser Cutter is turned on.
  13. Initiate Cutting: Start the cutting job from the control panel.
  14. Finishing: Remove Parts, clean the area. Apply any necessary finishing touches, such as cutting, painting, or assembly.
First Test Cut

Test Results

Setting Value Observation
Power Red 100%
Blue 100% First layer of cardboard cut through
Blue 75% Engraving color too light
Blue 85% Perfect
Speed Red 30% First cut: did not cut through. Second cut: smokes & small fires, still incomplete; needed knife.
Red 20% Mostly cut through, but second layer needed knife. Result resembled perforated Amazon box.
Red 15% or lower Recommended to test
Blue 100%
Set Power and Speed
Set XY Home
w1 pic 5 w1 pic 6 w1 pic 6

Learning from Mistakes

My second attempt at laser cutting did not work for my final product, because my dimensions and ratios are off once I imported and adjusted them in the laser cutter computer.

I reused the card board which has some of it cut out. In my second cut, the pattern over lapped with the cut out part from trial 1, causing the laser to shoot through the honeycomb structure underneath the material. I will make sure to aviod next time, and I have to do a second cut to get the shape!

Kerf

In my test trial, my tabs & slots are a lose fit due to kerf from cutting a second time.

In my actual laser cutting session, my tabs are too big (all the bad thoughts of having to go back to fusion, my life flashed before my eyes), but luckily it is cardboard, I start pinching the tabs until they fit into my slots!

Engraving in Laser Cutting

Engraving vs. cutting in Inkscape and the lab software: I follow the lab convention Blue = Engrave, Red = Cut, and set power/speed based on the table above.

Steps

  1. Separate geometry by operation. Select paths you want to engrave (fills, hatch, logos) and those you want to cut (outer profiles).
  2. Assign stroke colors:
    • Blue (#0000FF) = Engrave
    • Red (#FF0000) = Cut
    In Inkscape: Object → Fill and Stroke → Stroke paint. Set Fill = None. In Stroke style, use a thin width (e.g., 0.1 mm) for clarity.
  3. Check real size. File → Document Properties to confirm page units (mm/in). With your artwork selected, verify W/H on the toolbar. Lock proportions and type exact dimensions if needed.
  4. Export for the laser. Save as Plain SVG (or PDF if your lab prefers). Keep colors intact.
  5. Map colors to processes in the laser software.
    • Blue (Engrave): set Speed high / Power lower for surface mark.
    • Red (Cut): set Speed lower / Power higher for through-cut.
    Use the lab’s recommended values from the table above, then run a small test square.
  6. Focus, frame, test. Check focus height, run a frame pass, and do a 10–20 mm test to confirm mark depth and cut-through without charring.
Engraving setup & color-layer mapping workflow.
Engraved lantern tab showing mismatch
Engraving mistake: tab dimensions mismatch with the front panel.

What Went Wrong (and Fix)

The engraved tab should match the front tab dimensions, but they differ here because I didn’t re-check sizes in Inkscape before cutting. Fix: verify units and W/H for both parts, use Align and Distribute to compare, and run a paper print check before sending to the laser.

Quick Pre-Flight Checklist

  • Units correct (mm or inches) and page size set.
  • All cut paths = Red, all engrave paths = Blue, fill = none.
  • No duplicate/stacked paths (Edit → Select Same → Stroke color, then Path → Combine as needed).
  • Dimensions match your sketch/CAD; do a paper print at 100% to confirm fit.
  • Test swatch for power/speed per the table; adjust if edges char or don’t go through.

Final Assemblying

My Assemblying Video

Finished Product

Finished Lantern

Mid-Autumn Festival Lantern

w1 pic 9 w1 pic 10 w1 pic 11
Effect in Dark Room
Silhouette Light Effects

Files

References

[1] Alfonso's Fusion 360 Tutorial: https://alfonso.pages.cba.mit.edu/recitations/parametric_design.html

[2] Laser Cut Slot Dimension: https://www.reddit.com/r/lasercutting/comments/16yn0e9/laser_cutting_slot_sizetolerance_recommendation/

[3] CAD Parameterization Tutorial: https://www.youtube.com/watch?v=tx89UXMeqwQ

Week 2 — Embedded Programming

Group assignment: documentation and group work for this week

Week 2 · Embedded Programming

Seeed XIAO RP2040 · LEDs · Capacitive touch on a copper PCB · I²C OLED · Serial plotting

RP2040 LED Test (Arduino)

              
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// LED pins #define PIN_RED 17 #define PIN_GREEN 16 #define PIN_BLUE 25 void setup() { pinMode(PIN_RED, OUTPUT); pinMode(PIN_GREEN, OUTPUT); pinMode(PIN_BLUE, OUTPUT); digitalWrite(PIN_RED, HIGH); // LEDs are active-low on this board digitalWrite(PIN_GREEN, HIGH); digitalWrite(PIN_BLUE, HIGH); } void loop() { digitalWrite(PIN_GREEN, LOW); delay(500); digitalWrite(PIN_GREEN, HIGH); digitalWrite(PIN_BLUE, LOW); delay(500); digitalWrite(PIN_BLUE, HIGH); digitalWrite(PIN_RED, LOW); delay(500); digitalWrite(PIN_RED, HIGH); delay(500); }
Serial plotter: capacitance spikes when touching the copper pads.
Blink LED
Serial Monitor

OLED Scrolling Text (Arduino)

              
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #define SCREEN_WIDTH 128 // OLED width (px) #define SCREEN_HEIGHT 64 // OLED height (px) #define SCREEN_ADDRESS 0x3C // 0x3C or 0x3D Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); void setup() { // initialize Serial port Serial.begin(9600); delay(50); // initialize display if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) { Serial.println(F("SSD1306 allocation failed")); for(;;) { } // halt } display.clearDisplay(); // text settings display.setTextSize(1); display.setTextColor(SSD1306_WHITE); display.setCursor(0, 25); display.print("Labubu"); display.display(); // ---- enable hardware scrolling (pick ONE) ---- display.startscrollright(0x00, 0x0F); // scroll entire screen to the right // display.startscrollleft(0x00, 0x0F); // scroll to the left // display.startscrolldiagright(0x00, 0x0F); // diagonal right // display.startscrolldiagleft(0x00, 0x0F); // diagonal left } void loop() { // Nothing needed here; the OLED handles scrolling. }
Uses Adafruit SSD1306 hardware scroll; set direction by swapping the startscroll* call.

OLED Sketch (snippet)

              
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #define SCREEN_ADDRESS 0x3C Adafruit_SSD1306 display(128, 64, &Wire, -1); void setup() { Serial.begin(9600); delay(50); display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS); display.clearDisplay(); display.setTextSize(1); display.setTextColor(SSD1306_WHITE); } void loop() { display.clearDisplay(); display.setCursor(28, 25); display.print("Labubu!"); display.display(); delay(250); }

Assignment Goals

  • Browse the RP2040 datasheet.
  • Write & test programs that interact with local I/O (LEDs, touch, OLED).
  • Communicate data to the computer (serial + live plotting).
  • Extra: I have made plans to try PlatformIO and ESP32, but I don't know where to start yet.

Local Input & Output

1) LEDs

According to Quentin Bolsée's example, it defined pins for red, green, and blue LEDs and blinked them in sequence to verify digital GPIO control.

2) Touch Sensing on Copper Board

The copper pads on my custom board act as capacitive sensors. When a finger touches a pad, the effective capacitance increases. The RP2040 measures this by timing charge/discharge cycles; the measurement rises on touch, and plotting those values yields a real-time graph of touch intensity.

3) OLED Display (I²C)

Using the Adafruit SSD1306 library, I initialized a 128×64 display and printed text (e.g., “Labubu!”). This validates I²C communication between the microcontroller and display.

Communication with the Computer

The sketch streams touch values over Serial. In the IDE’s plotter, touches show up as spikes, satisfying the “interact + communicate” requirement.

Physics Rationale (Why Numbers Rise When I Touch)

A capacitor stores charge: Q = C · V. The copper pad and ground form a capacitor with air (and board materials) as the dielectric. Your body behaves like a large conductive object near ground; touching the pad increases the pad’s capacitance C. The microcontroller senses this via timing, so the reported value increases—what you see as rising numbers and peaks in the plot.

Reflection

This week tied together sensing (capacitive touch), processing (RP2040), and output (LEDs/OLED) with simple physics. Arduino made it straightforward to connect hardware effects to visual feedback.

Week 3 — 3D Scanning and Printing

Group assignment: documentation and group work for this week

3D Printing

玲珑球 inspiration

Inspiration

My Week 3 3D printing project is inspired by the traditional 玲珑球 (Línglóng Ball/Nested Ball), an extraordinary hand-crafted artifact from the Qing Dynasty. These intricate puzzle balls, carved from a single piece of ivory, often contain multiple concentric spheres nested inside each other, each freely rotating. They reflect the pinnacle of Chinese artisanship: precision, patience, and the pursuit of impossibility.

What fascinates me is how these artifacts parallel the challenge of non-subtractive design in digital fabrication. Just like artisans achieved the impossible by hand, 3D printing allows us to create nested and interlocked geometries that machines cannot carve subtractively. My design takes direct inspiration from this tradition, reimagined through modern additive manufacturing.

I also drew inspiration from Lingdong, an alumnus of this class, who created a modern reinterpretation of the 玲珑球/Nested Ball in his own Week 6 project.

Fusion 360 Design

Here is my own attempt to reinterpret the Nested Ball using Fusion 360. I modeled nested shells with Voronoi patterned cutouts uisng Meshmixer, capturing the spirit of the original hand-carved puzzle balls, while showcasing what 3D printing makes uniquely possible.

Torus Knot

Torus Knot CAD Model

Finished Torus Knot checking for continuity.

Twisted torus ring render

Inspiration

This piece reinterprets the flowing, braided rhythm of traditional Chinese jade bracelets known as 绞丝 / 麻花镯. The form is a continuous tube that follows a circular path and twists multiple times, creating a braided silhouette that reads as soft silk but is printed as a single body.

This design is inspired by the braided jade bracelets (绞丝纹 / 麻花手镯) of the Qing Dynasty, important artifacts in the Shanghai Museum that exemplify the elegance of rhythmic linework and the technical mastery of jade carving. These bracelets are considered standard forms of Qing court art, with the twisted silk-like pattern representing both aesthetic refinement and extraordinary craftsmanship.

My STL explores the rarer, high-craft variant: the bracelet is effectively hollow and interlocking—the apparent strands weave around each other without being fused inside, echoing museum pieces where carvers created the illusion of independent helices. Additive manufacturing lets me realize this as a single print, while preserving the visual logic of interlaced jade cords.

Specs
  • Ring outer Ø: ~80–100 mm (parametric)
  • Tube Ø: ~2.5–3.5 mm
  • Twist: 720°–1440° (2–4 full turns around the ring)
  • Optional braided look via Circular Pattern (8–16 copies)

Modeling Steps (Fusion 360)

Bracelet Modeling Step 1 Bracelet Modeling Step 2
Full Fusion 360 Tutorial
  1. On the XY plane, sketch a 30 mm diameter circle with its center positioned 100 mm from the origin (this is the base path reference).
  2. On the perimeter of that larger circle, sketch a 10 mm diameter circle (strand profile).
  3. Use Trim to remove the portion of the large circle that lies inside the small circle, leaving two distinct circles.
  4. Open Modify → Move/Copy. Select the entire sketch and set the pivot to the origin. Click Confirm (to lock the pivot at the origin).
  5. Make a copy of the sketch and rotate it –5° about the Y-axis (pivot at the origin).
  6. Repeat the copy/rotate operation to create six additional copies, each rotated by an extra . Stop when you have 8 sketches total evenly distributed around the origin.
  7. For the second sketch (the one at –5° about Y), select only its small circle. In Modify → Move/Copy, set the pivot to the center of its corresponding large circle. Align the pivot by draging rotation manipulator (the small circle by the arrows) to the center of the small circle of the sketch.
  8. Rotate that small circle by 45° about the Z-axis.
  9. Repeat the previous step for the remaining small circles so they are sequentially offset by 90°, 135°, 180°, … relative to the first sketch’s small circle.
  10. Use Trim to remove all remaining large circles. You should now have a ring of small profile circles with progressive angular offsets.
  11. With all profiles complete, select the entire sketch group and open Modify → Move/Copy. Set the pivot at the origin and confirm. Create copies of the group, rotating each by 40° increments until the sequence closes the full 360°.
  12. Use Create → Loft and sequentially select the small circles in 3D to connect them into a smooth, continuous strand around the ring.
    Tip: If a loft fails, check profile order and spacing; adjust angles or add guide profiles as needed.
  13. With the strand body created, open Modify → Move/Copy, set pivot to origin, confirm, and make a copy rotated by 10°.
  14. Create three copies total (original + 3), each offset by 10°, to form four interwoven strands. Inspect continuity, then export as .stl.
    Print note: Lay the ring flat; 0.16–0.20 mm layers, 3 perimeters, 10–20% gyroid infill.

Print Plan

  • Material: White PETG (The lesson is, the more rigid the material, the easier to remove support. Also, PETG is shiny!)
  • Nozzle: 0.4 mm  •  Layer: 0.16–0.20 mm
  • Perimeters: 3  •  Infill: 10% gyroid
  • Supports: Organic, Everywhere.
  • Orientation: Lay the ring flat for strength and surface finish

Project Demo | 3D Printed Torus Knot Bracelet

Week 3 3D Support Structure

Organic support within the independent spirals, surprisingly easy to remove.

Week 3 cut_final_torus_knot

Torus Knot, removed all the support.

Files

3D Scan Banana

Using Creality Ferret 3D, I scanned a banana I retrieved from the Banana Lounge.

Week 3 3D Scan from Creality Ferret Pro

Initial Scan of Banana (Hollow) and Caesar Statue by Creality Ferret Pro.

Week 3 Ready to Print Banana

Ready to Print Solid Banana STL

Following Anthony's advice, I tried scanning the banana on its own for a few times, and the Creality Ferret Pro just couldn't pickup the entire banana while it is spinning. Therefore, I placed the little Caesar statue next to it and get a full complete scan of the banana.

I then imported the scan into Meshmixer, using Plane Cut to slice off the Caesar and the base, leaving a hollow Banana; then I use Meshmixer to make it solid, below are my steps:

Vinyl sticker reference artwork
Import and select Plane Cut.
Vinyl stickers after cutting
Adjust the angle of Plane Cut.

Filling a Hollow 3D Scan in Meshmixer

  1. Open Meshmixer and go to File → Import to load scanned .stl or .obj model.
  2. Click the model to select it in the Object Browser (bottom-right corner).
  3. Go to Edit → Make Solid to generate a solid, printable version of your scan.
  4. In the Make Solid panel, adjust the parameters:
    Solid Type: Accurate (recommended for detailed scans)
    Solid Accuracy: Increase for smoother details
    Mesh Density: Increase for finer mesh
    Offset Distance: Set to 0 mm for same surface, or positive to thicken walls For mine, I used default.
  5. Vinyl sticker reference artwork
    Once all the parameters are checked, hit cut.
    Vinyl stickers after cutting
    Make solid, this takes a few seconds.
  6. Wait for the preview to update. Check that holes are filled and the interior is solid, then click Accept.
  7. To fix any remaining holes, go to Analysis → Inspector and click Auto Repair All until the mesh is fully watertight.
  8. Finally, export the new solid model via File → Export → STL and it’s ready for 3D printing.
Week 3 Solid Banana

Ready to Print Solid Banana STL

Week 3 Solid Banana

Finished product leaving the 3D printer.

Week 3 Solid Banana

Cut and Final Form of Banana.

Ta-da! Now we have a " f r e s h " 3D Banana!

Files

  • Please find my files here!
  • Solid_Banana.stl
  • (This is a dropbox link, you (and anyone with this link) can download from it, ignore "can't load this file", that's just b/c dropbox don't support stl preview.) If you can not download it, please email me at annieliy@mit.edu.

Week 4 — Electronics Design

This week, I designed a custom PCB around the Seeed XIAO ESP32S3 to drive a 2.8" SPI TFT display (with optional touch) for my location-tracking project.

Group assignment: documentation and group work for this week

Goals

Week 4 screen

2.8" SPI TFT display, touchable, 14 pins.

Week 4 screen

Seeed XIAO ESP32S3, with WiFi, 5V input, and location tracking library.

What I designed

Schematic highlights

I started by creating clear net labels (SPI_SCK, SPI_MOSI, SPI_MISO, TFT_CS, TFT_DC, TFT_RST, 5V, GND) and connecting them between the XIAO pins and the 14-pin display connector.

Week 4 schematic (XIAO ESP32S3 to TFT connector)

Schematic: XIAO ESP32S3 mapped to 2.8" TFT SPI connector pins.

PCB layout + routing

After importing the netlist into PCB Editor, I placed the XIAO footprint and the 1×14 connector, then routed the SPI + control lines. I also set up net classes to route power thicker than signals and drew the board outline on Edge.Cuts.

Week 4 PCB layout and routing

PCB: component placement and routed traces (power + signal nets).

Checks (ERC / DRC)

I ran ERC to confirm the schematic connections, then ran DRC after routing. The remaining flags were mostly silkscreen-related (text size / silkscreen clipping), which do not affect electrical function.

Week 4 DRC results window

DRC: final check after routing (warnings mainly from silkscreen constraints).

Process recap

  1. Labeled SPI + control nets on the XIAO pins
  2. Added a 1×14 connector symbol and matched labels pin-by-pin to the TFT
  3. Ran ERC and fixed “label not connected” issues by completing the connector mapping
  4. Imported into PCB Editor and placed footprints
  5. Set net classes (Power thicker than Signal) and routed traces
  6. Drew the board outline on Edge.Cuts and ran DRC

Demo / build log

Short video walkthrough of the board design and routing:

Files

Extra credit: case design for the screen + PCB

As extra credit, I designed a 3D-printable enclosure that fits both the TFT display and the PCB, with cutouts for the screen and sufficient clearance for assembly. I measured key dimensions in CAD and verified fit before slicing.

Fusion 360 case design

After: nicely enclosed. I used four 40 screws and nuts to secure the screen onto the drilled holes; case material is PLA.

Fusion 360 case design

Before: PCB and TFT display with no case.

Fusion 360 case design

I also cut a box which I glued to the screen case for full enclosure.

Fusion 360 case design

Case design in CAD.

Slicer preview

Prusa slicer preview.

Week 5 — Electronics Production

Electronics Production

This week focused on the full electronics production workflow: preparing a Fab-ready PCB design, generating milling files from KiCad, setting up the milling machine, changing tools, and fabricating the final copper board. The goal was to translate a finished PCB design into a physical circuit board using the lab’s CNC milling process.

Group assignment: documentation and group work for this week

Big thanks to the GOAT A n t h o n y for teaching us how to use the milling machine — patiently, repeatedly, and with heroic restraint, despite having explained the same steps approximately a thousand times.

I converted this ...

Week 4 PCB layout and routing

to this.

Week 4 PCB layout and routing

and this!

Week 4 PCB layout and routing

and this!

Finished milled PCB

Finished PCB after milling and removal from the machine.

Preview

Exporting Fab-Ready Files from KiCad

I began by exporting fabrication-ready files from KiCad. This included carefully checking that the correct layers were enabled:

These layers were exported and verified to ensure compatibility with the milling workflow used in the lab. I double-checked trace widths, clearances, and overall board dimensions before proceeding.

Fab-ready PCB preview

Fab-ready PCB files opened and previewed before milling.

Milling

Tool Selection and Milling Parameters

For milling, I selected two different end mills depending on the task:

My board is a 3cm by 7cm board, total estimated milling time by machine is 20 minutes. The board was secured to the milling bed using strong double-sided tape on the back of the copper board to ensure it remained flat and stable throughout the process.

Double sided tape on copper board

Double-sided tape applied to the back of the copper board before mounting.

Tool Changing Process

I first milled the traces using the 1/64" end mill. After the trace milling was complete, I paused the machine and changed tools to the 1/32" end mill in order to mill the board outline.

During the tool change, I used two wrenches to safely remove and install the end mill, and used wire clips to allow the machine to re-probe the bed accurately after the tool swap. This ensured correct Z-height calibration for the second milling pass.

⚠️Audio maybe loud in the youtube videos below.⚠️

The first video below exists primarily so Neil can verify that I did, in fact, operate the machine myself. After that, I’ve included a close-up tutorial video for everyone else, featuring the GOAT A n t h o n y in original speed, no edits, no shortcuts, and no mercy‼️ for improper tool changes.

Milling Process

⚠️Audio maybe loud in the youtube video below.⚠️

Cleaning and Board Removal

After milling completed, I vacuumed the board and surrounding area to remove copper dust and debris. Once cleaned, I carefully pried the finished board off the milling bed, taking care not to bend or damage the copper traces.

⚠️Audio maybe loud in the youtube video below.⚠️

Finished milled PCB

Finished PCB after milling and removal from the machine.

Finished milled PCB

Soldered pcb with ESP32S3 and eight 0 ohm resistor as jump wires.

I tested the ESP32S3 with a simple LED test. Then I went onto soldering the 2.8 inch TFT display to my pcb.

Finished milled PCB

TFT display soldered onto board, check finals week for my location tracking code!!

Finished milled PCB

TFT display soldered onto board, check finals week for my location tracking code!!

Week 6 — Computer-Controlled Machining

CNC-Milled Stool

For Machine Week, I designed, milled, and assembled a meter-scale stool using CNC routing. The stool is constructed from sheet stock and assembled using interlocking geometry.

Group assignment: documentation and group work for this week

Big thanks to A n t h o n y and D a v e at the EECS shop for turning a big, loud, slightly terrifying CNC machine into something approachable—and for patiently walking me through how routers, bits, saws, and assorted sharp spinning things actually turn wood into furniture.

w9 pic 1

Finished stool on work bench.

w9 pic 1

And it passes the weight test! It can hold heavier stuff than this water bottle.

Extra Credit: curved surface

This project explore structural press-fit design and form-driven CNC geometry. In particular, I incorporated curved surfaces along the stool legs and edges to improve ergonomics and visual softness, satisfying the curved-surface extra credit.

w6 pic 1

(This is only partial view of CAD, complete one below) Curved edge design on stool.

Torus Knot CAD Model

Wood board 3D preview.

Assignment Checklist
  • ✔ Designed, milled, and assembled a large (~meter-scale) object
  • ✔ CNC-milled from sheet material
  • Curved surfaces included (leg and edge profiles)
  • Three-axis toolpaths used

Final Result

Finished CNC stool

Finished CNC-milled stool. The structure is stabilized by horizontal stretchers and interlocking joints.

Design Intent

The stool is designed around a simple, repeatable frame: four vertical legs connected by horizontal stretchers and topped with a flat seat panel. The geometry emphasizes structural clarity while allowing the CNC process to define the final form.

Rather than keeping all edges rectilinear, I intentionally introduced curved outer profiles along the legs. These curves soften the visual weight of the stool and improve hand-feel, demonstrating how subtractive digital fabrication can still produce expressive forms.

CAD & CAM Workflow

First, I draw th outlines and design on Inkscape; then I exported it as DXF to Fusion 360.

Torus Knot CAD Model

Line Design in Fusion.

Torus Knot CAD Model

In Fusion 360, I used extrude to make DXF 3D.

Torus Knot CAD Model

CNC toolpath preview before machining.

  1. Modeled the stool in CAD with material thickness 11mm defined as a parameter, allowing easy tolerance adjustment.
  2. Designed press-fit joints sized based on measured stock thickness.
  3. Added curved leg profiles using sketch splines and fillets.
  4. Generated CNC toolpaths including 2D contours and three-axis finishing passes for curved surfaces.

CAM Parameters

I created two 2D contour toolpaths for each manufacturing setup. Compared to the default CAM settings, I modified the following parameters:

Setting Value
Tool 3/8" Flat Endmill
Spindle Speed 12,000 rpm
Feedrate 120 ft/min
Tab Width & Height 0.375"
Bottom Height −0.03" (to ensure cutting fully through the stock)

The slight negative bottom height ensured a clean cut-through across the full thickness of the OSB board.

CNC Fabrication

The stool was milled from a single sheet of material using a CNC router. All parts were cut in a single setup.

Torus Knot CAD Model

All parts after milling, before assembly.

A slightly deeper final pass ensured clean cut-through. Tabs were removed manually and edges were lightly sanded.

Assembly

The stool assembles through interlocking joints and friction fit. The horizontal members lock the legs in place and prevent racking.

Torus Knot CAD Model

Finished stool with the pieces cut out.

Torus Knot CAD Model

Assembled stool, it supports the heavy bag.

Failures & Fixes

One issue I encountered during fabrication was related to the tab geometry. The original tab length did not fit into the slots as I had expected based on the CAD model.

To resolve this, instead of relying on a single long tab, I switched to using three shorter tabs stacked vertically. Each tab corresponded to the standard OSB board thickness of approximately 11 mm, resulting in a combined engagement height of 33 mm (11 mm × 3). I wasn't able to avoid using hot glue; I used hot glue inside the slots and in between tabs to secure them more.

Reflection

This project reinforced the importance of material measurement, tolerance testing, and toolpath strategy in CNC fabrication. Small changes in joint sizing had a large impact on assembly quality.

If I were to iterate further, I would refine the curved profiles using additional finishing passes and explore alternative seat geometries.

Files

Week 7 — Input Devices

This week, I designed and soldered a new pcb board which should drive a 1.8 inch TFT screen, specifically for the Input Devices assignment. However, the screen was connected correctly but TFT display did not work. (Sorry Neil!) I then used one touch sensor GPIO (D1) on Seeed Studio XIAO ESP32-S3, to give a touch sensing reading on my serial monitor.

Group assignment: documentation and group work for this week

Torus Knot CAD Model

1.8 inch TFT screen + ESP32S3 schematic

Torus Knot CAD Model

My KiCAD skills have significantly improved; No cross paths and jumper wire resistors in sight!!

Torus Knot CAD Model

Milled.

Torus Knot CAD Model

Soldered and connected to 1.8 inch TFT (Left), compare to final project (Right) board which is designed to connect to 2.8 inch TFT.

ESP32-S3 capacitive touch on GPIO 2 (D1)

The Seeed XIAO ESP32-S3 exposes several GPIOs that support capacitive touch sensing. I used GPIO 2 (D1) in this test (any touch-capable GPIO would also work). The ESP32-S3 measures a capacitance-related value on that pin; touching the pin/pad with a finger increases the effective capacitance, producing a clear change in the reading.

How the test works

Code (Arduino)

// Capacitive Touch Test on Seeed XIAO ESP32-S3
    // Pin used: GPIO 2 (D1) in this build (touch-capable pin)

    void setup() {
      Serial.begin(115200);
      delay(1000);
      Serial.println("ESP32-S3 Capacitive Touch Test (GPIO 2 / D1)");
    }

    void loop() {
      // On many cores you can pass the GPIO number directly.
      // If your core requires T0/T1 style enums, map GPIO 2 accordingly.
      int val = touchRead(2);     // GPIO 2 (D1)
      Serial.println(val);
      delay(200);
    }

Note: Depending on your ESP32 core/library, touchRead() may accept either a GPIO number (as shown) or a touch-channel macro. The key behavior is the same: you should see a stable baseline value and a noticeable shift when touched.

The TFT backlight reliably turned on, but the display content did not render correctly. I suspect a driver/compatibility mismatch (i.e., the TFT module is not the exact controller I assumed), because I tested multiple libraries and initialization variants and still could not get stable pixels.

Week 8 — Output Devices

This week, I built an interactive, location-aware output system using a custom PCB (Seeed XIAO ESP32S3) driving a 2.8" SPI TFT display. The device detects where I am on MIT campus using Wi-Fi fingerprinting and displays context-aware messages, animations, and “Easter eggs” directly on the screen.

Group assignment: documentation and group work for this week

Big thanks to the mighty Q u e n t i n for teaching me how to display on TFT screen using Arduino!!

Finished milled PCB

TFT display soldered onto board, check finals week for my location tracking code!!

System Overview

The system continuously scans nearby Wi-Fi access points, compares their BSSIDs and signal strengths against known location fingerprints, and maps the result to a specific MIT building or landmark. Once a location is detected, the TFT screen updates with a customized message and visual effect.

  • Microcontroller: Seeed XIAO ESP32S3
  • Output device: 2.8" SPI TFT display (ILI9341)
  • Input source: Ambient Wi-Fi signals (RSSI + BSSID)
  • Interface: Visual text + animation on TFT
System overview diagram

System architecture: ESP32 scans Wi-Fi → infers location → updates TFT output.

System overview diagram

Set up with 2.8" SPI TFT display.

System overview diagram

PCB board.

System overview diagram

Schematic again for Seeed XIAO ESP32S3 driving 2.8" SPI TFT display (ILI9341).

Finished milled PCB

TFT display soldered onto board, check finals week for my location tracking code!!

Finished milled PCB

Location display.

Location Detection via Wi-Fi Fingerprinting

Instead of using GPS or cloud-based geolocation APIs, I implemented Google API (outdoors) + a local Wi-Fi fingerprinting approach(indoors), which works reliably indoors and does not require external services.

Each location (e.g. Building 38, Killian Court, Media Lab) is represented by a small set of known Wi-Fi access point BSSIDs. When the ESP32 detects one or more of these BSSIDs above a signal strength threshold, it infers the corresponding location.

Wi-Fi scanning code snippet

Arduino logic for scanning nearby Wi-Fi networks and matching BSSIDs. In this section for example, Building 38 is identified by the strong and consistent networks of EECS Shop and EECS Lab.

Wi-Fi scanning code snippet

Arduino logic for displaying matched position using boolean.

This approach allowed me to create a flexible, expandable location system: adding a new building only requires collecting its Wi-Fi fingerprints and defining a new detection function.

Files

TFT Output Design

The TFT display acts as the primary user-facing output device. When a location is detected, the screen displays a welcoming message, the user’s presence, and a themed visual effect.

Different locations trigger different color schemes and animations, reinforcing the idea of a “living map” that reacts to the environment.

TFT displaying location message

TFT display showing a detected location and custom message.

For example:

  • ✅Building 38: Green text with matrix-style animation
  • 🍀Killian Court: Formal welcome message and dome-inspired effects
  • 🧠Media Lab: Glitch effects and high-contrast visuals
  • 🎃Easter eggs: Fun proximity alerts (e.g. “Police Car on the Dome”)

Demo

Torus Knot CAD Model

My wifi scanning script for ESP32S3.

Torus Knot CAD Model

This displays nearby WiFi SSIDs live!

Concept

GPS indoors is unreliable, so for my final project I used a practical alternative: WiFi fingerprinting. As I walked around campus, I recorded a small set of “stable” SSIDs/BSSIDs seen consistently at specific locations. Later, my final project device checks the current scan and matches it against those fingerprints to infer where I am.

What I record per access point

  • SSID: human-friendly network name
  • BSSID: AP MAC address (more stable than SSID alone)
  • RSSI: signal strength (helps filter weak / far networks)

How it plugs into my final project

  • ESP32 scans WiFi periodically
  • Matches against location fingerprint lists
  • Displays “Building 38 / Media Lab / …” on TFT

Live Location Tracking!!

In the demo video below, I walk through different parts of campus while the device dynamically updates its output based on the detected location.

I added some effects such as Matrix Rain, Glitch Effect, Pulsing dome so it looks cool! Check out the final display effect below:

Interaction Flow

  1. The ESP32 continuously scans nearby Wi-Fi networks
  2. Strong signals are filtered and matched against known fingerprints
  3. A location is inferred based on detected BSSIDs
  4. The TFT screen updates with location-specific text and animations
  5. If no match is found, the system remains in an “unknown location” state

Reflection

This week pushed me to think about output devices as interfaces, not just displays. By tying the TFT output directly to sensed environmental data, the screen becomes an active participant in the system rather than a passive indicator.

The Wi-Fi fingerprinting approach also highlighted how much contextual information already exists in everyday signals, and how embedded systems can leverage them creatively without relying on heavy infrastructure.

Week 9 — Molding and Casting

This week, I made a silicone Labubu from a 3D print mold!

Group assignment: documentation and group work for this week

Big thanks to J e s s e , A i j i a , and A n t h o n y for great advice along the way and helped making this possible!

Molding

 Labubu 3D print mold negative model in fusion

Labubu 3D print mold negative model in fusion.

Labubu 3D print mold in PLA

Labubu 3D print mold in PLA.

I printed a negative mold of a labubu. Material is PLA (Layer = 2, Layer Height: 0.2-0.4mm, no support) They have registers and can snap together nicely.

Files

  • Please find my files here!
  • labubu_mold_smaller
  • (This is a dropbox link, you (and anyone with this link) can download from it, ignore "can't load this file", that's just b/c dropbox don't support stl preview.) If you can not download it, please email me at annieliy@mit.edu.

Pouring Holes

I use a flush cutter to create one bigger (which I later learned that it is NOT big enough!) hole for pouring, and one small hole for air to come out as I pour. The flush cutter is great, it cuts through PLA like butter!

Hot Glue Sealing

Per Jesse's advice, I used the hot glue gun to seal the mold, which prevents potential leakage. Hot glue can be later removed with alcohol.

Learning from Mistakes

If you have a closed mold like mine, please read this!! The pouring hole I created was too small, which made the pouring process very difficult. Any attempt to pour a larger flow of silicone caused the material to overflow from the hole. I had to stop frequently to wipe away the excess and then pour again very carefully, controlling the stream to be extremely thin. As shown, the opening is smaller than half the size of a thumbnail. I recommend making a pouring hole at least the size of a thumbnail. Because the small opening only allowed a very slow flow, it took me approximately 35 minutes to pour about 150 mL of silicone. The only silver lining was that the slow, steady pour prevented any air bubbles from forming.

Smoothing the layer lines: Bee's Wax Coating

I used the air heater to melt bee's wax, first apply a somewhat thin layer to the mold surface using the small brush, then use the air heater to melt the wax on mold surface, let it flow around to get a even, thin coat, then drip the excess wax back down to the plate.

Although as my first try the coating is not perfectly even, it does the job to blur a majority of the layer lines!

Casting

Demolding

First, I used alcohol to remove the hot glue sealing. I was briefly worried because the silicone outside my mold was sticky and not cured. Then I used a screw driver to pry open the mold (moment of truth!).

The finished product looked great after removing excess silicone! It cured nicely. The mold is also reusable, just re-apply bee's wax and hot glue.

To resemble the real Labubu (which is not green), I touched up the silicon labubu with acrylic pain (I used 3 main colors: Red + Green = Brown, Skin, White). It wasn't easy because acrylic paint don't stick onto silicon. However, after it dried, I applied a thick layer, and it looked fine! My silicon labubu now joins the lovely labubu family.

w9 pic 1

Acrylic painted silicon Labubu.

w9 pic 2 w9 pic 3 w9 pic 4

Seems familiar? Have you noticed my favicon? 😝

Week 11 — Networks & Communications

For Networks & Communications week, I built a wireless “scanner node” on an ESP32 that live-scans nearby WiFi networks and prints SSID/BSSID/RSSI. I then used the stable SSIDs as indoor “location fingerprints” for my final project: when the device sees familiar networks (e.g., EECS Labs/Shop for Building 38; Media Lab SSIDs for Media Lab), it displays the detected location on my final project PCB + TFT screen.

Assignment Requirements Checklist

Design, build, and connect wired or wireless node(s)

I used an ESP32 (Seeed XIAO ESP32S3) as a wireless node that performs active WiFi scanning.

With network or bus addresses

The scan outputs network identifiers: SSID (network name) and BSSID (AP MAC address), plus RSSI. BSSID serves as a stable address-like identifier for each access point.

And local input and/or output device(s)

Output is shown live via the Serial Monitor during data collection, and the same “fingerprints” are later used as an output on my final project (location name rendered on a TFT screen).

Demo

Torus Knot CAD Model

My wifi scanning script for ESP32S3.

Torus Knot CAD Model

This displays nearby WiFi SSIDs live!

Concept

GPS indoors is unreliable, so for my final project I used a practical alternative: WiFi fingerprinting. As I walked around campus, I recorded a small set of “stable” SSIDs/BSSIDs seen consistently at specific locations. Later, my final project device checks the current scan and matches it against those fingerprints to infer where I am.

What I record per access point

  • SSID: human-friendly network name
  • BSSID: AP MAC address (more stable than SSID alone)
  • RSSI: signal strength (helps filter weak / far networks)

How it plugs into my final project

  • ESP32 scans WiFi periodically
  • Matches against location fingerprint lists
  • Displays “Building 38 / Media Lab / …” on TFT

Hardware

Parts

  • Seeed XIAO ESP32S3 (wireless node)
  • USB-C cable (power + programming)
  • Computer with Arduino IDE (Serial Monitor output)

Wiring

No external wiring required for WiFi scanning itself. The ESP32 only needs power over USB-C. (In my final project, the same ESP32 is wired to a TFT for the location display.)

Torus Knot CAD Model

ESP32 board used for scanning.

Torus Knot CAD Model

Later integration: final PCB + TFT that displays detected location

Software

Workflow

  1. Program ESP32 with a WiFi scan sketch
  2. Open Serial Monitor to view live scan results
  3. Walk around campus and record stable SSIDs/BSSIDs per location
  4. Paste those fingerprints into my final project code for matching

Core code (WiFi scan)

Demo

Torus Knot CAD Model

My wifi scanning script for ESP32S3.

Torus Knot CAD Model

This displays nearby WiFi SSIDs live!

What the output looks like

Scan complete. SSID: EECS_Labs | BSSID: 9C:8C:D8:12:2C:E0 | RSSI: -71 SSID: EECS_Shop_24 | BSSID: 80:3F:5D:67:53:04 | RSSI: -62 SSID: Media Lab | BSSID: 5C:5B:35:EE:C0:95 | RSSI: -85

Location Fingerprints I Recorded

As I moved around campus, I noted a small set of networks that consistently show up in each location. This creates a lightweight indoor “signature” for each building.

Tip: SSIDs can be shared across buildings, so I prefer to record BSSIDs (AP MAC addresses) when possible. RSSI helps ignore very weak signals from far away.

How This Becomes Indoor Location Tracking

Matching logic (high level)

  • Scan nearby WiFi networks
  • Check if any BSSID/SSID matches a known location list
  • Optionally require RSSI above a threshold
  • Pick the best match (or “Unknown”)

Final project output

  • Location name displayed on TFT
  • Updates live as I move around indoors
  • Same ESP32 node; now paired with a display

Results

What I’d improve next

Week 12 — Interface & Application Programming

Touch-Driven Application on ESP32-S3

For Interface and Application Programming week, I wrote an embedded application that interfaces a user with a physical input device I made using the ESP32-S3’s built-in capacitive touch sensor. The application translates human touch into application-level state changes and provides immediate, human-readable feedback through a serial interface.

Rather than printing raw sensor values, the firmware implements event detection, state management, and user feedback, forming a complete interaction loop: user action → sensing → application logic → output.

Application behavior

The application treats the capacitive touch pin as a touch button. Each touch event advances the system through a set of predefined modes. The current mode is printed to the Serial Monitor, making the interaction explicit and observable.

  • Input: Human finger touching GPIO 2 (D1), a touch-capable pin
  • Processing: Thresholding + edge detection + mode state machine
  • Output: Human-readable messages in the Serial Monitor

This turns a raw hardware capability (capacitive sensing) into an interactive application that a user can control in real time.

Live user interaction

The following Serial Monitor output (captured in a video) shows the application responding to repeated touch events. Each touch advances the mode and immediately reports the new state to the user:

04:36:55.720 -> Current mode: DEBUG
    04:36:58.004 -> 
    04:36:58.004 -> Touch detected!
    04:36:58.004 -> Current mode: IDLE
    04:36:59.712 -> 
    04:36:59.712 -> Touch detected!
    04:36:59.712 -> Current mode: ACTIVE
    04:37:01.323 -> 
    04:37:01.323 -> Touch detected!
    04:37:01.323 -> Current mode: DEBUG
    04:37:05.098 -> 
    04:37:05.098 -> Touch detected!
    04:37:05.098 -> Current mode: IDLE
    04:37:06.902 -> 
    04:37:06.902 -> Touch detected!
    04:37:06.902 -> Current mode: ACTIVE
    04:37:09.595 -> 
    04:37:09.595 -> Touch detected!
    04:37:09.595 -> Current mode: DEBUG

This demonstrates a complete, repeatable interaction cycle where the user intentionally controls application behavior through physical touch.

Application code

The code below implements the application logic. Touch events are detected using a calibrated threshold based on observed sensor values, and a rising-edge detector ensures that each physical touch triggers exactly one state change.

// =======================================================
    // Interface & Application Programming
    // Capacitive Touch User Interface
    // Board: Seeed XIAO ESP32-S3
    // Input: Capacitive touch on GPIO 2 (D1)
    // Output: Serial Monitor
    // =======================================================
    
    const int TOUCH_PIN = 2;              // GPIO 2 (D1)
    const int TOUCH_THRESHOLD = 100000;   // Based on measured values
    
    bool lastTouchState = false;
    int mode = 0;
    const int NUM_MODES = 3;
    
    void setup() {
      Serial.begin(115200);
      delay(1000);
    
      Serial.println("========================================");
      Serial.println("ESP32-S3 Touch Interface Application");
      Serial.println("Touch the pad to change modes");
      Serial.println("========================================");
      printMode();
    }
    
    void loop() {
      int touchValue = touchRead(TOUCH_PIN);
      bool touched = (touchValue > TOUCH_THRESHOLD);
    
      // Detect new touch (rising edge)
      if (touched && !lastTouchState) {
        mode = (mode + 1) % NUM_MODES;
        Serial.println();
        Serial.println("Touch detected!");
        printMode();
      }
    
      lastTouchState = touched;
      delay(100);
    }
    
    void printMode() {
      Serial.print("Current mode: ");
      switch (mode) {
        case 0: Serial.println("IDLE"); break;
        case 1: Serial.println("ACTIVE"); break;
        case 2: Serial.println("DEBUG"); break;
      }
    }

Week 13 — Wildcard Week, Glass Engraving

Glass Engraving

For Wildcard Week, I used a glass engraving process to fabricate two small etched designs inside/through a clear glass prism block:

  • Bowtie Charm: a CAD model I designed and exported as an STL, then engraved into the glass.
  • Banana: a 3D scan I captured, cleaned into a watertight mesh, exported as an STL, then engraved into the glass.

Files

Big thanks to the mighty Q u e n t i n of course!!

Finished milled PCB

Bowtie charm stl.

Finished milled PCB

Bowtie charm is now living forever inside the glass prism!

Finished milled PCB

Additionally, a banana also lives forever inside another glass prism.