Skip to content

12. Mechanical Design, Machine Design

Assignments and Assessment this week

Mechanical Design (part 1 of 2)

Group assignment:

Design a machine that includes mechanism + actuation + automation + application Build the mechanical parts and operate it manually Document the group project

Individual assignment:

Document your individual contribution

Machine Design (part 2 of 2)

Group assignment:

Actuate and automate your machine Document the group project

Individual assignment:

Document your individual contribution

Learning outcomes

Work and communicate effectively as a team Design, plan and build a machine Analyse and solve technical problems Recognise opportunities for improvements in the design

Have you answered these questions?

Documented the machine building process to the group page Documented your individual contribution to this project on your own website Linked to the group page from your individual page as well as from group page to your individual pages Shown how your team planned, allocated tasks and executed the project (Group page) Described problems and how the team solved them (Group page) Listed possible improvements for this project (Group page) Included your design files (Group page) You need to present your machine globally and/or include a 1 min video (1920x1080 HTML5 MP4) + slide (1920x1080 PNG) (Group page)

Group Assignment

Here is a group assignment page

handmade material inspection device

This week, we’re working on a project conceived by Koshi Kato (2026), with the goal of creating a homemade material inspection device that can automatically measure Young’s modulus.

Explanations of Young’s modulus and other related concepts can be found on the group page.

My design responsibilities included creating the material placement platform, the electronic components, and the program.

In the first week, our goal was to connect the components, get it working, and obtain measurements.

First Spiral

We decided to try modifying an onigiri machine using First Spiral.

First, I designed a support structure (Supports Creation) to hold the materials.

Next, I decided to learn how to operate each of the electronic components I would be using.

Stepper motor

How to connect A4988 Written by mirrorn from a blog about a homemade CNC machine and laser cutter.

How to connect DRV8825 Written by mirrorn from a blog about a homemade CNC machine and laser cutter.

Using the Arduino library AccelStepper

#include <AccelStepper.h>

const int  INTERFACE_TYPE = 1; 
const byte STEP_PIN       = D5; 
const byte DIR_PIN        = D4; 


const float MOVE_SPEED    = 2000; 

AccelStepper Xaxis(INTERFACE_TYPE, STEP_PIN, DIR_PIN);

void setup() {

  Xaxis.setMaxSpeed(10000);
  Xaxis.setSpeed(MOVE_SPEED); 
}

void loop() {

  Xaxis.runSpeed();
}

Screw pitch=2mm Screw lead=1 It moves 2mm per rotation.

A NEMA17 motor rotates once every 200 pulses.

The DRV8825 has 1/32 microstepping, a maximum voltage of 45V, and a rated current of 1.5A (maximum 2.5A).

Minimum distance traveled 2/200*32

Load cell & HX711 AD converter

Using the HX711 from the Arduino library

#include "HX711.h"

// HX711 circuit wiring
const int LOADCELL_DOUT_PIN = D9;
const int LOADCELL_SCK_PIN = D8;

HX711 scale;

void setup() {
  Serial.begin(115200);
  scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
}

void loop() {

  if (scale.is_ready()) {
    int reading = scale.read();

    //Serial.print("HX711_reading ");
    //Serial.print(",");
    Serial.println(reading);
    //Serial.println(",");

  } else {
    Serial.println("HX711 not found.");
  }

  delay(100);

}

future programing

Press switch L start | Lpless unit down | L Load Cell touch | L pless unit up | L pless unit Slow down | L Load Cell touch | L pless unit stop | L start meguaring Young’s Modulus | L pless unit Slow down | L serial print text to csv | L Load Cell not pressing | L Finish meguaring | L pless unit up to start point | L sleep | L Elce sleep

#include <AccelStepper.h>
#include "HX711.h"

// Pin configuration
const int INTERFACE_TYPE = 1;
const int STEP_PIN       = 2;
const int DIR_PIN        = 5;

const int BUTTON_PIN     = 3;

const int LOADCELL_DOUT  = 9;
const int LOADCELL_SCK   = 8;

// Parameters
const long  THRESHOLD     = 50000;// Test you are loadcell
const int   STEPS_PER_REV = 6400; // Total pulses for 1 rotation (1/32 step)
const int   BACK_REV      = 5;    // Reversal amount (rotations)
const float MOVE_SPEED    = 2000.0;

AccelStepper Xaxis(INTERFACE_TYPE, STEP_PIN, DIR_PIN);
HX711 scale;

// Control state machine
enum State { WAIT_BUTTON, MOVING, REVERSING };
State currentState = WAIT_BUTTON;

void setup() {
  Serial.begin(115200);
  pinMode(BUTTON_PIN, INPUT_PULLUP); // Button between pin 3 and GND
  scale.begin(LOADCELL_DOUT, LOADCELL_SCK);

  Xaxis.setMaxSpeed(12800);
  Xaxis.setAcceleration(5000);
  Xaxis.setMinPulseWidth(2); // For RP2040 high speed stability
}

