Mechanical Engineering Portfolio — 2026

ALEX DiFranco

Future Mechanical Engineer  ·  Eastchester, NY
RC Systems  ·  Instrumentation  ·  Hardware Design  ·  Data Analysis

// student_data.sys
SchoolEastchester HS, NY
GPA3.9 UW / ~96 W
SAT1350
MajorMech. Engineering
ClassSenior — 2027
Portfolio● ACTIVE
// 01
About Me & Background
// 02
RC Dynamometer Project
// 03
Build Code
// 04
Photography
// 05
Contact
Alex DiFranco · Engineering Portfolio · 2026
Contact GitHub
01 — About Me & Background

How I Think
About Engineering

I've always liked figuring out how stuff actually works — not just reading about it, but taking it apart, measuring it, and seeing what actually makes it better instead of just guessing.

Honestly my interest in engineering isn't tied to one specific thing. I just think tradeoffs are interesting — weight vs. strength, efficiency vs. output, cost vs. performance. Those aren't abstract ideas to me, I'm literally dealing with them every time I build something.

The way I approach pretty much every project is the same: set a baseline, change one thing, measure what happened, repeat. That's basically what engineers and researchers do for a living. I just happen to be doing it with an RC car and a spreadsheet for now.

I want to study mechanical engineering and actually build high-performance mechanical systems someday. Everything I'm doing right now — classes, this project, all the data collection — is pointing toward that.

Alex DiFranco
Alex DiFranco
// profile.json
SchoolEastchester HS, NY
MajorMechanical Engineering
GPA3.9 UW / ~96 Weighted
InterestsEngineering, CAD, Robotics
MethodBuild → Test → Iterate
ClassSenior — 2027
⚙️
Systems Thinking
I want to actually understand how parts interact with each other — not just what each one does on its own, but why the whole thing behaves the way it does once real-world stuff gets involved.
📊
Data Over Instinct
Every change I make gets tracked and measured somehow. I don't really trust my gut on this stuff when I could just go get the actual number instead.
🔁
Purposeful Iteration
V2 needs to actually be better than V1 for a reason I can point to. If I can't explain why something's better, I'm not really engineering anything — I'm just guessing.
Outside the Workshop
Activities & Experience
RC Dynamometer — Self-Directed
Been designing and building a low-cost RC dynamometer to actually measure how my car performs instead of guessing. On V2 now — roller-based, magnetic floating sensor, fully hands-free. V3's next, and that one's about getting an actual horsepower number out of it.
Coding & Software Projects
Picking up programming through AP Computer Science, and getting more interested in using code for actual engineering stuff, like the dyno's data.
Student Government
Active member, helping out with school initiatives and just generally getting better at working with people alongside the technical stuff.
Photography
Automotive, industrial, architectural — whatever catches my eye honestly. Same analytical brain, just a different outlet.
Tennis — Eastchester HS
Competitive player. Honestly tennis works the same muscle engineering does for me — figure out the pattern, adjust, execute.
Academic Coursework
Completed AP Exams
AP Psychology — 5AP Computer Science A — 4AP Language — 4APUSH — 4
Current Courses — Senior Year
AP Physics CAP CalculusAP LiteratureAP BusinessAP MacroeconomicsAP ItalianRobotics
Academic Profile
3.9 GPA (UW)~96 WeightedSAT: 1350Class of 2027
About — Alex DiFrancoNext: Project →
02 — Featured Project

Building an RC
Dynamometer

Started as just a speed sensor, turned into an actual testing rig

// Self-Directed Engineering Project — 2024–2026
Problem: I wanted to know if changes I made to my RC car were actually doing anything, instead of just guessing off how it felt.

Solution: I'm building a low-cost RC dynamometer — basically a rig that measures how the car actually performs instead of me just guessing. The car's the test subject, but the dyno itself is really the project. It's touched mechanical design, wiring up sensors, and the physics behind RPM and speed. V0 was me just learning the sensor and sketching out ideas, V1 got it working, V2 made it way more consistent, and V3's next.

