17 March 2026

I Vergara Final project - Concept proposal

 Story board # 1 - Productivity Pal

 

 

 Story board # 2 - Email scraper display

  

 Story board # 3 - Meal prep randomizer

 

Abstract / Concept statement

 For this project I will develop a Productivity Companion with RFID Tokens. The device is a small desk tool that allows a user to quickly switch between productivity modes using physical tokens. Each token represents a category such as focus timers, reminders, or motivational quotes. When the user taps a token on the device, an RFID reader recognizes it and the screen changes to the corresponding mode. A rotary knob allows the user to navigate options and the button confirms actions such as starting a timer.

 

Hardware List

Main components 

  • ESP32 microcontroller

  • Small TFT LCD display

  • RFID reader module

  • RFID tags to place inside round tokens

  • Rotary encoder with push button 

Extra components 

  • Breadboard

  • Jumper wires

  • Connection cables

3D components 

  • Enclosure for the device

  • Round tokens containing RFID tags

  • Printed dock to hold the tokens 

Software List

Development tools 

  • Arduino IDE

Programming

  • Component’s libraries

  • AI tools to help generate and debug code when needed

Design Tools

  • TinkerCAD for designing the enclosure and tokens

  • 3D printing slicer software used by the campus printers 

 

Project plan

Phase 1: Research and planning

  1. Review documentation for the ESP32, TFT display, and RFID reader.
  2. Confirm how the RFID reader detects different tags.
  3. Define the four tokens and their functions (Focus timer, Reminders, Quotes, Idle mode).

Phase 2: Basic hardware setup

  1. Connect the ESP32 to the breadboard.
  2. Connect the TFT display and test that it can show text.
  3. Connect the RFID reader and test reading RFID tags.
  4. Test the rotary encoder input.

Phase 3: Prototype interaction

  1. Write basic code to detect which RFID token is scanned.
  2. Display different text on the screen depending on the token.
  3. Add rotary encoder functionality to scroll through options.
  4. Add button functionality to confirm selections.

Phase 4: Productivity features

  1. Implement a simple focus timer (5, 10, and 25 minute options).
  2. Add simple reminders stored in the program.
  3. Add a set of motivational or stoic quotes.

Phase 5: Physical design

  1. Design the enclosure using TinkerCAD.
  2. Design round token cases that hold the RFID tags.
  3. Design a dock that holds the tokens next to the device.
  4. Print the enclosure and tokens using campus 3D printers.

Phase 6: Assembly

  1. Solder wires for permanent connections.
  2. Install the screen, RFID reader, and rotary encoder inside the enclosure.
  3. Assemble and mount all components in the case.

Phase 7: Testing and refinement

  1. Test that tokens reliably trigger the correct modes.
  2. Adjust the interface for readability on the small screen.
  3. Fix any wiring or code issues.
  4. Test the device in a desk environment.

Phase 8: Final presentation preparation

  1. Clean up the enclosure and improve the appearance if needed.
  2. Prepare demonstration scenarios showing how the tokens activate the system.
  3. Document the final device and interaction.

 


16 March 2026

Group 16: Scaffolding: Progress Review

Our controller has a conceptual connection to Five Nights at Freddy’s because it is made to simulate the computer that the player uses in FNAF and combines the other gameplay elements inside. 


The FNAF controller would consist of a board with various buttons coinciding with the buttons that are displayed in the game of FNAF, with each camera having its own button. It would also feature sliding pieces on both sides that could be opened or closed, and cover a light sensor that would open or close the doors within the game.

Beneath each door slider would be an old home-style switch that could be flicked to enable or disable the lights on both sides of the "Tablet".




Colored Sketch

PsuedoCode

define camerabuttons as list of digital inputs

define leftdoorslidersensor as analog input

define rightdoorslidersensor as analog input

define leftlightswitch as binary  digital input

define rightlightswitch as binary digital input


define led outputs within the bounds of the screen being on or not


Call leftdoorslidersensor

Call rightdoorslidersensor

Call leftlightswitch

Call rightlightswitch 

delay 


function handlecamerabuttons

    for each button in camerabuttons

        read button state

        if button is pressed then

            send signal: camera X pressed


function handledoorsliders


INT    leftsensorvalue

  INT  rightsensorvalue


    if leftsensorvalue < threshold then

        send signal: "left door closed"

    else

        send signal: "left door open"

    endif

    if rightsensorvalue < threshold then

        send signal: "right door closed"

    else

        send signal: "right door open"

    endif


