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);
}
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);
}