These are really easy to use - just two pins are used to step the motor and tell it which direction to turn. They support bi-polar (4,6 and 8 wire steppers) motors and have a trim pot for varying the current supply.
So I wired an Easy Driver running on a PC PSU 12V supply into an Airpax stepper motor that I found a pair of on Ebay. It made a few noises and tick-tocked, but spectacularly failed to spin. I suspect these motors need more voltage/current to run. Oh well. In my box-o-junk I had a stepper from a 99p Ebay printer. Wiring that up and tweaking the step speed gave good results so I fitted this motor to the X-axis drive shaft on my mill. Now we're in business:
The green wire on the left is an end-stop switch. When the X-axis reaches the wires it makes a circuit that stops the motor running. I also used this to set a 'zero' for the axis. Some Arduino coding gave me the following functions (so far!):
- Go to zero (and reset the step counter at the zero postion)
- Do a relative move (+ve or -ve direction) at a certain speed
- Move to a set position on the X-axis
The code can be controlled by serial commands - the intent is to use GRBL eventually, but this is great for getting to grips with hardware/software tuning :)
Now I just need some more stepper motors.
Here's some really bad, hacked code. Don't look at it too hard or it might self-combust...
// CmdMessenger library available from https://github.com/dreamcat4/cmdmessenger
#include <CmdMessenger.h>
// Streaming4 library available from http://arduiniana.org/libraries/streaming/
#include <Streaming.h>
// Mustnt conflict / collide with our message payload data. Fine if we use base64 library ^^ above
char field_separator = ',';
char command_separator = ';';
// Attach a new CmdMessenger object to the default Serial port
CmdMessenger cmdMessenger = CmdMessenger(Serial, field_separator, command_separator);
// ------------------ C M D L I S T I N G ( T X / R X ) ---------------------
// We can define up to a default of 50 cmds total, including both directions (send + recieve)
// and including also the first 4 default command codes for the generic error handling.
// If you run out of message slots, then just increase the value of MAXCALLBACKS in CmdMessenger.h
// Commands we send from the Arduino to be received on the PC
enum
{
kCOMM_ERROR = 000, // Lets Arduino report serial port comm error back to the PC (only works for some comm errors)
kACK = 001, // Arduino acknowledges cmd was received
kARDUINO_READY = 002, // After opening the comm port, send this cmd 02 from PC to check arduino is ready
kERR = 003, // Arduino reports badly formatted cmd, or cmd not recognised
// Now we can define many more 'send' commands, coming from the arduino -> the PC, eg
// kICE_CREAM_READY,
// kICE_CREAM_PRICE,
// For the above commands, we just call cmdMessenger.sendCmd() anywhere we want in our Arduino program.
kSEND_CMDS_END, // Mustnt delete this line
};
// Commands we send from the PC and want to recieve on the Arduino.
// We must define a callback function in our Arduino program for each entry in the list below vv.
// They start at the address kSEND_CMDS_END defined ^^ above as 004
messengerCallbackFunction messengerCallbacks[] =
{
G00, // 004 Rapid positioning
G01, // 005 Linear interpolation
G09, // 006 Exact stop check
RESET_X, // 007 go to end stop in x
ABS_X, // 008 go to absolute location in X - assumes system has been zeroed
NULL
};
// Its also possible (above ^^) to implement some symetric commands, when both the Arduino and
// PC / host are using each other's same command numbers. However we recommend only to do this if you
// really have the exact same messages going in both directions. Then specify the integers (with '=')
#define DIR_PIN 3
#define STEP_PIN 2
float x_speed = 0.1;
int end_stop_1 = 6;
int end_stop_2 = 7;
long max_x = 31500;
long curr_pos = 0;
float max_x_speed = 0.2;
void setup()
{
//setup serial comms
Serial.begin(9600);
// cmd messanger setup
cmdMessenger.print_LF_CR(); // Make output more readable whilst debugging in Arduino Serial Monitor
// Attach default / generic callback methods
cmdMessenger.attach(kARDUINO_READY, arduino_ready);
cmdMessenger.attach(unknownCmd);
// Attach my application's user-defined callback methods
attach_callbacks(messengerCallbacks);
arduino_ready();
pinMode(DIR_PIN, OUTPUT);
pinMode(STEP_PIN, OUTPUT);
pinMode(end_stop_1, INPUT);
pinMode(end_stop_2, INPUT);
}
void loop()
{
// Process incoming serial data, if any
cmdMessenger.feedinSerialData();
}
// ------------------ C A L L B A C K M E T H O D S -------------------------
void G00()
{
int i=0;
int j=0;
long go_x = 0;
char str_temp[10];
while ( cmdMessenger.available() )
{
char buf[350] = {
'\0' };
cmdMessenger.copyString(buf, 350);
if(buf[0])
{
//cmdMessenger.sendCmd(kACK, buf);
for(j=0;j<10;j++)
{
str_temp[j] = buf[j];
}
switch(i){
case 0:
//cmdMessenger.sendCmd(kACK, "Channel");
go_x = atol(str_temp);
break;
case 1:
//cmdMessenger.sendCmd(kACK, "Channel");
x_speed = atof(str_temp);
break;
}
i++;
}
}
Serial.print("moving head in x, d=");
Serial.print(go_x);
Serial.print(", speed= ");
Serial.println(x_speed);
rotate(go_x, x_speed);
Serial.print("Stoped at pos=");
Serial.println(curr_pos);
//set_rate(go_x, 0, 0);
}
void G01()
{
// All stop
//set_rate(0, 0, 0);
}
void G09()
{
// All stop
//set_stop();
}
void RESET_X()
{
rotate(40000,0.1);
curr_pos = 0;
Serial.println(" X axis at origin");
}
void ABS_X()
{
int i=0;
int j=0;
long go_x = 0;
char str_temp[10];
while ( cmdMessenger.available() )
{
char buf[350] = {
'\0' };
cmdMessenger.copyString(buf, 350);
if(buf[0])
{
//cmdMessenger.sendCmd(kACK, buf);
for(j=0;j<10;j++)
{
str_temp[j] = buf[j];
}
switch(i){
case 0:
//cmdMessenger.sendCmd(kACK, "Channel");
go_x = atol(str_temp);
break;
case 1:
//cmdMessenger.sendCmd(kACK, "Channel");
x_speed = atof(str_temp);
break;
}
i++;
}
}
long del_pos = curr_pos - go_x;
Serial.print("moving head in x, pos=");
Serial.print(go_x);
Serial.print(", delta pos= ");
Serial.print(del_pos);
Serial.print(", speed= ");
Serial.println(x_speed);
rotate(del_pos, x_speed);
Serial.print("Stoped at pos=");
Serial.println(curr_pos);
}
// ------------------ D E F A U L T C A L L B A C K S -----------------------
void arduino_ready()
{
// In response to ping. We just send a throw-away Acknowledgement to say "im alive"
cmdMessenger.sendCmd(kACK,"Arduino ready");
}
void unknownCmd()
{
// Default response for unknown commands and corrupt messages
cmdMessenger.sendCmd(kERR,"Unknown command");
}
// ------------------ E N D C A L L B A C K M E T H O D S ------------------
void attach_callbacks(messengerCallbackFunction* callbacks)
{
int i = 0;
int offset = kSEND_CMDS_END;
while(callbacks[i])
{
cmdMessenger.attach(offset+i, callbacks[i]);
i++;
}
}
void rotate(long steps, float speed){
//rotate a specific number of microsteps (8 microsteps per step) - (negitive for reverse movement)
//speed is any number from .01 -> 1 with 1 being fastest - Slower is stronger
int dir = (steps > 0)? HIGH:LOW;
boolean step_dir;
if (steps > 0)
step_dir = true;
else
step_dir = false;
steps = abs(steps);
digitalWrite(DIR_PIN,dir);
float usDelay;
if(speed < max_x_speed)
usDelay = (1/speed) * 70;
else
usDelay = (1/max_x_speed) * 70;
for(long i=0; i < steps; i++){
if((curr_pos >= max_x) && !step_dir)
{
Serial.println("Max X reached - halting ");
break;
}
digitalWrite(STEP_PIN, HIGH);
delayMicroseconds(usDelay);
digitalWrite(STEP_PIN, LOW);
delayMicroseconds(usDelay);
if(step_dir)
curr_pos--;
else
curr_pos++;
if(check_end_stops() && step_dir)
{
Serial.print("End STOP: Max steps achieved: ");
Serial.println(i);
break;
}
}
}
void rotateDeg(float deg, float speed){
//rotate a specific number of degrees (negitive for reverse movement)
//speed is any number from .01 -> 1 with 1 being fastest - Slower is stronger
int dir = (deg > 0)? HIGH:LOW;
digitalWrite(DIR_PIN,dir);
int steps = abs(deg)*(1/0.225);
float usDelay = (1/speed) * 70;
for(int i=0; i < steps; i++){
digitalWrite(STEP_PIN, HIGH);
delayMicroseconds(usDelay);
digitalWrite(STEP_PIN, LOW);
delayMicroseconds(usDelay);
}
}
boolean check_end_stops()
{
if(digitalRead(end_stop_1) == false)
return true;
else
return false;
}
No comments:
Post a Comment