end function




Team 3 Scaffolding: Progress Review

 Jesse Smith and Micahel Rowley

Minecraft Pickaxe Controller


Our controller is a Minecraft pickaxe that uses one of the game's most iconic tools and actions for input. The design connects directly to Minecraft's visual style, representing the diamond pickaxe with its color.  The player uses the pickaxe for mining, combat, and exploration. Instead of pressing ordinary buttons on a standard controller, the player performs motions that resemble using a tool. Buttons on the handle select actions such as placing blocks, mining, and interacting. The player then confirms those inputs by striking the pointed end of the pickaxe against a surface. Jumping is performed by tapping the butt end of the pickaxe against a surface. To control the camera, the player holds the look button on the handle and drags the pickaxe along a surface. This makes playing the game feel more interactive and enhances immersion. Movement will be done using a pad with directional buttons that remains on a table or floor. This is to give a separation between movement actions and aiming/interacting. 


Controller Sketch:





Schematic:


Pseudocode:


/*
Minecraft Pickaxe Controller Pseudocode


Goal:
Create a controller shaped like a Minecraft diamond pickaxe that allows
players to perform actions using physical motions instead of traditional
buttons.


-------------------------------------------------------
SETUP SECTION
-------------------------------------------------------


Initialize the Arduino board.


Define all input pins:
- Button for selecting "Place Block"
- Button for selecting "Mine / Attack"
- Button for activating "Look Mode"
- Sensor in the pickaxe tip for detecting strikes
- Sensor in the butt end for detecting taps (jump)


Initialize communication with the computer so the controller
can send keyboard and mouse inputs to Minecraft.


Set default action to NONE.



-------------------------------------------------------
MAIN LOOP
-------------------------------------------------------


Continuously run the following steps while the controller is powered.


1. Check the handle buttons to see which action the player selects.
2. Check the tip sensor to detect if the pickaxe hits a surface.
3. Check the butt sensor to detect if the player taps the bottom.
4. Check if the Look Mode button is being held.
5. If Look Mode is active, read motion input to control the camera.



-------------------------------------------------------
ACTION SELECTION
-------------------------------------------------------


If the player presses the "Place Block" button:
    Set the current action to PLACE_BLOCK.


If the player presses the "Mine / Attack" button:
    Set the current action to MINE_ACTION.


If no button is pressed:
    Keep the last selected action.



-------------------------------------------------------
TIP STRIKE DETECTION
-------------------------------------------------------


Read the sensor located in the pointed end of the pickaxe.


If the sensor detects a strong impact:
   
    Check which action is currently selected.


    If the action is PLACE_BLOCK:
        Send a RIGHT CLICK input to Minecraft
        (this places a block).


    If the action is MINE_ACTION:
        Send a LEFT CLICK input to Minecraft
        (this mines blocks or attacks enemies).


    Wait a short amount of time to prevent
    multiple accidental triggers.



-------------------------------------------------------
JUMP DETECTION
-------------------------------------------------------


Read the sensor located in the butt end of the pickaxe.


If the player taps the butt end against a surface:
   
    Send the SPACEBAR input to Minecraft
    (this makes the player jump).


    Add a short delay to avoid repeated jumps.



-------------------------------------------------------
LOOK MODE
-------------------------------------------------------


If the player holds the "Look Mode" button:


    Activate camera control.


    Read motion from the motion sensor
    (such as an accelerometer or tilt sensor).


    Convert motion values into mouse movement.


    Move the mouse cursor left/right/up/down
    to control the player's camera view.


If the Look Mode button is released:


    Stop sending camera movement.



-------------------------------------------------------
REPEAT
-------------------------------------------------------


Return to the beginning of the loop and
continue reading inputs from the controller.

*/

Scaffolding: Progress Review - Team 6

 The Yolk Controller is a custom flight controller designed for Star Wars: Squadrons, built around the fantasy of piloting an X-Wing or TIE Fighter in the heat of space combat. The controller takes the form of a yoke, the kind of dual-grip flight stick found in real aircraft cockpits, drawing a direct visual line between the player's hands and the experience of being a starfighter pilot in the Star Wars universe. Every input on the controller maps intentionally to the game's systems. Two potentiometers manage the ship's energy distribution across speed, laser power, and shields, mirroring the in-game resource triangle that skilled pilots constantly balance. A toggle switch physically flips shield coverage between the front and rear of the ship. The bumpers and triggers handle targeting, primary laser fire, secondary rocket fire, and system repair. Finally, the Circuit Playground Express reads the controller's real-world motion: rotating it steers the ship, pushing it forward increases thrust, and tilting it up or down moves the ship along the vertical axis. Every gesture feels like flying.

