Machine Building Project¶
This is the documentation page of Machine Building activity by Ahmad Tijjani Ishaq and Muhammad Jidda.
As for our individual Contribution it can be found here Jidda and Ahmed
Slide¶
Presentaion Video¶
Group Assignment Overview¶
This is the group assignment of the week.
- Design a machine that includes mechanism+actuation+automation+application;
- Build the mechanical parts and operate it manually;
- Document the group project and your individual contribution;
- Actuate and automate your machine;
- Document the group project and your individual contribution
MACHINE¶
Machines are mechanical devices designed to perform specific tasks by converting energy from one form to another. They are integral to human civilization and play a crucial role in various aspects of our daily lives, from simple tools to complex industrial equipment.
For our activity, We decided to make a pen plotter using CoreXY systems architecture.
Overview¶
CoreXY is a kinematic arrangement commonly used in the design of Computer Numerical Control (CNC) machines. It offers a mechanism for precise control of movement along two axes (X and Y) using a system of belts and pulleys. CoreXY provides advantages such as reduced moving mass, increased work speed, and improved work quality compared to other motion systems.
Building Mechanical part¶
The mechanical frame or body has to be in place before any automation can take place, hence we follow the following steps to make our mechanism.
Obtaining Components¶
Having had the design concept in mind, we started by obtaining the materials required by following the tempalte laid in the following reference to coreXY.
Some parts are purchased while others were made locally in the lab as some of them are 3D printed parts while some are acrylic materials.
The following parts were purchased. Credit to Koji Yamada/ Hajime Ito For documenting as shown below.
(1) Frame
SN | Item | Details | Qty | Remarks |
---|---|---|---|---|
1 | 2020Aluminum Extrusion(Y) | ex.400mm | 2P | |
2 | 2020Aluminum Extrusion(X) | ex.300mm | 2P | 3mm Acrylic spacer will be added |
3 | 2020Aluminum Extrusion(X) | ex.300mm | 1P | |
4 | Delta Socket | 4P | ||
5 | Socket Head Screws | M5x8mm | 8P | |
6 | T-Slot | M5 | 8P | |
7 | Non-stretch fishing line |
(2) Y-axis Pulley *2 units required for both sides.
SN | Item | Details | Qty | Remarks |
---|---|---|---|---|
8 | Socket Head Screws | M5x30mm | 1P | Inner wheels |
9 | V-slot Wheel | 1P | Inner wheels | |
10 | Spring Washer | M5 | 1P | Inner wheels |
11 | Washer | M5 | 1P | Inner wheels |
12 | Nut | M5 | 1P | Inner wheels |
13 | Socket Head Screws | M5x30mm | 1P | Outer wheels |
14 | V-Slot Wheel | 1P | Outer wheels | |
15 | Spring Washer | M5 | 1P | Outer wheels |
16 | Acrylic Spacer | 5mm | 1P | Outer wheels |
17 | Washer | M5 | 1P | Outer wheels |
18 | Nut | M5 | 1P | Outer wheels |
19 | Socket Head Screws | M5x8mm | 2P | |
20 | T-Slot | M5 | 2P |
(3) Y-axis Carriage *2 units required for both sides.
SN | Item | Details | Qty | Remarks |
---|---|---|---|---|
21 | Socket Head Screws | M5x40mm | 1P | Inner wheels |
22 | V-Slot Wheel | 1P | Inner wheels | |
23 | Spring Washer | M5 | 1P | Inner wheels |
24 | V-Slot Wheel | 1P | Inner wheels | |
25 | Spring Washer | M5 | 1P | Inner wheels |
26 | Nut | M5 | 1P | Inner wheels |
27 | Socket Head Screws | M5x30mm | 1P | Outer wheels |
28 | V-Slot Wheel | 1P | Outer wheels | |
29 | Nut | M5 | 1P | Outer wheels |
30 | Socket Head Screws | M5x8mm | 2P | |
31 | T-Slot | M5 | 2P |
(4) Y-axis Motor *2 units required for both sides.
SN | Item | Details | Qty | Remarks |
---|---|---|---|---|
32 | Stepper Motor | NEMA17 17HS4401 1.5A 42x42x38mm | 1P | Motor |
33 | Socket Head Screws | M3x8mm | 4P | Motor |
34 | Socket Head Screws | M5x30mm | 1P | Pulley |
35 | Bearing | D16xd5xH5 | 2P | Pulley |
36 | Spring Washer | M5 | 1P | Pulley |
37 | Washer | M5 | 1P | Pulley |
38 | Spring Washer | M5 | 1P | Pulley |
39 | Nut | M5 | 1P | Pulley |
40 | Socket Head Screws | M5x8mm | 2P | |
41 | T-Slot | M5 | 2P |
(5) X-axis Carriage
SN | Item | Details | Qty | Remarks |
---|---|---|---|---|
42 | Socket Head Screws | M5x30mm | 4P | |
43 | V-Slot Wheel | 4P | ||
44 | Nut | M5 | 1P | |
45 | Socket Head Screws | M3x15mm | 2P | Non-stretch fishing line holder |
46 | Washer | M3 | 2P | ditto. |
47 | Nut | M3 | 2P | ditto. |
(6) Limit Switch *2 units required for both X and Y axes.
SN | Item | Details | Qty | Remarks |
---|---|---|---|---|
48 | Limit Switch | 1P | ||
49 | Screw | M2x12mm | 2P | |
50 | Nut | M2 | 2P | |
51 | Socket Head Screws | M5x8mm | 1P | |
52 | T-Slot | M5 | 1P |
locally made materials
Some 3D printings were made as well as laser cutting.
SN | Item | Image | Purpose | Data | QTY |
---|---|---|---|---|---|
53 | Capstan Motor | For stepper motor | STL | 2P | |
54 | Capstan Pulley | For stepper motor | STL | 2P | |
55 | Stud 4pcs | For rolling pulley smoothly | STL | 5P | |
56 | X-axis Carriage | For mounting X-carriage | STL | 2P | |
57 | X-axis Carriage | For holding strings | STL | 1P | |
58 | Y-axis Pulley | For mounting pulleys on Y-axis | STL | 2P | |
59 | Y-axis Carriage | For mounting Y-carriage | STL | 2P | |
60 | Y-axis Motor | For mounting stepper motor | STL | 2P |
Assembly of parts¶
Parts obtained were assembled according to CoreXY systems architecture..
The frame is set and movements are tested. The coreXY mechanism is now set for use as base of our pen plotter.
Automation¶
To complete our machine building, we did the following.
- Build the pen holder.
- mill the electronic circuits board.
- Program the system.
Building the pen holder¶
The pen holder is primarilly our payload but we hope to add more payload to the coreXY device. We got the stl and laser cut part of the pen holder sytem from Nntuan Thigivers pen plotter files and the stl file can be accessed here
The penholder uses a servo motor to move the plotter hesd up and down. In addition to pen holder we mounted the limit switch at their respective possitions.
Milling The electronics board¶
The boards were milled, two similar for driving stepper and another one for driving the servo motor in the penholder.
indepth on how to mill the board can be found in our electronics production page.
we got the PNG files for stepper motor board design from coreXY reference page. and that of servo from the servo reference
Bill of material for milling the stepper board is as follows:
Part | Count | Info |
---|---|---|
Xiao RP2040 | 1 | |
H-Bridge TB67H451FNG | 2 | |
0.1uF 1206 | 2 | |
1uF 1206 | 2 | |
10uF 1206 | 2 | |
0.25R 1206 | 2 | |
120R 1206 | 2 | |
1x7 SMD Vertical Pinsocket | 2 | |
S4B-XH-SM4-TB or 1x4 SMD Pinheader | 1 | |
1x2 SMD Pinheader | 1 |
Bill of material for milling the servo board is as follows:
Part | Count | Info |
---|---|---|
Xiao RP2040 | 1 | |
1k smd res | 1 | |
10k smd res | 1 | |
1x7 SMD Vertical Pinsocket | 2 | |
S4B-XH-SM4-TB or 1x4 SMD Pinheader | 1 | |
1x3 SMD Pinheader | 1 | |
Light emitting diode smd | 1 | |
schottky diode smd CDBM1100-G | 1 | |
Mosfet | 1 | |
1x2 header for 12v power | 1 |
Additional Parts Needed before programming are: - USB 3.0 for multiple USB ports - USB type C cable for connection to PC
Programming the system.¶
The last step for our machine is the coding aspect. To proceed with this we did the following.
- Upload the Arduino firmware for stepper motor and servo motor
- Visit the Modular Thingsthing site to pair devices and do coding.
- test code individual servo and stepper to get familiar with how the framework behave.
- Then we did general coding, different version were generated for the pen plotter as a result of corrections and modification. visit kannai lab documentation for that.
Web Interface Implementation¶
We want the plotter to work with a canvas so that anything that is drawn on the canvas can be plotter by the machine. other features add is the ability to draw shapes like circle, square and star easily by clicking on the shape.
Sketch
Result We have deploy the modular-thing project locally and made some modification of the interface
Code
//https://fabacademy.org/2024/labs/kannai/Instruction/tips/machine_building/
// Array of [x,y] positions of drawing design
//Square
var ptsSquare = [[50,0],[50,50],[0,50],[0,0]];
//Star
var ptsStar = [[20,10],[30,50],[40,10],[10,40],[50,40],[20,10]];
//new code for circle
var centerX = 0; // X-coordinate of the center of the circle
var centerY = 0; // Y-coordinate of the center of the circle
var radius = 30; // Radius of the circle
var numPoints = 50; // Number of points to approximate the circle
var ptsCircle = [];
for (var i = 0; i < numPoints; i++) {
var angle = (i / numPoints) * 2 * Math.PI;
var x = centerX + radius * Math.cos(angle);
var y = centerY + radius * Math.sin(angle);
ptsCircle.push([x, y]);
}
// svg converter to point
var pathData = "M 20,10 L 30,50 L 40,10 L 10,40 L 50,40 Z"; // Path data from the SVG path
var pts = [];
// Regular expression to match commands (M, L, etc.) and numbers
var regex = /([MLHVCSQTAZmlhvcsqtaz])\s*(-?\d*\.?\d+)(?:\s*,\s*(-?\d*\.?\d+))?/g;
var match;
while (match = regex.exec(pathData)) {
var command = match[1];
var x = parseFloat(match[2]);
var y = parseFloat(match[3]);
switch (command) {
case 'M': // Move to
case 'L': // Line to
pts.push([x, y]);
break;
// Handle other commands as needed (e.g., curve commands)
}
}
console.log(pts);
// UI in View tab
var el = document.createElement("div");
el.style = `
padding: 10px;
`;
el.innerHTML = `<center>
<h2><font color="#5B9BAF">FabAcademy2024 - Machine Building</font></h2>
<img src="https://fabacademy.org/2024/labs/kannai/images/logo2022-yoko-w_transp.png" alt="FabLab Kannai" width="200">
<h3><font color="#5B9BAF">Pen Plotter Machine Interface</font></h3>
<p></p>
<hr>
<table>
<tbody>
<tr>
<td></td>
<td><button id="yPlus"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-caret-up-fill" viewBox="0 0 16 16">
<path d="m7.247 4.86-4.796 5.481c-.566.647-.106 1.659.753 1.659h9.592a1 1 0 0 0 .753-1.659l-4.796-5.48a1 1 0 0 0-1.506 0z"/>
</svg><br /> Y+ </button></td>
<td></td>
<td> </td><!-- space in 3rd column-->
<td><button id="zUp"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-caret-up-fill" viewBox="0 0 16 16">
<path d="m7.247 4.86-4.796 5.481c-.566.647-.106 1.659.753 1.659h9.592a1 1 0 0 0 .753-1.659l-4.796-5.48a1 1 0 0 0-1.506 0z"/>
</svg><br />Z+ </button></td>
</tr>
<tr>
<td><button id="xMinus"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-caret-left-fill" viewBox="0 0 16 16">
<path d="m3.86 8.753 5.482 4.796c.646.566 1.658.106 1.658-.753V3.204a1 1 0 0 0-1.659-.753l-5.48 4.796a1 1 0 0 0 0 1.506z"/>
</svg> X- </button></td>
<td><button id="Home" style="border: none; background: none; cursor: pointer;"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-house" viewBox="0 0 16 16">
<path d="M8.707 1.5a1 1 0 0 0-1.414 0L.646 8.146a.5.5 0 0 0 .708.708L2 8.207V13.5A1.5 1.5 0 0 0 3.5 15h9a1.5 1.5 0 0 0 1.5-1.5V8.207l.646.647a.5.5 0 0 0 .708-.708L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293zM13 7.207V13.5a.5.5 0 0 1-.5.5h-9a.5.5 0 0 1-.5-.5V7.207l5-5z"/>
</svg></button></td>
<td><button id="xPlus"> X+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-caret-right-fill" viewBox="0 0 16 16">
<path d="m12.14 8.753-5.482 4.796c-.646.566-1.658.106-1.658-.753V3.204a1 1 0 0 1 1.659-.753l5.48 4.796a1 1 0 0 1 0 1.506z"/>
</svg> </button></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td><button id="yMinus">Y- <br /><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-caret-down-fill" viewBox="0 0 16 16">
<path d="M7.247 11.14 2.451 5.658C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z"/>
</svg></button></td>
<td></td>
<td></td>
<td><button id="zDown"> Z- <br /><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-caret-down-fill" viewBox="0 0 16 16">
<path d="M7.247 11.14 2.451 5.658C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z"/>
</svg> </button></td>
</tr>
</tbody>
</table>
<hr>
<p><b>Draw Shapes</b></p>
<button style="border: none; background: none; cursor: pointer;" id="DrawCircle"><p></p><svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" class="bi bi-circle" viewBox="0 0 16 16">
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16"/>
</svg></button>
<button style="border: none; background: none; cursor: pointer;" id="DrawSquare"> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" class="bi bi-square" viewBox="0 0 16 16">
<path d="M14 1a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1zM2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2z"/>
</svg></button>
<button style="border: none; background: none; cursor: pointer;" id="DrawStar"> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" class="bi bi-star" viewBox="0 0 16 16">
<path d="M2.866 14.85c-.078.444.36.791.746.593l4.39-2.256 4.389 2.256c.386.198.824-.149.746-.592l-.83-4.73 3.522-3.356c.33-.314.16-.888-.282-.95l-4.898-.696L8.465.792a.513.513 0 0 0-.927 0L5.354 5.12l-4.898.696c-.441.062-.612.636-.283.95l3.523 3.356-.83 4.73zm4.905-2.767-3.686 1.894.694-3.957a.56.56 0 0 0-.163-.505L1.71 6.745l4.052-.576a.53.53 0 0 0 .393-.288L8 2.223l1.847 3.658a.53.53 0 0 0 .393.288l4.052.575-2.906 2.77a.56.56 0 0 0-.163.506l.694 3.957-3.686-1.894a.5.5 0 0 0-.461 0z"/>
</svg></button>
<br/>
<p></p>
<canvas style="border: 1px solid black;" id="drawingCanvas" width="100" height="100"></canvas><br>
<button id="convertBtn">Start Drawing</button>
<button id="resetBtn">Reset</button>
<pre id="pointsDisplay"></pre>
`;
//pen up initially
zUp();
//Synchronizer of two motors
var machine = createSynchronizer([motorA, motorB]);
//Definition of CoreXY Motion
async function goTo(x,y){
console.log(`Moving to (${x}, ${y})`);
await machine.absolute([1*(x+y),1*(x-y)]);
}
// Set button ID and click_event
el
.querySelector("#xPlus")
.addEventListener("click", () => {
xPlus();
})
el
.querySelector("#xMinus")
.addEventListener("click", () => {
xMinus();
})
el
.querySelector("#yPlus")
.addEventListener("click", () => {
yPlus();
})
el
.querySelector("#yMinus")
.addEventListener("click", () => {
yMinus();
})
el
.querySelector("#zUp")
.addEventListener("click", () => {
zUp();
})
el
.querySelector("#zDown")
.addEventListener("click", () => {
zDown();
})
el
.querySelector("#Home")
.addEventListener("click", () => {
goToHome();
})
el
.querySelector("#DrawCircle")
.addEventListener("click", () => {
delay(100);
drawCircle();
})
el
.querySelector("#DrawSquare")
.addEventListener("click", () => {
delay(100);
drawSquare();
})
el
.querySelector("#DrawStar")
.addEventListener("click", () => {
delay(100);
drawStar();
})
// canvas
const canvas = el.querySelector('#drawingCanvas');
const ctx = canvas.getContext('2d');
const convertBtn = el.querySelector('#convertBtn');
const resetBtn = el.querySelector('#resetBtn');
const pointsDisplay = el.querySelector('#pointsDisplay');
let points = [];
// Function to draw on canvas
function draw(event) {
var rect = canvas.getBoundingClientRect();
var x = Math.round(event.clientX - rect.left);
var y = Math.round(event.clientY - rect.top);
points.push([x, y]);
ctx.lineTo(x, y);
ctx.stroke();
}
// Function to clear the canvas
function resetCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
points = [];
pointsDisplay.textContent = '';
}
// Function to convert drawing to points
function convertToPoints() {
// pointsDisplay.textContent = JSON.stringify(points);
drawObj();
}
// Event listeners
canvas.addEventListener('mousedown', (event) => {
var rect = canvas.getBoundingClientRect();
var x = Math.round(event.clientX - rect.left);
var y = Math.round(event.clientY - rect.top);
ctx.beginPath();
ctx.moveTo(x, y);
canvas.addEventListener('mousemove', draw);
});
canvas.addEventListener('mouseup', () => {
canvas.removeEventListener('mousemove', draw);
});
convertBtn.addEventListener('click', convertToPoints);
resetBtn.addEventListener('click', resetCanvas);
render(el);
// document.addEventListener('DOMContentLoaded', () => {
// });
// When you start running this javascript code, the machine runs from here
//motor setting
motorA.setCurrent(1);
motorA.setStepsPerUnit(5);
motorB.setCurrent(1);
motorB.setStepsPerUnit(5);
machine.setPosition([0, 0]);// set present position as (X0,Y0)
//machine.setPosition(0, 0);// CHECK this syntax works or not
//var isAtEndStopX = false;
//console.log(isAtEndStopX);
// Function definition
async function goToHome(){
while(await motorB.getLimitState()){ // Limit switch at X- as Normally-Open
motorA.velocity(10);//move motorA CW
motorB.velocity(10); //move motorB CW
}
while(await motorA.getLimitState()){ // Limit switch at Y- as Normally-Open
motorA.velocity(10); //positive value means CW
motorB.velocity(-10);//negative value means CCW
}
motorA.velocity(0);
motorB.velocity(0);
machine.setPosition([0, 0]);
await delay(1000);
goTo(10,10 );
machine.setPosition([0, 0]);
await delay(1000);
}//end of goToHome
function xPlus() {
zUp();
machine.setPosition([0, 0]);
for ( i = 0; i<10; i++){
goTo(i,0 );
}
}
function xMinus() {
zUp();
machine.setPosition([0, 0]);
for ( i = 0; i<10; i++){
goTo(-i,0 );
}
}
function yPlus() {
zUp();
machine.setPosition([0, 0]);
for ( i = 0; i<10; i++){
goTo(0,i );
}
}
function yMinus() {
zUp();
machine.setPosition([0, 0]);
for ( i = 0; i<10; i++){
goTo(0,-i );
}
}
function zUp() {
// Code for the function goes here
console.log(servo.writeAngle(70));
}
function zDown() {
console.log(servo.writeAngle(90));
}
// new code
async function drawCircle(){
// await goTo(ptsCircle[0][0], ptsCircle[0][1]);
zDown();
for (let i = 0; i < ptsCircle.length; i++){
await goTo(ptsCircle[i][0], ptsCircle[i][1]);
await delay(200);
}
zUp();
}
async function drawSquare(){
//await goTo(ptsSquare[0][0], ptsSquare[0][1]);
zDown();
for (let i = 0; i < ptsSquare.length; i++){
await goTo(ptsSquare[i][0], ptsSquare[i][1]);
await delay(200);
}
zUp();
}
async function drawStar(){
// await goTo(points[0][0], points[0][1]);
zDown();
for (let i = 0; i < ptsStar.length; i++){
await goTo(ptsStar[i][0], ptsStar[i][1]);
await delay(200);
}
zUp();
}
async function drawObj(){
await goTo(points[0][0], points[0][1]);
zDown();
for (let i = 0; i < points.length; i++){
await goTo(points[i][0], points[i][1]);
await delay(200);
}
zUp();
}