Engineering Roadmap
00
// Phase Zero — Complete
Learn the Sensor & Plan the Design
  • Goal: figure out how the Hall sensor actually works before I build anything
  • Wired it up on a breadboard, no mount or stand, just messing around with it
  • Sketched a few stand/clip ideas, didn't commit to any
  • Nothing working yet, just research and planning
01
// Phase One — Complete
Build the Dyno
  • Goal: can I actually measure RPM and wheel speed?
  • Made a simple desk-clip stand to keep the rig from moving around
  • Mounted a magnet to the wheel and a Hall sensor to catch it every rotation
  • Turns sensor pulses into RPM and top speed
02
// Phase Two — Complete
Build a Roller System
  • Goal: get consistent runs instead of one-off spins
  • Designed and built my own roller on ball bearings (it just ended up looking like a paint roller), went through three stand designs before one actually held still
  • Vibration was the real problem — switching to the smallest magnet I had fixed it completely
  • Sensor board floats on a 3D-printed mount held on with magnets — fully hands-free now
03
// Phase Three — Planned
Calculate Horsepower
  • Goal: actually get a horsepower number out of this thing, not just RPM and MPH
  • Means a lot more testing and getting into the physics side of it
  • Once V3's done, I'm probably calling it a day on this project
V0 — Learning & Planning
Hall Sensor Breadboard Test
Hall Sensor Breadboard Test
Early Stand Sketches
Early Stand Sketches
Clip Prototype Attempt
Clip Prototype Attempt

Honestly V0 wasn't much. No stand, no mount, nothing measuring anything yet. I just wired the sensor up on a breadboard to see how it worked, and sketched out a couple ideas for a stand/clip. That's it. It's the "figuring stuff out before I actually build it" stage. I actually had a clip designed and in the works, but it ended up way too tight and just didn't work. Also tried a circular mounting point up top, but it wasn't strong enough and slid around like crazy.

V1 — Original Build
Dyno V1 — Full Rig
Dyno V1 — Full Rig
Full Rig No Car
Full Rig No Car
Magnet on Wheel
Magnet on Wheel
Desk-Clip Stand
Desk-Clip Stand
Circuit Setup
Circuit Setup
01
// Frame & Mount
Desk-Clip Stand
Just a stand that clips into my desk so the rig stays put while the car's running. Not perfect, the desk itself flexes a little, but it's good enough to get a real reading off of.
02
// Sensing System
Hall Sensor + Magnet
Magnet taped to the wheel, Hall sensor propped nearby to pick it up every time it goes around. That's the whole electrical side, and it's basically what makes any of this possible.
03
// Measurement Method
RPM → Speed
The car's motor spins the wheel, I'm not spinning it by hand. What I am doing by hand is holding the chassis down, because it vibrates like crazy at full throttle. Pulses turn into RPM and top speed. Nothing fancy, but it works, and it's what V2 ends up building on.
How It Works — V1
01
Wheel Spins
Motor drives the wheel, I hold the chassis steady by hand
02
Magnet Passes Sensor
Magnet on the wheel sweeps by once per rotation
03
Electrical Pulse
Hall sensor fires a pulse every time the magnet passes
04
Pulses Counted
Controller counts pulses over a set window
05
RPM Calculated
Pulse count turns into RPM and wheel speed
Results — V1 Testing

Average RPM and average speed below are each from 5 separate 30-second trials.

Not gonna lie, this data isn't super clean. Takes the wheel a second to actually get up to speed, so early readings drag the average down a bit. There's also some wobble from the wheel itself and a little give in the desk. Not perfect, but it's a real starting point.

