Motor Shield for Arduino for Drawbot

motor shield

Okay, I got another motor shield in. So I can now afford to leave my motor shield in the ArtEngine lab till ArtEngine get’s a shield to go with their Arduinos.

So I’ll bring it down to Artengine tonight along with a power supply.

Driving steppers, servos and DC motors with Arduino

Motor Shield

I finally got my driver board in today. These are great for making a drawbot and other small projects.

These are also very easy to hook up and program.

Features:

2 connections for 5V ‘hobby’ servos connected to the Arduino’s high-resolution dedicated timer – no jitter!

4 H-Bridges: L293D chipset provides 0.6A per bridge (1.2A peak) with thermal shutdown protection, internal kickback protection diodes. Can run motors on 4.5VDC to 36VDC.

Up to 4 bi-directional DC motors with individual 8-bit speed selection (so, about 0.5% resolution)

Up to 2 stepper motors (unipolar or bipolar) with single coil, double coil or interleaved stepping.

Pull down resistors keep motors disabled during power-up

Big terminal block connectors to easily hook up wires (10-22AWG) and power

Arduino reset button brought up top

2-pin terminal block and jumper to connect external power, for seperate logic/motor supplies

Tested compatible with Arduino Mega, Diecimila & Duemilanove

Download the easy-to-use Arduino software library, check out the examples and you’re ready to go

Technical Specification:

This special motor drive shield is based on Arduino Motor drive shield but more powerful than Arduino Motor drive shield

It can connect with sensors directly

The extended part can support plug and play, you can pull out it and push into it.

The motor drive, can also drive 4 dc motor can be 600MA through each motor, motor can be run in to the 36V voltage between 4.5 V.

Can also drive two stepper motor and two steering gear

Drawbot stress test

Drawbot

I did the wiring, glued the spools onto the motors using a glue gun (loctite didn’t work) and made a pen holder.

Even before running it with the pen I let it run for about 4 hours to see if everything was okay. I noticed right away that the motors were getting pretty warm at 13.5V. So I ripped the 9V off my cordless phone. Seems to run nice and quiet with that. After 4 hours, no overheating.

I added the pen holder and a ball point so it wouldn’t mark everything up.

It turns out the ballpoint works great. Obviously that’s an anomaly.

I’ve had it going with the pen for about an hour now. No missed steps.

Drawbot with motor shield

I just started to poke around to write some code for my new Drawbot.

I was curious if anybody had done this with a motorshield already. I found a conversation over at Adafruit. It’s inconclusive and it’s a couple of years ago. I sent a note to the thread starter to see if they got it working or abandoned the project.

Here’s a “polargraph“.

James Provost has one using the same shield.

Looks like Jeffry Street is up to the same thing.

I’ve pinged these guys. Perhaps they get back to share code. In the mean time I’ll try and get some code running myself.

I noticed the use of Processing.org on this polar based one.

G-Code is another approach to eyeball:

Here’s one g-code attempt. Another thread.

Here’s one that shows the code. I have a copy here (ArduinoCNC).

Another arduino based CNC machine has code posted (GCode_Interpreterdc).

Here’s a whole project on streaming g-code to arduino.

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) {}
} 
                                          

Adafruit Motor Shield Kit for Arduino

motor shield

Today I was thinking about a drawbot type machine so I went to my parts bin to see what sorts of steppers are there. I found two nice ones with a built in gear box.

I’ve have a Motor Shield that I bought Robotshop.ca which can control two servos and either 4 DC motors or 2 stepper motors.

I’ve experimented with operation of servos in the past but today I decided to get it working with a couple of stepper motors.

The manual (which I got from Robotshop’s Web site today) says to put the stepper library (AFMotor folder) into the “arduino/hardware/library” directory. This didn’t work. I moved the folder to the “arduino/libraries” folder and it worked.

I opened the arduino environment then opened the sample program in libraries/AFMotor/Examples/StepperTest which is called StepperTest.pde.

I made a few modifications:

#include 

AF_Stepper motor(48, 1);
AF_Stepper motor2(48, 2);

void setup() {
  Serial.begin(9600);           // set up Serial library at 9600 bps
  Serial.println("Stepper test!");

  motor.setSpeed(300);  // 10 rpm   
  motor2.setSpeed(300);
}

void loop() {
  //Serial.println("Single coil steps");
  //motor.step(10000, FORWARD, SINGLE); 
  //motor.step(100, BACKWARD, SINGLE); 

  //Serial.println("Double coil steps");
  //motor.step(10000, FORWARD, DOUBLE); 
  //motor.step(100, BACKWARD, DOUBLE);

  //Serial.println("Interleave coil steps");
  motor.step(1000, FORWARD, INTERLEAVE); 
  motor.step(1000, BACKWARD, INTERLEAVE); 
   motor2.step(1000, FORWARD, INTERLEAVE); 
  motor2.step(1000, BACKWARD, INTERLEAVE); 

//#ifdef MICROSTEPPING
//  Serial.println("Micrsostep steps");
//  motor.step(100, FORWARD, MICROSTEP); 
//  motor.step(100, BACKWARD, MICROSTEP); 
//#endif

}

I used a 13.5V supply to power the motor shield and a 6V supply to power the arduino.

The steppers get pretty warm. I’m suspecting they may be happier if I add a lower voltage for the shield power.