2018
July Saturday 21

Bookmark and Share

Related Articles...

MILWAUKEE WI Arduino Meet Up Make Space

WANTED: CORE TEAM MEMBER TO HELP START NON-PROFIT GROUP.

WANTED: Angle Investor Start-Up Funding

Large Industrial Zoned Arduino Make Space Acquired!

Email :

COASMailBox @ gmail.com

MILWAUKEE WI Raspberry Pi Meet Up Make Space

WANTED: CORE TEAM MEMBER TO HELP START NON-PROFIT GROUP.

WANTED: Angle Investor Start-Up Funding

Large Industrial Zoned Raspberry Pi Make Space Acquired!

Email :

COASMailBox @ gmail.com

MILWAUKEE WI Internet of Things (IoT) Meet Up Make Space

WANTED: CORE TEAM MEMBER TO HELP START NON-PROFIT GROUP.

WANTED: Angle Investor Start-Up Funding

Large Industrial Zoned Make Space Acquired!

Full Advanced Fabrication Facility, machine Shop, Welding, Electronics Lab Equipment Acquired!

Email :

COASMailBox @ gmail.com

MILWAUKEE WI Machine Repair, & Installation  - Tier 1 Business Support

Machine Technician Mechanic 20+ Years  Personal Experienced In Industrial Factory Machine Servicing, Rebuilding, Installation And Repair - Plus A 35+ Years Experienced Computer Engineer Service Technician Team Ready For Your Outsourced Market Advantage Needs!

Hartung Industrial - Member - CGI Science & Technology Group

Email :

COASMailBox @ gmail.com

2017 NOVEMBER REVIEW

Arduino Open Source Community member - Tier 1 Full Stack Developer

Arduino, L293 IC, Stepper Motors, Mini CNC Proof Of Concept Modeling

2018 APRIL | by Gene Casanova

Senior Systems Engineer


The L293 & L293D IC - Quadruple High Current Half-H Drives

The L293 and L293D IC devices are quadruple high-current half-H drivers. The L293 is desined toi handle birdirectional drive currents to 1A at votlaes from 4.5 to 36V.

The L293D is designed to handle 600ma at voltages from 4.5 to 36V.

Both devices are designed to drive inductive loads such as relays, solenoids, DC and bipolar stepping motors, and other high-current/high-voltage loads in positive supply applications.

Each output is a complete totem-pole drive circuit, with a Darlington transistor sink and a pseudo-Darlington source. Drivers are enabled in pairs, with drivers 1 and 2 enabled by 1,2EN and drivers 3 and 4 anabled by 3,4 EN.

The L293 and L293D are characterized for operation from 0°C to 70°C

Reference TI Datasheet.

CGI Computer Wares, in Milwaukee WI USA, provides high grade L293 IC Chips.

All inputs are TTL compatible and tolerant up to 7 V.

Each output is a complete totem-pole drive circuit, with a Darlington transistor sink and a pseudo-Darlington source. Drivers are enabled in pairs, with drivers 1 and 2 enabled by 1,2EN and drivers 3 and 4 enabled by 3,4EN. When an enable input is high, the associated drivers are enabled, and their outputs are active and in phase with their inputs. When the enable input is low, those drivers are disabled, and their outputs are off and in the high-impedance state. With the proper data inputs, each pair of drivers forms a full-H (or bridge) reversible drive suitable for solenoid or motor applications.

On the L293, external high-speed output clamp diodes should be used for inductive transient suppression. On the L293D, these diodes are integrated to reduce system complexity and overall system size. A VCC1 terminal, separate from VCC2, is provided for the logic inputs to minimize device power dissipation. The L293 and L293D are characterized for operation from 0°C to 70°C.

NOTICE: Output diodes are internal in the L293D.

Properly heatsinking the L293 when driving high-current is critical to design. The Rthj-amp of the L293 can be reduced by soldering the GND pins to a suitable copper area of the printed circuit board or to an external heat sink.

During soldering, the pin temperature must not exceed 260°C, and the soldering time must not exceed 12 seconds.


Ardunio Drives Servos, Stepper Motors, X, Y, Z Planes

One L293 IC can be used to interface Arduino I/O pins to X axis stepper or servo motor, Y axis stepper or servo motor, and a servo motor for the Z-axis.

Ardunio X Y Z Stepper Motor Circuit

Stepper Motor Axis Test & Calibration

Begin by connecting the X and Y axis stepper motors. TNext, calibrate the stepper motors by running the following calibration programs.


X Axis Test

X-Axis is connected to I/O pins 8,9,10 and 11.

Load this proram in the Arduino connected to the stepper motors.

/*
 * Arduino Mini CNC Plotter
 * X Axis Test Routine
 * 2018
 * Casanova
*/
#include <Stepper.h>	// Include Stepper Motor Library