Lessons From Building V1
📐
Vibration Control First
A rig that shakes gives you garbage readings before you've even measured anything. Fixing the mounting problem first ended up mattering way more than the sensor itself.
🧲
A Clean Signal Beats a Complex One
One magnet, one Hall sensor, about as simple as it gets. But it gives a clean pulse every rotation, which is really all I needed to calculate RPM.
🔁
Prove the Concept Before Adding Complexity
Could've jumped straight to rollers and logging and graphs. Building the dumbest possible version first just confirmed the core idea actually works.
V2 — Roller System (Current Build)
Roller Rig — Full Build
Roller Rig — Full Build
Roller Rig — No Car
Roller Rig — No Car
Sensor Mount with Magnets
Sensor Mount with Magnets
Custom Roller on Bearings
Custom Roller on Bearings
Breadboard Wire Extension
Breadboard Wire Extension
01
// Frame & Drive
Custom-Built Roller
Built this roller myself, it just happens to look like a paint roller. Runs on ball bearings, mounted with hot glue. Went through three different stand designs before one actually held still under load.
02
// Vibration Fix
Tiny Magnet, Zero Vibration
Any magnet bigger than the smallest one I owned made the whole thing vibrate like crazy at speed. Dropped down to the tiny one and it just fixed itself. Zero vibration.
03
// Sensor Mount
Hands-Free Floating Mount
Press-fit 3D-printed bracket holds the sensor board. Strong magnet on the bracket, another one under the desk, so it just snaps into place. No holding anything anymore, just pull the trigger.
04
// Wiring Fix
Staples as Conductors
Roller's mounted at 90°, so the breadboard connections needed more reach to clear it. Plugged some spare staples straight into the breadboard as conductive material to extend things upward. Tape's only there to hold the tiny magnet on.
How It Works — V2
01
Pull the Trigger
Wheel drives the roller directly, completely hands-free
02
Roller Spins
The custom roller spins on ball bearings
03
Magnet Passes Sensor
Tiny magnet on the roller sweeps past the floating sensor mount once per rotation
04
Electrical Pulse
Hall sensor fires a pulse every time the magnet passes
05
RPM & MPH Calculated
Code counts pulses, throws out the first 5 seconds of startup, and turns the rest into RPM and MPH over a 30-second run
Results — V2 Testing

Average RPM and average speed below are each from 5 separate 30-second trials.

Way tighter than V1 honestly — the roller and floating sensor mount got rid of most of the noise. Run 5 dips a bit, which lines up with the battery starting to sag by the end. Turns out results depend a lot on battery voltage, so that's something I need to keep track of going forward.

Lessons From Building V2
🧲
Smaller Magnet, Zero Vibration
I figured a bigger magnet meant a stronger signal. Nope, it just threw the whole roller off balance at speed. Smallest magnet I owned ended up being the fix.
🧊
Let the Sensor Float
Holding the sensor board by hand was causing its own vibration. Mounting it on a magnetic press-fit bracket got my hands out of it completely, the rig kind of just runs itself now.
📎
Staples as Conductive Extensions
Didn't have the right length wire on hand, so I plugged spare staples right into the breadboard as conductive material to extend things up and clear of the roller. Cheap fix, but honestly kind of satisfying.
// What's Next
V3 is next, and probably the last one.

V3 is all about getting an actual horsepower number out of this thing instead of just RPM and MPH — more testing, more physics, more figuring it out as I go. Haven't started building it yet. Once V3's done, I think that's where I call it for this project.

Project — RC DynamometerNext: Build Code →
04 — Photography

Through the
Lens

Photography's kind of how I look at the world when I'm not building something — still pretty analytical about it honestly, I'm drawn to geometry, mechanical stuff, city textures. Click into any album below.

NATURE
// 50 photos
Open Album →
CARS
// 50 photos
Open Album →
CITIES
// 30 photos
Open Album →
Photography — Alex DiFrancoNext: Contact →
04 — Photography

Album

Album — Alex DiFrancoNext: Contact →
05 — Contact

Let's Build
Something.

Down to talk to engineers, admissions folks, or honestly anyone into mechanical systems, engineering, or just building stuff with their hands.

Alex DiFranco · Engineering Portfolio · 2026← Back to Home
03 — Build Code

