Other Drawbot projects

I now have an arduino/MotorShield running with a couple of steppers so I need to mount the spools on the steppers and write the code to start drawing.

There are a couple of projects out there using a Cartesian coordinate system such as an Etch A Sketch.  Here’s one with and without an Arduino.

The code below is from AS220.

// Drawbot portrait of Erik Satie
// (cc) 2008 AS220 Labs

#include                                                                     

#define motorStepsA 400                   
#define motorStepsB 400                                            
#define motorPinA1 8                                                                    
#define motorPinA2 9 
#define motorPinB1 10                                                                
#define motorPinB2 11

// Approximate number of steps per inch, calculated from radius of spool
// and the number of steps per radius
int StepUnit = 102;   

// Approximate dimensions of the total drawing area
int w= 40.5*StepUnit;
int h= 42.5*StepUnit;

// Coordinates of current (starting) point
int x1= w/2;
int y1= h;

// Approximate length of strings from marker to staple
int a1= sqrt(pow(x1,2)+pow(y1,2));
int b1= sqrt(pow((w-x1),2)+pow(y1,2));

// Size of image array
int rows = 31;  
int columns = 23  ;

// Radius of pixel circles, in StepUnits
int radius = 40;   // equals about .4 inches  

// Size of page
int pageW = columns*radius*2;
int pageH = rows*radius*2;

// Size of one "pixel"
int cellW =2*radius;
int cellH = 2*radius;

// Coordinate of upper left corner of page
int page0X = x1-(pageW/2)-400;
int page0Y = y1-pageH-500;

// The image: 0=white, 11=black
char image[] = {
1, 1, 2, 2, 3, 3, 5, 9, 10, 10, 11, 11, 11, 11, 10, 8, 7, 8, 9, 9, 9, 9, 9, 
1, 1, 2, 3, 3, 7, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 10, 8, 8, 8, 8, 8,
8, 
1, 2, 2, 3, 5, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 8, 8, 8, 8,
8, 
1, 2, 2, 3, 7, 10, 10, 11, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 8, 8, 8, 8,
9, 
1, 1, 2, 2, 8, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 9, 8, 8, 8,
9, 
1, 1, 2, 2, 8, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 9, 8, 8, 8,
8, 
1, 1, 1, 1, 8, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 9, 7, 7, 7,
8, 
0, 1, 1, 1, 8, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 9, 8,
8, 9, 
1, 4, 6, 8, 9, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
9, 8, 
7, 9, 9, 9, 10, 9, 9, 9, 9, 10, 10, 10, 9, 7, 7, 9, 10, 11, 11, 11, 11, 11, 9, 
2, 7, 9, 9, 9, 7, 5, 6, 8, 6, 6, 9, 7, 3, 1, 2, 7, 10, 11, 11, 11, 11, 10, 
0, 0, 3, 5, 0, 1, 4, 5, 4, 0, 0, 3, 7, 3, 0, 1, 4, 9, 10, 11, 11, 11, 9, 
0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 2, 6, 2, 0, 0, 3, 8, 10, 10, 11, 9, 7, 
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 1, 0, 0, 1, 3, 5, 7, 7, 9, 6, 7, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 5, 7, 8, 7, 8, 8, 
0, 0, 0, 0, 0, 0, 3, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 8, 7, 7, 8, 
0, 0, 0, 0, 0, 1, 6, 5, 2, 0, 0, 0, 1, 1, 0, 1, 1, 3, 4, 3, 3, 4, 4, 
0, 0, 0, 0, 1, 4, 6, 5, 3, 3, 1, 1, 1, 2, 2, 1, 2, 3, 3, 4, 4, 5, 5, 
0, 0, 0, 2, 5, 8, 8, 9, 8, 8, 5, 3, 3, 2, 3, 3, 3, 2, 4, 4, 4, 4, 5, 
0, 0, 0, 2, 6, 5, 3, 6, 9, 9, 8, 6, 6, 5, 4, 5, 2, 2, 3, 3, 4, 5, 5, 
0, 0, 0, 0, 4, 3, 1, 3, 6, 8, 9, 9, 8, 6, 8, 6, 2, 2, 3, 3, 4, 5, 5, 
0, 0, 0, 0, 5, 2, 0, 1, 4, 9, 9, 9, 9, 8, 8, 2, 1, 0, 2, 3, 4, 5, 5, 
0, 0, 0, 0, 3, 4, 2, 6, 9, 9, 10, 9, 9, 7, 4, 0, 0, 0, 4, 4, 4, 5, 6, 
0, 0, 0, 0, 3, 6, 7, 9, 9, 9, 9, 8, 3, 0, 0, 0, 0, 1, 8, 7, 4, 5, 6, 
0, 0, 0, 0, 3, 6, 9, 9, 9, 9, 9, 3, 0, 0, 0, 0, 1, 7, 10, 10, 6, 5, 6, 
0, 0, 0, 0, 5, 8, 9, 9, 9, 9, 5, 1, 0, 0, 0, 2, 7, 10, 10, 10, 10, 8, 7, 
0, 0, 0, 0, 7, 9, 9, 9, 9, 8, 3, 1, 0, 3, 7, 9, 10, 10, 10, 11, 11, 11, 9, 
0, 0, 0, 1, 7, 9, 9, 9, 6, 3, 1, 4, 8, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 
0, 0, 0, 1, 7, 8, 9, 9, 5, 4, 6, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11,
11, 
0, 0, 0, 0, 3, 6, 9, 8, 7, 9, 9, 7, 8, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 
0, 0, 0, 0, 3, 9, 9, 1, 8, 9, 2, 3, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11
};