void loop() {
  switch (currentState) {
    case WAIT_BUTTON:
      // Start sequence on button press
      if (digitalRead(BUTTON_PIN) == LOW) {
        delay(200); // Debounce
        Xaxis.setSpeed(MOVE_SPEED);
        currentState = MOVING;
      }
      break;

    case MOVING:
      // Constant speed rotation
      Xaxis.runSpeed();

      // Load cell trigger check
      if (scale.is_ready() && scale.read() > THRESHOLD) {
        // Calculate 5-rev reverse target from current position
        long target = Xaxis.currentPosition() - (long)(STEPS_PER_REV * BACK_REV);
        Xaxis.moveTo(target);
        currentState = REVERSING;
      }
      break;

    case REVERSING:
      // Move with acceleration to target
      if (Xaxis.distanceToGo() != 0) {
        Xaxis.run();
      } else {
        // Sequence finished
        currentState = WAIT_BUTTON;
      }
      break;
  }
}
#include <AccelStepper.h>
#include "HX711.h"

const int INTERFACE_TYPE = 1;
const int STEP_PIN       = D9;
const int DIR_PIN        = D8;

const int BUTTON_PIN     = D10;

const int LOADCELL_DOUT  = D4;
const int LOADCELL_SCK   = D5;

const long  THRESHOLD      = 50000;
const int   STEPS_PER_REV  = 6400; 
const int   BACK_REV       = 5;
const float MOVE_SPEED     = 2000.0;
const float SLOW_SPEED     = 500.0;
const float SCREW_PITCH    = 2.0;

AccelStepper Xaxis(INTERFACE_TYPE, STEP_PIN, DIR_PIN);
HX711 scale;

enum State { WAIT_BUTTON, MOVING, REVERSING, REPROACH, MEASURING };
State currentState = WAIT_BUTTON;

long zeroStepPos = 0;
long lastLoad    = 0;

void setup() {
  Serial.begin(115200);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  scale.begin(LOADCELL_DOUT, LOADCELL_SCK);
  Xaxis.setMaxSpeed(12800);
  Xaxis.setAcceleration(5000);
  Xaxis.setMinPulseWidth(2);
}

void loop() {
  long currentLoad = scale.is_ready() ? scale.read() : 0;

  switch (currentState) {
    case WAIT_BUTTON:
      if (digitalRead(BUTTON_PIN) == LOW) {
        delay(200);
        Xaxis.setSpeed(MOVE_SPEED);
        currentState = MOVING;
      }
      break;

    case MOVING:
      Xaxis.runSpeed();
      if (currentLoad > THRESHOLD) {
        Xaxis.moveTo(Xaxis.currentPosition() - (long)(STEPS_PER_REV * BACK_REV));
        currentState = REVERSING;
      }
      break;

    case REVERSING:
      if (Xaxis.distanceToGo() != 0) {
        Xaxis.run();
      } else {
        Xaxis.setSpeed(SLOW_SPEED);
        currentState = REPROACH;
      }
      break;

    case REPROACH:
      Xaxis.runSpeed();
      if (currentLoad > THRESHOLD) {
        zeroStepPos = Xaxis.currentPosition();
        lastLoad = currentLoad;
        currentState = MEASURING;
      }
      break;

    case MEASURING:
      Xaxis.runSpeed();
      float distance = (Xaxis.currentPosition() - zeroStepPos) * (SCREW_PITCH / (float)STEPS_PER_REV);

      Serial.print(distance, 4); 
      Serial.print(",");
      Serial.println(currentLoad);

      if (currentLoad < lastLoad) {
        Xaxis.setSpeed(0);
        currentState = WAIT_BUTTON; 
      }
      lastLoad = currentLoad;
      break;
  }
}

It is not working programs because the sensor readings were interfering with the motor’s movement. However, we wanted to read the sensor readings as precisely as possible.

As a solution, our instructor,Kae Nagano (2019), offered a good suggestion.

Since our microcontroller was an RP2040, we used a second core (setup 1, loop 1) and created a program that constantly measured force and distance while activating the motor when a button was pressed.

// The normal, core0 setup
#include <AccelStepper.h>
#include "HX711.h"

const int INTERFACE_TYPE = 1; 
const int STEP_PIN = D5; 
const int DIR_PIN = D4; 

const int LOADCELL_DOUT_PIN = D1;
const int LOADCELL_SCK_PIN = D0;
long HX711_reading = 0;
int sensorValue = 0;

const int analogInPin = A2;

int switch_status = 1;
int machine_status = 0;
int Inverted_status = 1;
const int SW_PIN = D10;