Dyno Code

The actual code behind each version, as I build it

V0 — Just Testing the Sensor

This isn't even a real dyno sketch, it's literally just checking if the Hall sensor works. I'd pass a magnet over it and watch the Serial output flip between ON and OFF. This is also how I learned that only one side of the magnet actually triggers the sensor — flip it around and it does nothing.

// dyno_v0.ino
const int hallPin = 2;

void setup() {
  pinMode(hallPin, INPUT);
  Serial.begin(9600);
}

void loop() {
  if (digitalRead(hallPin) == LOW) {
    Serial.println("ON");
  } else {
    Serial.println("OFF");
  }

  delay(100);
}
V1 — Hall Sensor RPM & Speed Reader

Reads pulses off the Hall sensor, turns them into RPM and MPH, and tracks a full run on its own — an LED lights up while it's running and switches over once the wheel's been still for 2 seconds, so I get max/average stats per run without touching a laptop.

// dyno_v1.ino
const int hallPin = 2;

const int runningLed = 8;
const int finishedLed = 13;

volatile long pulseCount = 0;

unsigned long lastCalcTime = 0;
unsigned long lastPulseTime = 0;
unsigned long sessionStart = 0;

const int interval = 500;   // RPM update rate
const int timeout = 2000;   // stop if no pulses for 2 sec

const float wheelDiameterInches = 2.67717; // CHANGE THIS

bool sessionActive = false;

long rpmSum = 0;
int rpmSamples = 0;

int maxRPM = 0;
float maxMPH = 0;

void setup() {
  pinMode(hallPin, INPUT);

  pinMode(runningLed, OUTPUT);
  pinMode(finishedLed, OUTPUT);

  digitalWrite(runningLed, LOW);
  digitalWrite(finishedLed, HIGH);

  Serial.begin(9600);
  Serial.println("RC RPM System Ready");

  attachInterrupt(digitalPinToInterrupt(hallPin), countPulse, FALLING);
}

void loop() {
  unsigned long now = millis();

  // ---- RPM CALC ----
  if (now - lastCalcTime >= interval) {
    lastCalcTime = now;

    long pulses = pulseCount;
    pulseCount = 0;

    int rpm = pulses * 120; // 500ms window scaling

    if (rpm > 0) {

      lastPulseTime = now;

      // START SESSION
      if (!sessionActive) {
        sessionActive = true;

        digitalWrite(runningLed, HIGH);
        digitalWrite(finishedLed, LOW);

        sessionStart = now;

        rpmSum = 0;
        rpmSamples = 0;
        maxRPM = 0;
        maxMPH = 0;

        Serial.println("=== RUN STARTED ===");
      }

      rpmSum += rpm;
      rpmSamples++;

      if (rpm > maxRPM) {
        maxRPM = rpm;
      }

      float circumference = wheelDiameterInches * 3.14159;
      float mph = rpm * circumference * 60.0 / 63360.0;

      if (mph > maxMPH) {
        maxMPH = mph;
      }

      Serial.print("RPM: ");
      Serial.print(rpm);
      Serial.print(" | MPH: ");
      Serial.println(mph, 2);
    }
  }

  // ---- END SESSION ----
  if (sessionActive && (now - lastPulseTime > timeout)) {

    sessionActive = false;

    digitalWrite(runningLed, LOW);
    digitalWrite(finishedLed, HIGH);

    float avgRPM = (rpmSamples > 0) ? (float)rpmSum / rpmSamples : 0;

    float circumference = wheelDiameterInches * 3.14159;
    float avgMPH = avgRPM * circumference * 60.0 / 63360.0;

    float runTime = (now - sessionStart) / 1000.0;

    Serial.println();
    Serial.println("===== RUN COMPLETE =====");

    Serial.print("Run Time (s): ");
    Serial.println(runTime, 2);

    Serial.print("Average RPM: ");
    Serial.println(avgRPM, 1);

    Serial.print("Max RPM: ");
    Serial.println(maxRPM);

    Serial.print("Average MPH: ");
    Serial.println(avgMPH, 2);

    Serial.print("Max MPH: ");
    Serial.println(maxMPH, 2);

    Serial.println("========================");
    Serial.println();
  }
}

