Drivers for the 2 stepper motors. (2 x SN754410). The LED's are for educational purposes, to show the state of the signals and polarity of the motor coils. Oh and computers have to have flashing lights :)
Breadboard.
/*
* Control 2 BiPolar Stepper Motors
*
* Receive Commands
* Use those commands to move the motors
* Return "ok" string to say done
*
* Use as you wish, give me credit of what you use :)
* Tim Jackson
*/
#include <Stepper.h>
#include <Servo.h>
#ifndef NULL #define NULL (0) #endif #define VERSION (1) // firmware version #define MAX_BUF (64) // What is the longest message Arduino can store?
// Motors used are from DVD/CD Drive // The motors have 20 step/revolution // Total revolutions 12 // 20 * 12 = 240 this is its max movement // Using 2 SN754410NE to drive them // motor 1 coil 1 pins 4, 5. // motor 1 coil 2 pins 6, 7. // motor 2 coil 1 pins 11, 10. // motor 2 coil 2 pins 13, 12.
Stepper stepperX(20, 4, 5, 6, 7);
Stepper stepperY(20, 13, 12, 11, 10);
Servo penServo;
// Command line variables char buffer[MAX_BUF]; // message int sofar; // size of buffer char mode_abs = 1; // absolute mode float fr = 0; // feed rate float unitMultiplyer = 240 / 36; // 240 steps = 36mm of movement, if inches then: 240 / 1.4173 float previousX = 0; float previousY = 0; int valZ = 0; int valT = 0; int valC = 0; int ToolPin = 3; int ServerPin = 9; int posUp = 2000;// 160 deg int posDown = 700;// 15 deg int maxSteps = 0; int no_data = 0; bool isComment = false;
void feedrate(float nfr) { // to do at some time
} void pause(long ms) {
delay(ms / 1000);
delayMicroseconds(ms % 1000);
} void setOrigin(float this_X, float this_Y) {
} void motorsOff() { // if motors need to be turned off.
} void Info() {
Serial.print("Tim's Bipolar XY Plotter. Version: ");
Serial.println(VERSION);
Serial.println("Commands:");
Serial.println("G00 [X(steps)] [Y(steps)]; - goX goY");
Serial.println("G01 [X(steps)] [Y(steps)] [F(feedrate)]; - travel to XY");
Serial.println("G02 [X(steps)] [Y(steps)] [I(steps)] [J(steps)] [F(feedrate)]; - clockwise arc");
Serial.println("G03 [X(steps)] [Y(steps)] [I(steps)] [J(steps)] [F(feedrate)]; - counter-clockwise arc");
Serial.println("G90; - absolute mode");
Serial.println("G91; - relative mode");
Serial.println("G92 [X(steps)] [Y(steps)]; - change logical position");
Serial.println("M100; - this Info message");
Serial.println("M101; - Reset Plotter");
Serial.println("All commands must end with a newline. /n");
delay(100);
} float parsenumber(char code, float val) { char *p = strchr(buffer, code); if (*p == code) { return atof(p + 1);
} return val;
} void checkTool() { // do +-Z for Tool State on or off
valZ = parsenumber('Z', valZ); //Serial.print(" valZ:"); //Serial.println(valZ); if (valZ > 0) {
ChangeTool(0);
} else {
ChangeTool(1);
}
} void processCommand() {
int cmd = parsenumber('G', -1); switch (cmd) { case 0: case 1: { // line //checkTool();
feedrate(parsenumber('F', fr));
MoveMotors_LINE(parsenumber('X', previousX) * unitMultiplyer, parsenumber('Y', previousY) * unitMultiplyer); break;
} case 2: case 3: { // arc int Roation = 0; if (cmd == 3) { Roation = 1; } //checkTool();
feedrate(parsenumber('F', fr));
MoveMotors_ARC(parsenumber('X', previousX) * unitMultiplyer, parsenumber('Y', previousY) * unitMultiplyer, parsenumber('I', previousX) * unitMultiplyer, parsenumber('J', previousY) * unitMultiplyer, Roation); break;
} case 4: pause(parsenumber('P', 0) * 1000); break; // dwell case 20: unitMultiplyer = 240.0 / 1.4173; break; // Inch mode case 21: unitMultiplyer = 240.0 / 36.0; break; // mm mode case 90: mode_abs = 1; break; // absolute mode case 91: mode_abs = 0; break; // relative mode case 92: setOrigin(parsenumber('X', 0), parsenumber('Y', 0)); break;// set origin default: break;
}
cmd = parsenumber('M', -1); switch (cmd) { case 3: ChangeTool(1); break; case 4: ChangeTool(2); break; case 5: ChangeTool(0); break;
//None Standard Commands case 18: motorsOff(); break; case 100: Info(); break; case 101: ResetMotors(); break; case 114: SendPositionToCom(previousX, previousY, valT, valC); break;// Send current position to serial default: break;
} //Serial.println("ok");
} void init_process_string()
{ //init our command for (byte i = 0; i < MAX_BUF; i++)
buffer[i] = 0;
sofar = 0;
Serial.flush();
Serial.println("ok");
}
// set the speed of the motor to 1000 RPMs max
stepperX.setSpeed(900);
stepperY.setSpeed(900); // set pin to switch tool on/off // pinMode(ToolPin, OUTPUT); //penServo.attach(ServerPin);
ResetMotors();
Info(); // show message
init_process_string();
} void loop() {
char c; //read in characters if we got them. if (Serial.available() > 0)
{
c = Serial.read();
no_data = 0; //newlines are ends of commands. if (c != '\n' || c != '\r')
{ if (c == 0x18) {
Serial.println("Tim");
} else { if (c == '(') {
isComment = true;
} // If we're not in isComment mode, add it to our array. if (!isComment)
{
buffer[sofar] = c;
sofar++;
} if (c == ')') {
isComment = false; // End of isComment - start listening again
}
}
}
} else
{
no_data++;
delayMicroseconds(100);//100
//if theres a pause or we got a real command, do it if (sofar && (c == '\n' || c == '\r' || no_data > 100))
{
processCommand(); // Process Command
init_process_string();//clear ommand.
}
}
}
Program to talk to the Arduino and tell it what to do. As the program uses G-Code to communicate with the Arduino, it will work with other machines that use basic G-Code and send back an "ok" as a reply. I have used it on a benbox laser cutter. (Note! though, benbox software home is Top Left. G-Code, home is Bottom Left.)
The program also has a sub program to convert DXF files to G-Code.
All my software is work in progress.
I am not a professional at this, I do it as a hobby.
Use accordingly. If you want to get in touch, use comments in google.