const int pasParRotation = 20; // Number of steps by turn. Standard value for CD/DVD

// X Axis Stepper Motor I/O Pins:
Stepper myStepperX(pasParRotation,8,9,10,11); 
 
void setup() {
		myStepperX.setSpeed(100);		// Stepper motor speed
 	/* The following step() function,
      * is used to move the stepper motor by steps.
		 * Set the number of steps to move the motor axial. 
 	 * Note, a CD/DVD drive motor can move about 250 steps max.
 	 * Negative number to move in reverse direction:
 	myStepperX.step(100);  // Measure the distance moved to calculate X calibration value	
 	delay(100);
}
void loop() {}

Start the program. If all is correct, the stepper motor must do 100 steps. Measure the distance moved, and divide by 100; to obtain the X-Axis calibration value.


Y Axis Test

Load this proram in the Arduino connected to the stepper motors.

/*
 * Arduino Mini CNC Plotter
 * Y Axis Test Routine
 * 2018
 * Casanova
*/
#include <Stepper.h>	// Include Stepper Motor Library

const int pasParRotation = 20; // Number of steps by turn. Standard value for CD/DVD

// X Axis Stepper Motor I/O Pins:
Stepper myStepperX(pasParRotation,2,3,4,5); 
 
void setup() {
		myStepperX.setSpeed(100);		// Stepper motor speed
 	/* The following step() function,
      * is used to move the stepper motor by steps.
		 * Set the number of steps to move the motor axial. 
 	 * Note, a CD/DVD drive motor can move about 250 steps max.
 	 * Negative number to move in reverse direction:
 	myStepperX.step(100);  // Measure the distance moved to calculate X calibration value	
 	delay(100);
}
void loop() {}

Start the program. If all is correct, the stepper motor must do 100 steps. Measure the distance moved, and divide by 100; to obtain the Y-Axis calibration value.


Issues

Issues possible:



Load Arduino CNC Program

/*
 * Arduino Mini CNC Plotter
 * Y Axis Test Routine
 * 2018
 * Casanova
 *
 * Send GCODE to Arduinog gctrl.pde https://github.com/damellis/gctrl
 * Convert SVG to GCODE with MakerBot Unicorn plugin for Inkscape
 * available @ https://github.com/martymcguire/inkscape-unicorn
 * Personal support available in Milwaukee WI, 'MKE Maker Space' group
 * Cotact for hands on support
*/
#include <Servo.h>
#include <Stepper.h>
#define LINE_BUFFER_LENGTH 512

/* PARAMETRES
*/

const int toolZUp = 130;				// Angle servomoteur, crayon relevé
const int toolZDown = 40;            // Angle servomoteur, crayon baissé
const int toolServoPin = 6;			// Pin sur lequel est relié le servomoteur
const int stepsPerRevolution = 20; 	// Valeur par défaut
const int vitesseDeplacement = 250;	// Vitesse de déplacement des axes X et Y

Servo toolServo;  					// Objet pour actionner le servomoteur

// Initialisation des moteurs pas à pas pilotés à l'aide d'un pont H L293D
Stepper myStepperY(stepsPerRevolution, 2,3,4,5);	// Axe X         
Stepper myStepperX(stepsPerRevolution, 8,9,10,11);  // Axe Y

// Calibration, nombre de pas par millimètre
float StepsPerMillimeterX = 6.0;
float StepsPerMillimeterY = 6.0;

/*
  FIN DE LA CONFIGURATION
*/

/* Structures, global variables    */
struct point { 
  float x; 
  float y; 
  float z; 
};

// Current position of plothead
struct point actuatorPos;

//  Drawing settings, should be OK
float StepInc = 1;
int StepDelay = 0;
int LineDelay = 50;
int toolDelay = 50;

// Drawing robot limits, in mm
// OK to start with. Could go up to 50 mm if calibrated well. 
float Xmin = 0;
float Xmax = 40;
float Ymin = 0;
float Ymax = 40;
float Zmin = 0;
float Zmax = 1;

float Xpos = Xmin;
float Ypos = Ymin;
float Zpos = Zmax; 

// Set to true to get debug output.
boolean verbose = false;

//  Needs to interpret 
//  G1 for moving
//  G4 P300 (wait 150ms)
//  M300 S30 (tool down)
//  M300 S50 (tool up)
//  Discard anything with a (
//  Discard any other command!

/**********************
 * void setup() - Initialisations
 ***********************/
void setup() {
  //  Setup
  Serial.begin( 9600 );
  
  toolServo.attach(toolServoPin);
  toolServo.write(toolZUp);
  delay(200);

  // Decrease if necessary
  myStepperX.setSpeed(vitesseDeplacement);
  myStepperY.setSpeed(vitesseDeplacement);  

  //  Set & move to initial default position
  // TBD

  //  Notifications!!!
  Serial.println("Mini CNC Plotter alive and kicking!");
  Serial.print("X range is from "); 
  Serial.print(Xmin); 
  Serial.print(" to "); 
  Serial.print(Xmax); 
  Serial.println(" mm."); 
  Serial.print("Y range is from "); 
  Serial.print(Ymin); 
  Serial.print(" to "); 
  Serial.print(Ymax); 
  Serial.println(" mm."); 
}

/**********************
 * void loop() - Main loop
 ***********************/
void loop() 
{
  delay(200);
  char line[ LINE_BUFFER_LENGTH ];
  char c;
  int lineIndex;
  bool lineIsComment, lineSemiColon;

  lineIndex = 0;
  lineSemiColon = false;
  lineIsComment = false;

  while (1) {

    // Serial reception - Mostly from Grbl, added semicolon support
    while ( Serial.available()>0 ) {
      c = Serial.read();
      if (( c == '\n') || (c == '\r') ) {             // End of line reached
        if ( lineIndex > 0 ) {                        // Line is complete. Then execute!
          line[ lineIndex ] = '\0';                   // Terminate string
          if (verbose) { 
            Serial.print( "Received : "); 
            Serial.println( line ); 
          }
          processIncomingLine( line, lineIndex );
          lineIndex = 0;
        } 
        else { 
          // Empty or comment line. Skip block.
        }
        lineIsComment = false;
        lineSemiColon = false;
        Serial.println("ok");    
      } 
      else {
        if ( (lineIsComment) || (lineSemiColon) ) {   // Throw away all comment characters
          if ( c == ')' )  lineIsComment = false;     // End of comment. Resume line.
        } 
        else {
          if ( c <= ' ' ) {                           // Throw away whitepace and control characters
          } 
          else if ( c == '/' ) {                    // Block delete not supported. Ignore character.
          } 
          else if ( c == '(' ) {                    // Enable comments flag and ignore all characters until ')' or EOL.
            lineIsComment = true;
          } 
          else if ( c == ';' ) {
            lineSemiColon = true;
          } 
          else if ( lineIndex >= LINE_BUFFER_LENGTH-1 ) {
            Serial.println( "ERROR - lineBuffer overflow" );
            lineIsComment = false;
            lineSemiColon = false;
          } 
          else if ( c >= 'a' && c <= 'z' ) {        // Upcase lowercase
            line[ lineIndex++ ] = c-'a'+'A';
          } 
          else {
            line[ lineIndex++ ] = c;
          }
        }
      }
    }
  }
}

void processIncomingLine( char* line, int charNB ) {
  int currentIndex = 0;
  char buffer[ 64 ];                                 // Hope that 64 is enough for 1 parameter
  struct point newPos;

  newPos.x = 0.0;
  newPos.y = 0.0;

  //  Needs to interpret 
  //  G1 for moving
  //  G4 P300 (wait 150ms)
  //  G1 X60 Y30
  //  G1 X30 Y50
  //  M300 S30 (tool down)
  //  M300 S50 (tool up)
  //  Discard anything with a (
  //  Discard any other command!

  while( currentIndex < charNB ) {
    switch ( line[ currentIndex++ ] ) {              // Select command, if any
    case 'U':
      toolUp(); 
      break;
    case 'D':
      toolDown(); 
      break;
    case 'G':
      buffer[0] = line[ currentIndex++ ];          // /!\ Dirty - Only works with 2 digit commands
      //      buffer[1] = line[ currentIndex++ ];
      //      buffer[2] = '\0';
      buffer[1] = '\0';

      switch ( atoi( buffer ) ){                   // Select G command
      case 0:                                   // G00 & G01 - Movement or fast movement. Same here
      case 1:
        // /!\ Dirty - Suppose that X is before Y
        char* indexX = strchr( line+currentIndex, 'X' );  // Get X/Y position in the string (if any)
        char* indexY = strchr( line+currentIndex, 'Y' );
        if ( indexY <= 0 ) {
          newPos.x = atof( indexX + 1); 
          newPos.y = actuatorPos.y;
        } 
        else if ( indexX <= 0 ) {
          newPos.y = atof( indexY + 1);
          newPos.x = actuatorPos.x;
        } 
        else {
          newPos.y = atof( indexY + 1);
          indexY = '\0';
          newPos.x = atof( indexX + 1);
        }
        drawLine(newPos.x, newPos.y );
        //        Serial.println("ok");
        actuatorPos.x = newPos.x;
        actuatorPos.y = newPos.y;
        break;
      }
      break;
    case 'M':
      buffer[0] = line[ currentIndex++ ];        // /!\ Dirty - Only works with 3 digit commands
      buffer[1] = line[ currentIndex++ ];
      buffer[2] = line[ currentIndex++ ];
      buffer[3] = '\0';
      switch ( atoi( buffer ) ){
      case 300:
        {
          char* indexS = strchr( line+currentIndex, 'S' );
          float Spos = atof( indexS + 1);
          //          Serial.println("ok");
          if (Spos == 30) { 
            toolDown(); 
          }
          if (Spos == 50) { 
            toolUp(); 
          }
          break;
        }
      case 114:                                // M114 - Repport position
        Serial.print( "Absolute position : X = " );
        Serial.print( actuatorPos.x );
        Serial.print( "  -  Y = " );
        Serial.println( actuatorPos.y );
        break;
      default:
        Serial.print( "Command not recognized : M");
        Serial.println( buffer );
      }
    }
  }
}


/*********************************
 * Draw a line from (x0;y0) to (x1;y1). 
 * Bresenham algo from https://www.marginallyclever.com/blog/2013/08/how-to-build-an-2-axis-arduino-cnc-gcode-interpreter/
 * int (x1;y1) : Starting coordinates
 * int (x2;y2) : Ending coordinates
 **********************************/
void drawLine(float x1, float y1) {

  if (verbose)
  {
    Serial.print("fx1, fy1: ");
    Serial.print(x1);
    Serial.print(",");
    Serial.print(y1);
    Serial.println("");
  }  

  //  Bring instructions within limits
  if (x1 >= Xmax) { 
    x1 = Xmax; 
  }
  if (x1 <= Xmin) { 
    x1 = Xmin; 
  }
  if (y1 >= Ymax) { 
    y1 = Ymax; 
  }
  if (y1 <= Ymin) { 
    y1 = Ymin; 
  }

  if (verbose)
  {
    Serial.print("Xpos, Ypos: ");
    Serial.print(Xpos);
    Serial.print(",");
    Serial.print(Ypos);
    Serial.println("");
  }

  if (verbose)
  {
    Serial.print("x1, y1: ");
    Serial.print(x1);
    Serial.print(",");
    Serial.print(y1);
    Serial.println("");
  }

  //  Convert coordinates to steps
  x1 = (int)(x1*StepsPerMillimeterX);
  y1 = (int)(y1*StepsPerMillimeterY);
  float x0 = Xpos;
  float y0 = Ypos;

  //  Let's find out the change for the coordinates
  long dx = abs(x1-x0);
  long dy = abs(y1-y0);
  int sx = x0>x1 ? StepInc : -StepInc;
  int sy = y0&ggt;y1 ? StepInc : -StepInc;

  long i;
  long over = 0;

  if (dx > dy) {
    for (i=0; i<dx; ++i) {
      myStepperX.step(sx);
      over+=dy;
      if (over>=dx) {
        over-=dx;
        myStepperY.step(sy);
      }
      delay(StepDelay);
    }
  }
  else {
    for (i=0; i<dy; ++i) {
      myStepperY.step(sy);
      over+=dx;
      if (over>=dy) {
        over-=dy;
        myStepperX.step(sx);
      }
      delay(StepDelay);
    }    
  }

  if (verbose)
  {
    Serial.print("dx, dy:");
    Serial.print(dx);
    Serial.print(",");
    Serial.print(dy);
    Serial.println("");
  }

  if (verbose)
  {
    Serial.print("Going to (");
    Serial.print(x0);
    Serial.print(",");
    Serial.print(y0);
    Serial.println(")");
  }

  //  Delay before any next lines are submitted
  delay(LineDelay);
  //  Update the positions
  Xpos = x1;
  Ypos = y1;
}

//  Raise tool
void toolUp() { 
  toolServo.write(toolZUp); 
  delay(LineDelay); 
  Zpos=Zmax; 
  if (verbose) { 
    Serial.println("tool up!"); 
  } 
}
//  Lower Tool
void toolDown() { 
  toolServo.write(toolZDown); 
  delay(LineDelay); 
  Zpos=Zmin; 
  if (verbose) { 
    Serial.println("tool down."); 
  } 
}

Install Processing or use gctrl.exe

Install a program to send a 'gcode' file, to the Arduino controler.

MacOS, FreeBSD, Linux users, install "Processing" (here) then run "gctrl.pde" (download here).


Plot A Drawing With gctrl

gctrl is an efficient basic program. The plotter starts after the selection of the gcode file. In case of problem, press “x” !


Use The Technology Wisely & Keep It Simple

- Cheers!

Gene Casanova


Need More?   Need Help? ........Software, Network, System & Data Center Builder & Developer | Development Services Available - Freelance Small Jobs; To Outsourced Long Term Service Provider Contract Labor Available.

CGI Computer Wares | EST 1979

Send E-MailCONTACT: [click]@CGIComputerWares.com