// ---- INTERRUPT ----
void countPulse() {
  pulseCount++;
}
V2 — Roller Dyno with Auto Run Detection

Rewrote this for the roller rig. A run starts on its own the second it picks up a Hall signal, throws out the first 5 seconds (that's just spin-up), and reports average/max RPM and MPH once the roller's been still for 2 seconds or 30 seconds have passed, whichever comes first.

// dyno_v2.ino
const int hallPin = 2;

const int runningLed = 8;
const int finishedLed = 13;

// =========================
// SETTINGS
// =========================

const unsigned long TEST_DURATION = 30000;     // 30 seconds
const unsigned long STARTUP_EXCLUSION = 5000;  // Ignore first 5 sec in averages

const unsigned long RPM_INTERVAL = 500;        // Calculate every 0.5 sec

const int ZERO_INTERVAL_LIMIT = 4;             // 4 × 500ms = 2 seconds

const float rollerDiameterMM = 25.0;            // Your roller diameter
const int magnetsPerRevolution = 1;

// =========================
// VARIABLES
// =========================

volatile long pulseCount = 0;

unsigned long lastCalcTime = 0;
unsigned long runStartTime = 0;

bool runActive = false;

int zeroIntervals = 0;

// Statistics
long rpmSum = 0;
int rpmSamples = 0;

int maxRPM = 0;
float maxMPH = 0;

// =========================
// SETUP
// =========================

void setup() {

  pinMode(hallPin, INPUT);

  pinMode(runningLed, OUTPUT);
  pinMode(finishedLed, OUTPUT);

  digitalWrite(runningLed, LOW);
  digitalWrite(finishedLed, HIGH);

  Serial.begin(9600);

  Serial.println();
  Serial.println("================================");
  Serial.println("      RC ROLLER DYNO V2");
  Serial.println("================================");
  Serial.println("Ready.");
  Serial.println("Waiting for first Hall signal...");
  Serial.println();

  attachInterrupt(
    digitalPinToInterrupt(hallPin),
    countPulse,
    FALLING
  );
}

// =========================
// MAIN LOOP
// =========================

void loop() {

  unsigned long now = millis();

  // ---------------------------------
  // CALCULATE RPM EVERY 500ms
  // ---------------------------------

  if (now - lastCalcTime >= RPM_INTERVAL) {

    lastCalcTime = now;

    // Safely copy pulse count
    noInterrupts();

    long pulses = pulseCount;
    pulseCount = 0;

    interrupts();

    // ---------------------------------
    // IF RUN IS NOT ACTIVE
    // ---------------------------------

    if (!runActive) {

      // First Hall signal starts the run
      if (pulses > 0) {

        runActive = true;

        runStartTime = now;

        zeroIntervals = 0;

        rpmSum = 0;
        rpmSamples = 0;

        maxRPM = 0;
        maxMPH = 0;

        digitalWrite(runningLed, HIGH);
        digitalWrite(finishedLed, LOW);

        Serial.println();
        Serial.println("================================");
        Serial.println("         RUN STARTED");
        Serial.println("================================");
        Serial.println("30 second timer started!");
        Serial.println();
      }

      return;
    }

    // ---------------------------------
    // RUN IS ACTIVE
    // ---------------------------------

    unsigned long elapsed = now - runStartTime;

    // ---------------------------------
    // CALCULATE RPM
    // ---------------------------------

    int rpm = 0;

    if (pulses > 0) {

      rpm = (pulses * 60000L) /
            RPM_INTERVAL /
            magnetsPerRevolution;

      // We got movement, reset zero counter
      zeroIntervals = 0;

    } else {

      // No pulses this interval
      rpm = 0;

      zeroIntervals++;

    }

    // ---------------------------------
    // CALCULATE MPH
    // ---------------------------------

    float circumferenceMM =
      rollerDiameterMM * 3.14159;

    float mph =
      rpm * circumferenceMM * 60.0 /
      1609344.0;

    // ---------------------------------
    // DISPLAY LIVE DATA
    // ---------------------------------

    Serial.print("Time: ");
    Serial.print(elapsed / 1000.0, 1);

    Serial.print("s | RPM: ");
    Serial.print(rpm);

    Serial.print(" | MPH: ");
    Serial.print(mph, 2);

    // Tell us if this is startup data
    if (elapsed < STARTUP_EXCLUSION) {
      Serial.println(" | STARTUP");
    } else {
      Serial.println(" | DATA");
    }

    // ---------------------------------
    // RECORD MAXIMUMS
    // ---------------------------------

    if (rpm > maxRPM) {
      maxRPM = rpm;
    }

    if (mph > maxMPH) {
      maxMPH = mph;
    }

    // ---------------------------------
    // RECORD AVERAGES
    // ---------------------------------

    // Only record averages after startup period
    if (elapsed >= STARTUP_EXCLUSION) {

      if (rpm > 0) {

        rpmSum += rpm;
        rpmSamples++;
      }
    }

    // ---------------------------------
    // STOP IF ZERO FOR 2 SECONDS
    // ---------------------------------

    if (zeroIntervals >= ZERO_INTERVAL_LIMIT) {

      Serial.println();
      Serial.println("No movement detected for 2 seconds.");

      finishRun(false);

      return;
    }

    // ---------------------------------
    // STOP AT 30 SECONDS
    // ---------------------------------

    if (elapsed >= TEST_DURATION) {

      finishRun(true);

      return;
    }
  }
}

// =========================
// FINISH RUN
// =========================

void finishRun(bool completed) {

  runActive = false;

  digitalWrite(runningLed, LOW);
  digitalWrite(finishedLed, HIGH);

  // Calculate averages
  float avgRPM = 0;

  if (rpmSamples > 0) {
    avgRPM = (float)rpmSum / rpmSamples;
  }

  float circumferenceMM =
    rollerDiameterMM * 3.14159;

  float avgMPH =
    avgRPM * circumferenceMM * 60.0 /
    1609344.0;

  Serial.println();
  Serial.println("================================");

  if (completed) {
    Serial.println("       30 SECOND RUN COMPLETE");
  } else {
    Serial.println("          INCOMPLETE RUN");
  }

  Serial.println("================================");

  Serial.print("Run Time: ");

  if (completed) {
    Serial.println("30.00 seconds");
  } else {
    unsigned long actualTime =
      millis() - runStartTime;

    Serial.print(actualTime / 1000.0, 2);
    Serial.println(" seconds");
  }

  Serial.println();

  Serial.println("--- RESULTS ---");

  Serial.print("Average RPM: ");
  Serial.println(avgRPM, 1);

  Serial.print("Average MPH: ");
  Serial.println(avgMPH, 2);

  Serial.print("Max RPM: ");
  Serial.println(maxRPM);

  Serial.print("Max MPH: ");
  Serial.println(maxMPH, 2);

  Serial.println();

  if (!completed) {
    Serial.println("Run was NOT counted as a valid");
    Serial.println("30-second test.");
  } else {
    Serial.println("Valid 30-second test.");
  }

  Serial.println();
  Serial.println("================================");
  Serial.println("Ready for next run.");
  Serial.println("================================");
  Serial.println();

  // Reset statistics for next run
  zeroIntervals = 0;
  rpmSum = 0;
  rpmSamples = 0;
  maxRPM = 0;
  maxMPH = 0;
}

// =========================
// HALL SENSOR INTERRUPT
// =========================

void countPulse() {

  pulseCount++;
}

V3's code goes here once I actually start building it — this'll be the horsepower calc.

Build Code — Alex DiFrancoNext: Photography →