9. Mechanical Design, Machine Design¶
This week, we are working on a plotting robot - Blot, which is presented by Leo and his teamates,comes from Hack Club. This blot was developed with support from MIT’s Center for Bits and Atoms.
Click here to our group work.
About the Blot¶
It is a custom CNC drawing machine. The code is written via Arudino IDE to drive the servo, which controls the movement of the robotic arm through the timing belt, and then performs artistic creations such as writing and painting.
Blot Overview¶
Below picture is from here.
3D model of Blot¶
This is the 3D model of the project
The Blot is made of 6 unique 3d printed parts. To 3D print the parts, you can access *.STL
files here
BOM of Blot¶
Below pictures from here;
You can find BOM here, and assembly guide here.
PCB design and Firmware¶
The source files for the control PCB
The source files for the power delivery PCB
The firmware for the Blot control board
Small Change we make to Blot¶
For 3D printed part,We can print one 3d print part and one metal part (above part) or we can combine together and print. So to make it simple ,our mentor Mr.Salman help to combine and 3d printed to avoid the extra metal part.
My Contribution to the Machine Build Project¶
Collecting components with team¶
We configured the materials here, most of them have been collected, but some are still missing.
- so we visited various hardware stores online and offline to collect some components
-
We finally disassembled some parts from a 3D printer and finally collected them all
-
During the assembly process, I tested the motor’s paddle size and found that it was big, not the wanted size.
The required size is: Servo + Arm (25mm cable), so I bought a small motor.
Record the assembly process¶
-
Assemble the Servo part and 3D parts
-
Adjust the eccentric nuts on the carriage to make it loosely fit on the rail.
-
Threading the Timing Belt
In this way, the idea for the movement control of the Blot is:
The control principle is:
When the Timing Belt Pulley on the left and right sides move in the same direction, control the movement of the x-axis:
The left wheel moves clockwise, the right wheel moves clockwise, and the x-axis moves to the left;
The left wheel moves counterclockwise, the right wheel moves counterclockwise, and the x-axis moves to the right;
When the Timing Belt Pulley on the left and right sides move in opposite directions, control the movement of the y-axis:
The left wheel moves counterclockwise, the right wheel moves clockwise, and the y-axis moves downward;
The left wheel moves clockwise, the right wheel moves counterclockwise, and the y-axis moves upward;
For more details of Threading the Timing Belt, please check here.
Assist the testing process¶
During the process, we need to understand the various interfaces of the a4988 Stepper Motor Driver and connect them correctly to the breadboard for testing and coding. I recorded the interface information of this driver and assisted in some coding work.
When using the A4988 stepper motor driver module to drive the Nema17 stepper motor, you need to correctly connect the 4 pins (2 phases and 4 wires) of the motor to the driver module. The Nema17 stepper motor usually has 6 pins, but 4 of them are the main coil pins. In order to understand how to connect effectively, I used the ChatGPT tool and tried the subsequent connections and codes.
Then we tried tested.
After we connect the A4988 stepper motor driver to the XIAO RP2040, we need to write code and control the Nema 17 stepper motor to run in the specified mode. I consulted some materials and wrote some code, then wrote down the control logic and submitted it to chatGPT. The following is the code it provides.
#include <AccelStepper.h>
// 定义步进电机的步数
#define STEPS 200
// 定义引脚
#define STEP_PIN 10
#define DIR_PIN 9
// 创建一个AccelStepper对象
AccelStepper stepper(AccelStepper::DRIVER, STEP_PIN, DIR_PIN);
void setup() {
// 设置步进电机的速度(RPM)
stepper.setMaxSpeed(1000);
// 初始化串口监视器(可选)
Serial.begin(9600);
}
void loop() {
// 读取电位计的值,并将其映射到0-500之间
int potVal = map(analogRead(A0), 0, 1024, 0, 500);
// 设置步进电机的速度
stepper.setSpeed(potVal);
// 顺时针移动10步
stepper.move(10);
stepper.runToPosition();
// 停两秒
delay(2000);
// 逆时针移动10步
stepper.move(-10);
stepper.runToPosition();
// 再停两秒
delay(2000);
}
We try debug:
We combined with the initial code of the project, and try many times of testing, we finally build our Plotting Blot!!!
Our Plotting Blot Demo Video¶
Later PCB board production¶
According to the assignment requirements, we are going to make the PCB. The original PCB design comes from our teamate Crail, he’s not available in his working hours, so I helpd to mill the board with our CNC machine and the V-bits that we have in our lab. It turned out to be like not easy if you want to be success in the first trial. In fact , I try mill it for 3 times due to different issues! And we finally succeed in the 4th times!
Later PCB board production
- Divide the PCB board into small pieces: The PCB board size provided by our space is too large to fit into the CNC machine. So I found a saw to cut it into small pieces (the saw was not easy to use and it was easy to saw crooked, so I used scissors to cut it later);
Use tape to hold the PCB in place
- The PCB board needs capacitors in the later production, so I helped collect capacitors and other components
- The first Trace G-code had problems. I found that the machine was running dry and did not cut the board. I checked the G-code and found that it was because the Z axis was set to -0.1016, which was too small, so I regenerated the G-code file.
- The second time was Edge’s G-code. The value of the Y axis exceeded the designed area. I confirmed that the zero point was cleared and regenerated the G-code file
- The third time seemed to be smooth, but when it came to the drilling part, because the cutter head was worn out and the new cutter head was not replenished in time, I used the old cutter head and the drilling failed.
Finally, the 4th time the PCB board was successfully made!
Source code of our Plotting Blot¶
This is Arduino code, for drawing a oblique line, operating motors, moving the same time on the X-axis and Y-axis.
#include <Arduino.h>
const int STEP_PIN_X = D10;
const int DIR_PIN_X = D9;
const int STEP_PIN_Y = D8;
const int DIR_PIN_Y = D7;
const float STEPS_PER_MM = 80.0; // Adjust this value based on your stepper motor's steps per millimeter
const float LINE_LENGTH_MM = 100.0; // Length of the line in millimeters
void setup() {
pinMode(STEP_PIN_X, OUTPUT);
pinMode(DIR_PIN_X, OUTPUT);
pinMode(STEP_PIN_Y, OUTPUT);
pinMode(DIR_PIN_Y, OUTPUT);
}
void loop() {
// Draw a line along the X-axis
drawLine(0, 0, LINE_LENGTH_MM, 0);
delay(1000); // Pause for 1 second
// Draw a diagonal line
drawLine(0, 0, LINE_LENGTH_MM, LINE_LENGTH_MM);
delay(1000); // Pause for 1 second
// Move back to the origin
drawLine(LINE_LENGTH_MM, LINE_LENGTH_MM, 0, 0);
delay(1000); // Pause for 1 second before repeating
}
void drawLine(float x0, float y0, float x1, float y1) {
// Convert millimeters to steps
int x0Steps = round(x0 * STEPS_PER_MM);
int y0Steps = round(y0 * STEPS_PER_MM);
int x1Steps = round(x1 * STEPS_PER_MM);
int y1Steps = round(y1 * STEPS_PER_MM);
int dx = abs(x1Steps - x0Steps);
int dy = abs(y1Steps - y0Steps);
int sx = (x0Steps < x1Steps) ? 1 : -1;
int sy = (y0Steps < y1Steps) ? 1 : -1;
int err = dx - dy;
while (true) {
if (x0Steps == x1Steps && y0Steps == y1Steps) break;
int e2 = 2 * err;
if (e2 > -dy) {
err -= dy;
x0Steps += sx;
digitalWrite(DIR_PIN_X, (sx > 0) ? HIGH : LOW);
digitalWrite(STEP_PIN_X, HIGH);
delayMicroseconds(500);
digitalWrite(STEP_PIN_X, LOW);
delayMicroseconds(500);
}
if (e2 < dx) {
err += dx;
y0Steps += sy;
digitalWrite(DIR_PIN_Y, (sy > 0) ? HIGH : LOW);
digitalWrite(STEP_PIN_Y, HIGH);
delayMicroseconds(500);
digitalWrite(STEP_PIN_Y, LOW);
delayMicroseconds(500);
}
}
}
Code Explanation¶
Includes: The Arduino.h library is included to use standard Arduino functions.
Pin Constants: Four constants are defined to represent the step and direction pins for two stepper motors (X and Y axes).
Conversion Constants:
STEPS_PER_MM: Number of steps the motor needs to move one millimeter. This value depends on your stepper motor and mechanical setup.
LINE_LENGTH_MM: Length of the line to be drawn in millimeters.
drawLine Function Calls: The drawLine function is called three times to draw different lines:
A horizontal line along the X-axis.
A diagonal line from the origin to the point (LINE_LENGTH_MM, LINE_LENGTH_MM).
A line moving back to the origin.
delay: After each line is drawn, the code pauses for 1 second.
Converting Coordinates to Steps: The function converts the start and end coordinates from millimeters to steps.
Bresenham’s Line Algorithm:
This algorithm is used to determine which points in the grid should be illuminated to form a close approximation to a straight line between the start and end points.
It uses incremental error checking to decide when to step in the X direction, Y direction, or both.
Movement Loop:
The loop continues until the current position (x0Steps, y0Steps) matches the target position (x1Steps, y1Steps).
err is the current error term.
e2 is twice the error term.
Depending on the value of e2, the function increments or decrements the step position and sets the direction and step signals accordingly.
digitalWrite sets the direction pin and triggers the step pin to move the motor.
delayMicroseconds introduces a short delay between step signals to control the speed of the motor.