Controller Sketch:

psudocode:

//Final Group 6
//Marc Walker, Nicholas Smith

#include <Adafruit_CircuitPlayground.h>
#include <Adafruit_Circuit_Playground.h>

//declare variables for analog read values

void setup() {
  // start CircuitPlayground and Serial Monitor
  CircuitPlayground.begin();
  Serial.begin(9600);
  delay(1000);
}
void loop()
{
  float rPot;//Right Potentiometer
  float lPot;//Left Potentiometer
  int shields;//Read value of shields mapped between 0 and 100
  int speed;//Read value of speed mapped between 0 and 100
  int laserStrength;//Read value of laserStrength mapped between 0 and 100
  float vertical;
  float horizontal;
  vertical = Get CPE accelerometer Y value;
  horizontal = Get CPE accelerometer X value;
  shields = lPot;
  speed = rPot;
  laserStrength = (shields + laserStrength) / 2;
  bool LButton = true if Left button is pressed;
  bool RButton = true if Right button is pressed;
  bool LSwitch = true if Left switch is flipped;
  bool RSwitch = true if Left switch is flipped;
  if Positive value of vertical value greater than 0
  {
    Press W Key
  }
  if Negative value of horizontal value less than 0
  {
    Press A Key
  }
  if Negative value of vertical value less than 0
  {
    Press S Key
  }
  if Positive value of horizontal value greater than 0
  {
    Press D Key
  }
  if(LButton)
  {
    Fire Lasers
  }   if(RButton)
{ fire secondary weapons }
  if(LSwitch)
  {
    Shields enabled in front
  }
  else
  {
    Shields enabled in back
  }
  if(RSwitch)
  {
    Sublight enabled
  }
  else
  {
    Sublight disabled
  }
}

Scaffolding: Progress Review - Team 17

 Our controller is meant to look like a stun gun from Resident Evil. We chose this design because weapons play an important role in the gameplay, so making the controller resemble one helps connect the physical controller to the actions happening in the game. It also makes the experience feel more immersive, since the player is holding something that resembles a weapon while playing. Since the game focuses on survival and defending yourself from enemies, using a controller shaped like a weapon fits well with the theme and overall atmosphere.

The controller uses several inputs that align with the game’s mechanics. Buttons control forward and backward movement, while a potentiometer is used for left and right movement. A switch allows the player to run, and a sound sensor is used to shoot the weapon. Other sensors provide additional functions, such as using a tilt switch for quick turns and a temperature sensor to open the inventory. Pressing both movement buttons at the same time opens the menu, where the same controls can be used to navigate options.


#include <Adafruit_CircuitPlayground.h>

#include <Adafruit_Circuit_Playground.h>

#include <Keyboard.h>

#include <KeyboardLayout.h>

#include <Keyboard_da_DK.h>

#include <Keyboard_de_DE.h>

#include <Keyboard_es_ES.h>

#include <Keyboard_fr_FR.h>

#include <Keyboard_hu_HU.h>

#include <Keyboard_it_IT.h>

#include <Keyboard_pt_PT.h>

#include <Keyboard_sv_SE.h>


// Get Adafruit Circuit Playground libraries

// Get keyboard libraries


// Movement variables


// DECLARE variable equal to forward button

// DECLARE variable equal to backward button

// DECLARE variable equal to potentiometer

// DECLARE variable equal to switch

// DECLARE variable equal to tilt switch


// Shooting variables


// DECLARE variable equal to light sensor

// DECLARE variable light baseline equal to light sensor value

// DECLARE variable equal to sound sensor

// DECLARE variable sound baseline equal to sound sensor value


// Menu variables


// DECLARE variable equal to temperature sensor

// DECLARE boolean inventory open set to FALSE

// DECLARE boolean menu open set to FALSE


void setup() {

  //In setup:


  // Initialize libraries

  

}