const float MOVE_SPEED = 5000; 
HX711 scale;

AccelStepper Xaxis(INTERFACE_TYPE, STEP_PIN, DIR_PIN);

void setup() {
  pinMode(SW_PIN,INPUT_PULLUP);
  Xaxis.setMaxSpeed(10000);
  Xaxis.setSpeed(MOVE_SPEED); 
  Serial.begin(115200);
}

void loop() {
  int current_switch = digitalRead(SW_PIN);
  //Serial.println(current_switch);
  // switch was plessd
  if (current_switch != switch_status && current_switch == LOW) {
    if (machine_status == 0) {
      machine_status = 1;
      Inverted_status = 1;
    } else {
      machine_status = 0;
      Inverted_status = -1;
    }

    Serial.print("machine_status = ");
    Serial.print(machine_status);
    Serial.print("  SW = ");
    Serial.println(current_switch);

    delay(200);  
  }

  // moveing moter
  if (machine_status == 1) {

    //Serial.println(machine_status);
    //for(int i=0;i<100;i++){
    Xaxis.runSpeed();
    //}
  }else{
    Xaxis.disableOutputs();
  }

  switch_status = current_switch;
}

// Running on core1

void setup1() {
  Serial.begin(115200);
  scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
}

void loop1() {

  if (scale.is_ready()) {
    HX711_reading = scale.read();
    sensorValue = analogRead(analogInPin);
    Serial.print(600);
    Serial.print(",");
    Serial.print(sensorValue);
    Serial.print(",");
    Serial.println(HX711_reading);
    //Serial.println(",");

  } else {
    Serial.println("HX711 not found.");
  }

  delay(100);

}
Even with this program, the motor’s movement was still erratic. Ultimately, we sent the motor movement part to the AI ​​Gemini for verification.

The motor movement in this program is erratic. In this program, when the switch is pressed, the motor rotates, and based on the data measured in Loop 1 of another core, if a certain threshold is exceeded, the motor stops and reverses rotation. The switch should start the motor when it is not operating, and stop the motor when it is operating, regardless of whether it is moving forward or backward.

#include <AccelStepper.h>
#include "HX711.h"

// Pin settings
const int INTERFACE_TYPE = 1; 
const int STEP_PIN = D5; 
const int DIR_PIN = D4; 
const int LOADCELL_DOUT_PIN = D1;
const int LOADCELL_SCK_PIN = D0;
const int SW_PIN = D10;
const int analogInPin = A2;

// Variables
long HX711_reading = 0;
int sensorValue = 0;
int switch_status = 1;
int machine_status = 0; // 0:Idle, 1:Forward(Down), 2:Reverse(Up)

// Custom settings
const long THRESHOLD = 250000;    
const float MOVE_SPEED = 10000;   // Forward speed
const float ESCAPE_SPEED = 5000;  // Reverse speed

HX711 scale;
AccelStepper Xaxis(INTERFACE_TYPE, STEP_PIN, DIR_PIN);

void setup() {
  pinMode(SW_PIN, INPUT_PULLUP);
  Xaxis.setMaxSpeed(10000);
  Serial.begin(115200);
}

void loop() {
  int current_switch = digitalRead(SW_PIN);

  // --- 1. Switch Control ---
  if (current_switch != switch_status && current_switch == LOW) {
    if (machine_status == 0) {
      machine_status = 1; // Start movement
      Xaxis.setSpeed(MOVE_SPEED);
      Serial.println("START: FORWARD");
    } else {
      machine_status = 0; // Stop movement
      Xaxis.stop();
      Xaxis.disableOutputs();
      Serial.println("STOP: BY SWITCH");
    }
    delay(200); // Debounce
  }
  switch_status = current_switch;

  // --- 2. Motor Logic ---
  if (machine_status == 1) {
    // Forward mode: check for overload
    if (HX711_reading < -THRESHOLD) {
      machine_status = 2; // Auto-reverse
      Xaxis.setSpeed(-ESCAPE_SPEED); 
      Serial.println("!!! OVERLOAD: REVERSING !!!");
    } else {
      Xaxis.runSpeed();
    }
  } 
  else if (machine_status == 2) {
    // Reverse mode: keep moving back
    Xaxis.runSpeed();
  } 
  else {
    // Stop mode
    Xaxis.disableOutputs();
  }
}

// --- Data Acquisition (Core 1) ---
void setup1() {
  scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
}

void loop1() {
  if (scale.is_ready()) {
    HX711_reading = scale.read();
    sensorValue = analogRead(analogInPin);

    // Print data for Serial Plotter
    Serial.print(600);
    Serial.print(",");
    Serial.print(sensorValue);
    Serial.print(",");
    Serial.println(HX711_reading);
  }
  delay(100);
}

homemade CNC machine and laser cutter