<div class="textcontainer"> <p class="margin"> </p> <h3>Weeks 10-12: Build a Drawing Machine </h3> <p class="margin"> </p> <div class="flexrow"> <a id="btn" href="./plotter_code.zip" download>Checkout our Code from this week! </a> </div> <p class="margin"> </p> <h4>Preparation: Idea Generation and Brainstorming </h4> <p class="margin"> </p> <p> This week's assignment was a group project. I worked together with Isa Gooijer, Thomas Kaminsky, and Aaron Kang to develop the Drawing Machine. <br> <br> Our group brainstormed a few possible ideas for the drawing machine project. We were firstly excited about developing a machine that could possibly draw on the human body as a pseudo tattoo gun type drawing experience. While we briefly flirted with the idea of making a tattoo gun it was quickly ruled out due to safety and hygiene concerns. Our second idea was using UV-activated ink or pens (glow-in-the-dark substance) as an output material. Energized by this idea, we decided to move forward with developing a Drawing Machine design from a prior student and online tutorial. We specifically took inspiration from: <a href="https://ctian5136.github.io/ps70portfolio/html/weeks/finalproject.html"> Cindy </a> and pen plotter designs from <a href="https://andrewsleigh.github.io/plotter/"> Andrew Leigh. </a> </p> <p class="margin"> </p> <div> <div style="text-align:center;"> <iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/pfx2bN_xx8s?si=mfE_V3fa0ROxu48g" width="560"></iframe> </div> <br> <h4>Parts Design</h4> <p class="margin"> </p> <p> To create the pen plotter, we used stl parts from Version 3 of the Cartesian Pen Plotter with V-Slot axis. We 3D printed the parts on the Prusa printers. Our first prints came out partially incomplete, so we redid some prints a second time. We then created an organization system for all our parts in order to categorize the many motors, cables, screws, bolts and more that were necessary for assembly. </p> <p class="margin"> </p> <div class="flexrow"> <img src="./org1.jpg" alt="org image" width=35%> <img src="./org2.jpg" alt="org image" width=35%> <img src="./org3.jpg" alt="org image" width=35%> </div> </p> <p class="margin"> </p> <h4>Assembly</h4> <p class="margin"> </p> <p>Once all of the 3D parts were correctly printed, we met to assemble the drawing machine. This was by far the most fun part of the process. We followed the photos and videos from the tutorials before us on how to connect all of the printed parts and components of assembly. <br> The only V-slot aluminum extrusion we could find was over a meter long, so we mounted the drawing machine on a long piece of plywood as a base (our particular drawing machine is quite a large scale). </p> <p class="margin"> </p> <div class="flexrow"> <img src="./assembly1.jpg" alt="assembly image" width=35%> <img src="./assembly2.jpg" alt="assembly image" width=35%> <img src="./assembly3.jpg" alt="assembly image" width=35%> </div> </p> <p class="margin"> </p> <h4>Wiring</h4> <p class="margin"> </p> <p> <b> The following components were used in wiring the drawing machine: </b> </p> <div> <ul> <li><p> ESP32</p></li> <li><p>2 x Stepper Drivers</p></li> <li><p>2 x breadboards </p></li> <li><p>USBC transformer converts 5V to 12V</p></li> <li><p>2 x Nema 17 Stepper motors (17 is the physical size)</p></li> </ul> </div> <p> In wiring the two stepper motors for the drawing machine, we used an ESP32 to connect the motors to Arduino in order to control their movement. We wired the motors to two breadboards (one extender board) and then used the Stepper drivers to transform movement instructions from Arduino and intake voltage to power the motors. We need to be able to simultaneously control both stepper motors. In order to figure this out, we looked at Cindy's old board and referenced the pins to assemble our board. We also had to construct our own extra long wires because our board scale is so large. <br> <br> We ran into some issues getting one of our Stepper Motors to run. After running a current to the motor, we learned that one of our motors had an internal issue, which Bobby suggested could be due to some magnetization issues. <br> <br> We initially struggled to get power to work because we only had AC cords, which is why we used the adapter to convert the 5V power supply into the 12V we needed to power two motors from an external power supply. </p> <p class="margin"> </p> <h4>Programming</h4> <p class="margin"> </p> <p> We developed some initial code to get the motors to individually move. Unfortunately, we weren't able to get the drawing machine responsive to this code after running into a number of bugs. Our next steps are to write and compile the Arduino code necessary for controlling the motors speed and direction, and second to develop the processing code necessary for Gcode use with the Pen plotter. </p> <p>Fortunately, after much trial and error (and extreme thanks to Thomas) we were able to get our drawing machine to draw a circle and square. The code we used to execute this is included in our files for the week. We were not able to get the pen plotter to fully work, so our next steps would be to improve processing code for pen plotter and allow the drawing machine to move along the z-axis. </p> <!-- <h5>Arduino Plotter Code</h5> <pre> <code> // MultiStepper.pde // -*- mode: C++ -*- // // Shows how to multiple simultaneous steppers // Runs one stepper forwards and backwards, accelerating and decelerating // at the limits. Runs other steppers at the same time // // Copyright (C) 2009 Mike McCauley // $Id: MultiStepper.pde,v 1.1 2011/01/05 01:51:01 mikem Exp mikem $ #include <AccelStepper.h> // Define some steppers and the pins the will use AccelStepper stepper1 = AccelStepper(1, 14, 12); AccelStepper stepper2 = AccelStepper(1, 25, 26); int s1_bounds[] = {-2000, 2000}; int s2_bounds[] = {-500, 500}; int T = 1; int speed = 700; long cur_pos[] = {0, 0}; long goal_pos[] = {1000,500}; float next_vel[] = {0., 0.}; float ratio = 5. / 7.5; // int points_x[] = {0, 1000, 1000, 0, 0}; // int points_y[] = {0, 0, 500, 500, 0}; // int points_x[] = {0, int(500 * ratio), int(1000 * ratio), int(500 * ratio)}; // int points_y[] = {0, 500, 0, -500}; // int points_x[] = {0, -1000, -1000, 0, 0, -1000, -1000, 0, 0, -1000, -1000, 0, 0, -1000, -1000, 0}; // int points_y[] = {0, 0, -500, -500, 0, 0, -500, -500, 0, 0, -500, -500, 0, 0, -500, -500}; const int N = 20; int points_x[N]; int points_y[N]; void get_circle_points(float radius) { float inc = 2 * M_PI / N; for (int i = 0; i < N; i++) { points_x[i] = round( radius * cos(inc * i) * ratio); points_y[i] = round( radius * sin(inc * i)); } } void get_star_points(float radius) { int fake_points_x[N]; int fake_points_y[N]; float inc = 2 * M_PI / N; for (int i = 0; i < N; i++) { fake_points_x[i] = round( radius * cos(inc * i) * ratio); fake_points_y[i] = round( radius * sin(inc * i)); } int permutation[] = {0, 2, 4, 1, 3}; for (int j = 0; j < N; j++) { points_x[j] = fake_points_x[permutation[j]]; points_y[j] = fake_points_y[permutation[j]]; } } void get_dy_dx() { float diff_x = goal_pos[1] - cur_pos[1]; float diff_y = goal_pos[0] - cur_pos[0]; float r = sqrt(diff_x*diff_x + diff_y*diff_y); next_vel[0] = diff_x / r; next_vel[1] = diff_y / r; } void set_goal(float x, float y) { goal_pos[0] = x; goal_pos[1] = y; } float dist() { return sqrt(pow(goal_pos[1] - cur_pos[1], 2.)+ pow(goal_pos[0] - cur_pos[0], 2.)); } int move_servos() { if (abs(stepper1.distanceToGo()) <= 1) { // Serial.printf("D2G 2 is : %d\n", stepper2.distanceToGo()); if (abs(stepper2.distanceToGo()) <= 1) { return 1; } } stepper1.run(); stepper2.run(); return 0; } void setup() { stepper1.setMaxSpeed(1000.0); stepper1.setAcceleration(200.0); stepper2.setMaxSpeed(1000.0); stepper2.setAcceleration(200.0); Serial.begin(115200); get_circle_points(3048 / 2); } int cur_point = 0; int num_points = N; int done = 0; void loop() { done = move_servos(); if (done == 1) { cur_point = (cur_point + 1) % num_points; Serial.print("Curr Point: "); Serial.printf("%d\n", cur_point); done = 0; goal_pos[0] = points_x[cur_point]; goal_pos[1] = points_y[cur_point]; stepper1.moveTo(goal_pos[0]); stepper2.moveTo(goal_pos[1]); cur_pos[0] = stepper1.currentPosition(); cur_pos[1] = stepper2.currentPosition(); get_dy_dx(); stepper1.setMaxSpeed(fabs(next_vel[1]) * speed); stepper1.setAcceleration(fabs(next_vel[1]) * speed / 2); stepper2.setMaxSpeed(fabs(next_vel[0]) * speed); stepper2.setAcceleration(fabs(next_vel[0]) * speed / 2.); } } </code> </pre> --> <p class="margin"> </p> <h4>Final Result</h4> <p class="margin"> </p> <p>Below is a brief video of our first prototype of the Drawing Machine. Drawing with UV ink! We placed a UV flashlight next to the paper to show the ink appearing. We were happily surprised to get a prototype working and intend to follow-up on the next steps of improving the pen plotter devie in time for Demo day in May :) </p> <div> <div style="text-align:center;"> <iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/KavDKJPyeYI?si=HcRGndqawHrjs7Xg" width="560"></iframe> </div> </div> </div>