void loop() {

  // While looping:


//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


  // Movement controls


  // READ forward button

  // IF forward movement button is pressed, THEN send forward input signal to computer


  // READ backward button

  // IF backward movement button is pressed, THEN send backward input signal to computer


  // READ potentiometer

  // MAP potentiometer so its values are split into three zones: Left, Middle, and Right zones

  // IF potentiometer values are in the left zone, THEN send player left rotation input signal to the computer

  // ELSE IF potentiometer values are in the right zone, THEN send player right rotation input signal to the computer

  // ELSE do nothing


  // READ switch

  // IF switch is equal to its on position, THEN send run/sprint input signal to the computer

  

  // READ tilt switch

  // IF tilt switch is equal to tilted, THEN send quick turn input signal to the computer


//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


  // Shooting controls


  // READ light sensor

  // CALCULATE and STORE difference of baseline subtracted from the light sensor value

  // MAP light zones using baseline

  // IF difference is in lower zone (darker), THEN send aim/ready weapon input signal to the computer


  // READ sound sensor

  // SET difference of baseline subtracted from the sound sensor value

  // MAP sound zones using baseline

  // IF difference is in upper zone (louder), THEN send shoot input signal to the computer


//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


  // Menu controls


  // READ temperature sensor

  // SET baseline variable equal to the input

  // IF temperature sensor values are greater than baseline (hotter) AND inventory open is TRUE, THEN send close inventory input signal to the computer and set inventory open to FALSE

  // ELSE IF temperature sensor values are greater than baseline AND inventory open is FALSE, THEN send open inventory input signal to the computer and set inventory open to TRUE


  // READ forward button and READ backward button

  // IF forward button AND backward button is pressed, THEN store time pressed

  // If time pressed subtracted from current time is greater than or equal to 3 seconds, THEN send escape menu input signal to the computer and set menu open to TRUE


  // READ forward button

  // If forward button is pressed AND inventory open is TRUE OR forward button is pressed AND menu open is true, THEN send scroll up input signal to the computer


  // READ backward button

  // If backward button is pressed AND inventory open is TRUE OR backward button is pressed AND menu open is true, THEN send scroll down input signal to the computer


  // READ potentiometer

  // IF potentiometer values are in the left zone AND inventory open is TRUE OR potentiometer values are in the left zone AND menu open is TRUE, THEN send left input signal to the computer

  // ELSE IF potentiometer values are in the right zone AND inventory open is TRUE OR potentiometer values are in the right zone AND menu open is TRUE, THEN send right input signal to the computer

  // ELSE do nothing


  // READ light sensor

  // CALCULATE and STORE difference of baseline subtracted from the light sensor value

  // IF difference is in the lower zone (darker), THEN send select input signal to the computer


}



 
Controls- 
Buttons – forward and backward movement; in menu, scroll up/move up and scroll down/move down
Potentiometer – move left and right; in menu, move left and right
Light sensor – ready weapon; in menu, select
Switch – run
Sound sensor – shoot
Temperature sensor – open inventory
Tilt switch – quick turn
Menu control – pressing both movement buttons at the same time opens the menu




Scaffolding: Progress Review - Team 8

The custom controller we settled on for the project was our treasure map design, which we made to expand upon the concept of the video game "Hidden Folks." Since the purpose of the is to explore the maps and find certain objects/people, we decided to use the classic "X" marks the spot treasure map. Since the game itself has quite a simple interface and controls, our team decided to create a visually immersive controller, using a similar art style to that of the game while also adding our own spin to it.

The control features two cylinders on each side, simultaneously representing a rolled-up scroll and providing sturdy handles for each hand. There is an "X" button in the center map portion of it, using a light sensor that maps to either "on" or "off" to select something within the game. There are two buttons for the "up" and "down" controls, and a touchpad that serves as the "left" and "right" controls as well.

Controller Sketch:



Schematic:

Pseudocode:
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);            
}