// Stepper motor objects: A is left, B is right
Stepper StepperA(motorStepsA, motorPinA1,motorPinA2);                                     
Stepper StepperB(motorStepsB, motorPinB1,motorPinB2);

void setup() { 
  // Set up stepper motors and random # seed, if needed
  delay(2000); 
  StepperA.setSpeed(15);                                                              
  StepperB.setSpeed(15);                                                                                                                                                     
  delay(2000);                                                                            
  randomSeed(analogRead(0));
}                                                                                       


float rads(int n) {
  // Return an angle in radians
  return (n/180.0 * PI);
}                                                                        

void moveTo(int x2, int y2) {
  
  // Turn the stepper motors to move the marker from the current point (x1,
  // y1) to (x2, y2)
  // Note: This only moves in a perfectly straight line if 
  // the distance is the same in both dimensions; this should be fixed, but it
  // works well
  
  // a2 and b2 are the final lengths of the left and right strings
  int a2 = sqrt(pow(x2,2)+pow(y2,2));
  int b2 = sqrt(pow((w-x2),2)+pow(y2,2));
  int stepA;
  int stepB;
  if (a2>a1) { 
    stepA=1; 
  }
  if (a1>a2) { 
    stepA=-1;
  }
  if (a2==a1) {
    stepA=0; 
  }
  if (b2>b1) { 
    stepB=1; 
  }
  if (b1>b2) { 
    stepB=-1;
  }
  if (b2==b1) {
    stepB=0; 
  }

  // Change the length of a1 and b1 until they are equal to the desired length
  while ((a1!=a2) || (b1!=b2)) {
    if (a1!=a2) { 
      a1 += stepA;
      StepperA.step(stepA); 
    }
    if (b1!=b2) { 
      b1 += stepB;
      StepperB.step(-stepB);
    }
  }
  x1 = x2;
  y1=y2;
}

void drawCurve(float x, float y, float fx, float fy, float cx, float cy) {
  // Draw a Quadratic Bezier curve from (x, y) to (fx, fy) using control pt
  // (cx, cy)
  float xt=0;
  float yt=0;

  for (float t=0; t<=1; t+=.0025) {
    xt = pow((1-t),2) *x + 2*t*(1-t)*cx+ pow(t,2)*fx;
    yt = pow((1-t),2) *y + 2*t*(1-t)*cy+ pow(t,2)*fy;
    moveTo(xt, yt);
  }  
}
                                                     

void drawCircle(int centerx, int centery, int radius) {
  // Estimate a circle using 20 arc Bezier curve segments
  int segments =20;
  int angle1 = 0;
  int midpoint=0;
   
   moveTo(centerx+radius, centery);

  for (float angle2=360/segments; angle2<=360; angle2+=360/segments) {

    midpoint = angle1+(angle2-angle1)/2;

    float startx=centerx+radius*cos(rads(angle1));
    float starty=centery+radius*sin(rads(angle1));
    float endx=centerx+radius*cos(rads(angle2));
    float endy=centery+radius*sin(rads(angle2));
    
    int t1 = rads(angle1)*1000 ;
    int t2 = rads(angle2)*1000;
    int t3 = angle1;
    int t4 = angle2;

    drawCurve(startx,starty,endx,endy,
              centerx+2*(radius*cos(rads(midpoint))-.25*(radius*cos(rads(angle1)))-.25*(radius*cos(rads(angle2)))),
              centery+2*(radius*sin(rads(midpoint))-.25*(radius*sin(rads(angle1)))-.25*(radius*sin(rads(angle2))))
    );
    
    angle1=angle2;
  }

}


              
void drawCircles(int number, int centerx, int centery, int r) {
   // Draw a certain number of concentric circles at the given center with
   // radius r
   int dr=0;
   if (number > 0) {
     dr = r/number;
     for (int k=0; k=0; i--) {
    for (int j=columns-1; j>=0; j--) {
        char n = image[i*columns + j];
        n = constrain(n, 0, 11);
        
        // Draw big circles
        drawCircles(n,
                  page0X+(j*cellW), 
                  page0Y+(i*cellH),
                  radius);
      if ((j>0) && (i>0)) {
    
        // Draw little circles in-between big circles
        // Average the values of the adjoining pixels
        n=(image[(i-1)*columns + j]+
           image[(i-1)*columns+j-1]+
           image[i*columns+j-1]+
           image[i*columns + j])/8;
        n = constrain(n, 0, 11);
        drawCircles(n,
                    page0X+(j*cellW-(cellW/2)), 
                    page0Y+(i*cellH-(cellH/2)),
                    radius/2);
      }
    }
    
  }
  
  // Move off page and wait
  moveTo(page0X-500, y1);
  while (1) {}
}