// slightly cleaned up from harvey moon's drawing machine // // gridding off space available in the image plane // repeatibility // accuracy // precision // // rtwomey@u.washington.edu // // Key 1 = 0,0 // Key 2 = width,0 // Key 3 = width,height // Key 4 = 0,height // Key 0 = Home // Key H = store home // Key S = stop // Key G = go Bot machine; import processing.serial.*; // serial communication import java.io.*; //Java // configuration boolean serialOn = false; boolean writeToFile = true; boolean printToConsole = true; PrintWriter writer; //--------------------------------------------------- // physical setup float MOTORSEP = 96.0;//72.0; // how far apart are the two steppers // offsets // line A, at limit switch, is 2.0 inches out. // line B, at limit switch, is 1.25 inches out. // paper size float PAGEW = 84.0;//36.0;//17.0;//22.0;//44.0; // width float PAGEH = 60.0;//14.0;//30;//30.0; // height float MARGIN = 2.0; // page location relative to motors float PAGE0X = (MOTORSEP-PAGEW)/2.0; // upper left float PAGE0Y = 6.0;//6.0-PAGEH; // top of paper //12.0;//40.0; float HOMEA = 81.0;//82.0;// 58.5225650924496; // 108 float HOMEB = 81.0;//82.0;//56.02580320709378; // 108 // scale image to screen int windowH = 800; float onScreenScale=windowH/PAGEH; int windowW = int(PAGEW*onScreenScale); // feed rates float FASTFEED = 200.0;//200.0; float SLOWFEED = 100.0;//15.0; // limit of the process int MAXDEPTH=4; //----------------------------------- // state variables boolean On = false;// USED SO THAT THE KEY 'S' AND 'G' START AND STOP THE DRAWING SEQUENCE, starts off to calibrate boolean done = false; boolean jumping = true; boolean atPoint = true; // if the arduino returns that it is at the point, turn true. boolean atHome=true; int scale=0; int x=0; int y=0; //------------------------------------ // main program void setup() { // graphics size(windowW, windowH); // load a font for text display PFont font; font = loadFont("Serif-24.vlw"); textFont(font, 12); // // store progress images // Photo = new OutputImage(); // arduino g-code interface machine = new Bot(this); machine.waitForStart(); writer = createWriter("test.txt"); machine.setupWriting(writer); background(255); // calc home values for X and Y (upper left corner of page) //HOMEA = sqrt(pow(PAGE0X, 2)+pow(PAGE0Y, 2)); //HOMEB = sqrt(pow(MOTORSEP-(PAGE0X), 2)+pow(PAGE0Y, 2)); if (printToConsole) println("(HOME: "+HOMEA + " " +HOMEB+")"); machine.storeHome(); machine.penUp(); } void draw() { stroke(120); strokeWeight(2); fill(220); if (On && !done) { drawGridAtScale(MARGIN, MARGIN, PAGEW-MARGIN, PAGEH-MARGIN, int(pow(2, scale))); if (incrementPosition(int(pow(2, scale)))) { scale++; if (scale>MAXDEPTH) { drawBox(MARGIN, MARGIN, PAGEW-MARGIN, PAGEH-MARGIN); done=true; } } } } boolean incrementPosition(int scale) { x++; if (x>=scale) { x=0; y++; if (y>=scale) { y=0; return true; } } return false; } boolean isEven(int num) { return (num%2==0); } boolean isOdd(int num) { return (num%2==1); } void drawGridAtScale(float left, float top, float right, float bot, int scale) { float ux=(right-left)/(float)scale; float uy=(bot-top)/(float)scale; // if ((scale<=1) || isOdd(x+y*scale)) drawScaledSegment(left+ux*x, top+uy*y, left+ux*(x+1), top+uy*(y+1)); // if ((scale<=1) || isEven(x+y*scale)) drawScaledSegment(left+ux*x, top+uy*(y+1), left+ux*(x+1), top+uy*y); drawScaledSegment(left+ux*x, top+uy*(y+0.5), left+ux*(x+1), top+uy*(y+0.5)); drawScaledSegment(left+ux*(x+0.5), top+uy*y, left+ux*(x+0.5), top+uy*(y+1)); delay(400); // } // } } void drawBox(float left, float top, float right, float bot) { drawScaledSegment(left, top, right, top); drawScaledSegment(right, top, right, bot); drawScaledSegment(right, bot, left, bot); drawScaledSegment(left, bot, left, top); } // keyboard interface void keyPressed() { if (key == 'g') { // start movement On = true; if (printToConsole)println("(GO!)"); machine.DirectCommand("G100 S100"); //moves servo, push pen off page machine.waitForOk(); jumping=true; } if (key == 's') { // stop movement On = false; if (printToConsole)println("(STOP)"); } if (key=='h') { machine.goHome(); } if (!On) { switch(key) { case '1': // top left machine.sendVal(0, 0, 0); break; case '2': // top right machine.sendVal(PAGEW, 0, 0); break; case '3': // lower right machine.sendVal(PAGEW, PAGEH, 0); break; case '4': // lower left machine.sendVal(0, PAGEH, 0); break; case '0': machine.penUp(); if (printToConsole)println("(going to stored home position)"); machine.DirectCommand("G1 X"+HOMEA+" Y"+HOMEB+" Z0.0 F"+FASTFEED); break; case 'd': machine.penDown(); break; case 'u': machine.penUp(); break; default: break; } //switch 1-4 keys } } void drawScaledSegment(float x1, float y1, float x2, float y2) { stroke(0, 256.0-scale*24.0); line(x1*onScreenScale, y1*onScreenScale, x2*onScreenScale, y2*onScreenScale); }; void drawCrossHairs(float x, float y) { float px, py; px=x*onScreenScale; py=y*onScreenScale; // stroke(128, 0, 0, 128); // line(px-3, py, px+3, py); // line(px, py-3, px, py+3); stroke(192, 0, 0, 128); line(px-1, py, px+1, py); line(px, py-1, px, py+1); }; void stop() { machine.penUp(); machine.DirectCommand("G1 X"+HOMEA+" Y"+HOMEB+" Z0.0 F"+FASTFEED); machine.stop(); };