// --- Main loop ---
void loop() {
  // --- 1. Read sensors ---
  int lightValue = analogRead(PIN_LIGHT_SENSOR);    // 0-1023
  int zoomValue = analogRead(PIN_ZOOM);             // 0-1023
  int frUpValue = analogRead(PIN_FSR_UP);           // 0-1023
  int frownValue = analogRead(PIN_FSR_DOWN);        // 0-1023

  // Read tilt from accelerometer (X/Y/Z)
  int tilt = readTiltX();                           //pseudocode funct
  int tilty = readTiltY();                          //pseudocode funct
 
  // --- 2. Process zoom control ---
  int zoomLevel = map(zoom/alue, 0, 1023, ZOOM_MIN, ZOOM_MAX);
  // Optionally use tiltX/Y to modify zoom or cursor movement

  // --- 3. Check FSR pressure pads ---
  bool upPressed = fsrUpValue > FSR_THRESHOLD;
  bool downPressed = frownValue > FSR_THRESHOLD;
 
  // --- 4. Check light sensor to confirm action ---
  bool isDark = lightValue < LIGHT_THRESHOLD;

  // --- 5. Perform actions ---
  if (upPressed && isDark) {
    moveUp();                                        //user-defined function
  }

  if (downPressed && isDark) {
  moveDown();                                       // user-defined function
  }

  // Optional: use tilt to modify movement
  if (tiltX > TILT_THRESHOLD) {
  moveRight ();
  }
  else if (tilt ‹-TILT_THRESHOLD) {
  moveLeft();
  }

  // Optional: output values for debugging
  Serial.print("Zoom: "); Serial.print1n(zoomLeve1);
  Serial-print("FSR Up: "); Senial.println(fsrUpValue);
  Serial-print("FSR Down: "); Serial-println(fsrDownValue);
  Serial.print("Light: "); Senial.println(lightValue);
 
  delay(50);                                       // small delay for stability
 
  // --- Pseudocode functions ---
  int readTiltx) {
  // Read X-axis from accelerometer
  return accelerometer.getX(); // placeholder
  }

  int readTilty() {
  // Read Y-axis from accelerometer
  return accelerometer.getY(); // placeholder
  }

  void moveUp() {
  // Implement the up action
  }

  void moveDown() {
  // Implement the down action
  }

  void moveRight() {
  // Implement right action
  }

  void moveLeft() {
  // Implement left action
  }


Scaffolding: Progress Review: Team 11

Concept/Mechanics

Our selected game is Sonic Robo Blast 2 Kart (SRB2 Kart)

Our controller is styled to mimic the radio of a car, we thought it would be a fun and cool idea since the music of racing games help set the emotions of high speed cars going around the race track. We also just thought it was goofy to control a car with a radio (since it's the last thing you want to be 'playing' with when actually driving). When you 'increase the volume' by turning up the left knob, the player will accelerate. Some form of PWM will be used to add a sort of analog feel to this normally digital input. When you 'scroll the radio channels' by turning the right knob, the car turns left and right. Placed above the volume knob is a slider that has 2 inputs, left position for holding the drift button, right position for using the item, the middle position for neutral (no input so the player can continue driving normally).


Sketch


Schematic


Pseudo Code

// Setup
// Assign the Left Knob to Pin A1 (Speed)
// Assign the Right Knob to Pin A2 (Steering)
// Assign the Slider to Pin A3 (Item, Neutral, Drift)
// Create variables to hold the values for all three sensors
// Create a 'Stopwatch' variable starting at 0 to track time
// Create a 'Is W Pressed' variable starting as false

// Void loop
// 1. Run the "Read Sensors" function
// 2. Run the "Handle Speed" function
// 3. Run the "Handle Steering" function
// 4. Run the "Handle Slider" function

// Read Sensors
// Read Left Knob (Speed): Map the 0-1023 range to a 1-10 range (10 is max speed, 1 is braking)
// Read Right Knob (Steering): Map the 0-1023 range to a -127-127 range (analog range for controller)
// Read Slider: Map the 0-1023 range to a 1-30 range

// Handle Speed
// Check the board's internal stopwatch and save it as 'Current Time'
//
// If Mapped Speed is 10:
//    - Hold 'W' down constantly (Full Throttle)
//
// Else If Mapped Speed is 1:
//    - Hold 'S' (Brake)
//
//  Else (Ehe speed is anywhere between 2 and 9):
//       - Calculate a "Press Time" (Higher speed = longer press)
//       - Calculate a "Release Time" (Higher speed = shorter release)
//
//       - If 'W' is currently pressed AND the "Press Time" has run out:
//           - Release 'W'
//           - Reset the stopwatch
//
//       - Else If 'W' is currently released AND the "Release Time" has run out:
//           - Press 'W'
//           - Reset the stopwatch

// Handle Steering
// - Send the mapped Right Knob value to the Gamepad Left Stick X-Axis

// Handle Slider
// 
//    If Slider is between 1 and 9: 
// - Hold 'Space' (Use Item)
//       - Release 'Left Shift'
//
//    Else If Slider is between 11 and 19:
// - Release Space and Left Shift (Neutral)
//
//    Else If Slider is between 21 and 30:
// - Hold 'Left Shift' (Drift)
//       - Release 'Space'