Ok, after a brief hiatus whilst I visited mum, and then home to celebrate our wedding anniversary, I'm back on the case.
probably easiest to put the sketch of Paul's traversers on here, and try to explain what I did and why. Hopefully that will give a flavour of the gentle art of programming...
The sketch is attached for anyone that wants to use it. You'll also need a wiring diagram, which looks like this;
And this is what the sketch looks like. I'm going to put some comments in a following post;
/*
28may19 - added detection of "wrong way" stepper wiring - if the carriage goes "up" instead of down when the program starts,
it will automatically inverts the constant "dir".
22 may 19 program to operate stepper leadscrew using A4988 driver
using an Arduino Nano
ELECTRICAL CONNECTIONS
Input pin A0 up limit switch wire colour
Input pin A1 down limit switch wire colour
Input pin A2 Down control wire colour
Input pin A3 Up control wire colour
Input pin A4 - A7 not used
Output pin 2 direction on vero
Output pin 3 step on vero
Output pin 4 Sleep on vero
Output pin 5 Reset on vero
Output pin 6 MS 3 Microstep on vero
Output pin 7 MS 2 on vero
Output pin 8 MS 1 on vero
Output pin 9 Disable on vero
Output pin 11 green led wire colour
Output pin 10 red led wire colour
SPEED
Stepper motor is normally 200 steps/turn and leadscrew is 5mm pitch
thus travel per full step is 5/200 = 0.025mm
Per Paul's post, traverser speed is 10 feet per minute
10 ft/min real = 70mm/min scale
70 mm/min = 14 revs/min with 5mm pitch
14 rpm = 2800 steps / min (single steps) = 46.67/second
stepdelay = 1/47/2 = 0.010714 seconds at full speed
needed to use 1/16 steps to get the speed down.
POSITIONS
Up, operating "up" limit switch
Down, ditto, down switch
Assumed travel = 85mm
Hence steps for full travel = 85/0.025 * 16 = 54400 - "totalsteps" -
This adjusts itself in the InitEndPos function
End of preamble =================================================================================
*/
int initialise = 0; // marker for position not found
int microsteps = 16; // can be 1 2 4 8 or 16 - use 16 for slow speed
bool setdir = LOW; // direction variable. LOW or HIGH. If it goes the wrong way, reverse this. It should go down (left, near) when turned on
bool dir = setdir; // temporary direction variable. LOW or HIGH.
bool pos = LOW; // position variable. LOW or HIGH. LOW = left, near, etc.
int startspeed = 30; // speed in mm/min
int fullspeed = 70; // speed in mm/min (avoiding decimals from m/sec)
int stepsturn = 200; // 200 steps per rev
int pitch = 5; // pitch of leadscrew
int totaltravel = 85; // mm
long totalsteps = 54400; //totaltravel * stepsturn * microsteps / pitch; // steps for full travel 54400 as a guess
int fullstepdelay = 600; // (30000000 * pitch * microsteps/ stepsturn / fullspeed); // microseconds
int startstepdelay = 3500; // (30000000 * pitch * microsteps/ stepsturn / startspeed); // microseconds
int stepdelay = 600; // this is used in the initialisation and then changes during cycle
int accelsteps = startstepdelay - fullstepdelay; // about 2900
int stepincrement = 1; // ((startstepdelay - fullstepdelay ) / accelsteps);
// End of Declaration ================================================================================
void setup() { //
Serial.begin (115200);
pinMode(A0, INPUT_PULLUP); // up limit switch
pinMode(A1, INPUT_PULLUP); // down limit switch
pinMode(A2, INPUT_PULLUP); // down control switch
pinMode(A3, INPUT_PULLUP); // up control switch
pinMode(2, OUTPUT); // Direction
pinMode(3, OUTPUT); // Step
pinMode(4, OUTPUT); // Sleep
pinMode(5, OUTPUT); // Reset
pinMode(6, OUTPUT); // Microstep 3
pinMode(7, OUTPUT); // Microstep 2
pinMode(8, OUTPUT); // Microstep 1
pinMode(9, OUTPUT); // Disable
pinMode(10, OUTPUT); // red led
pinMode(11, OUTPUT); // green led
digitalWrite(4, HIGH);
digitalWrite(5, HIGH);
digitalWrite(9, LOW); // hold sleep reset & disable off
if (microsteps == 2) { // half microstepping
digitalWrite (8, HIGH);
digitalWrite (7, LOW);
digitalWrite (6, LOW);
}
else if (microsteps == 4) { // quarter
digitalWrite (8, LOW);
digitalWrite (7, HIGH);
digitalWrite (6, LOW);
}
else if (microsteps == 8) { // eighth
digitalWrite (8, HIGH);
digitalWrite (7, HIGH);
digitalWrite (6, LOW);
}
else if (microsteps == 16) { // sixteenth
digitalWrite (8, HIGH);
digitalWrite (7, HIGH);
digitalWrite (6, HIGH);
}
else {
microsteps = 1;
digitalWrite (8, LOW);
digitalWrite (7, LOW);
digitalWrite (6, LOW);
}
Serial.println ("setup completed");
Serial.print ("microsteps = ");
Serial.println (microsteps);
Serial.print ("stepdelay = ");
Serial.println (stepdelay);
Serial.print ("totalsteps = ");
Serial.println (totalsteps);
Serial.print ("accelsteps = ");
Serial.println (accelsteps);
Serial.print ("fullstepdelay ");
Serial.println (fullstepdelay);
Serial.print ("startstepdelay ");
Serial.println (startstepdelay);
Serial.print ("stepincrement ");
Serial.println (stepincrement);
// confirmation on screen
}
// End of Setup =======================================================================================
void loop() { // this is the main body of the program and will run until the power is turned off
// checkconnections(); // remove first pair of // to test button connections. Ensure "serial monitor" is on
// runstepper (); // remove first pair of // to test motor connections
if (initialise == 0) { // Hoist position not known.
InitEndPos();
}
if (digitalRead(A2) == LOW) { // DOWN control switch pressed
// need to add de-bounce here
if (pos == HIGH) {
GoDown(totalsteps);
}
}
if (digitalRead(A3) == LOW) { // UP control switch pressed
// need to add de-bounce here
if (pos == LOW) {
GoUp(totalsteps);
}
}
} // end of main loop =============================================================================
void GoDown(long gosteps) { // function to go to down position
digitalWrite(10, HIGH); // Turn on RED led
digitalWrite(11, LOW); // Turn off GREEN led
digitalWrite(2, dir); // go down
long stp = 0;
stepdelay = startstepdelay;
Serial.print ("stepdelay = ");
Serial.println (stepdelay );
while (stp < gosteps) {
if (stp < accelsteps) {
stepdelay = stepdelay - stepincrement;
}
if (stp > (gosteps - accelsteps)) {
stepdelay = stepdelay + stepincrement;
}
digitalWrite(3, HIGH);
delayMicroseconds (2);
digitalWrite(3, LOW);
delayMicroseconds (stepdelay);
// Serial.println (stepdelay);
stp ++;
}
digitalWrite(11, HIGH); // Turn on GREEN led
digitalWrite(10, LOW); // Turn off RED led
pos = LOW;
Serial.println ("DOWN, LEFT, NEAR");
}
// End of GoDown Function ================================================================================
void GoUp(long gosteps) { // function to go to up position - it's the same as the GoDown with the "!" in front of "dir",
// and modified comments.
digitalWrite(10, HIGH); // Turn on RED led
digitalWrite(11, LOW); // Turn off GREEN led
digitalWrite(2, !dir); // go up
long stp = 0;
stepdelay = startstepdelay;
while (stp < gosteps) {
if (stp < accelsteps) {
stepdelay = stepdelay - stepincrement;
}
if (stp > (gosteps - accelsteps)) {
stepdelay = stepdelay + stepincrement;
}
digitalWrite(3, HIGH);
delayMicroseconds (2);
digitalWrite(3, LOW);
delayMicroseconds (stepdelay);
// Serial.println (stepdelay);
stp ++;
}
digitalWrite(11, HIGH); // Turn on GREEN led
digitalWrite(10, LOW); // Turn off RED led
pos = HIGH;
Serial.println ("UP, RIGHT, FAR");
} // End of GoUp Function ================================================================================
void InitEndPos() { // function to initialise Down & Up positions & steps to travel ==========================================
// table will drive one way until it hits a switch.
// ideally down/near/left every time it is turned on, but in case it goes up, it will stop and reverse slowly til it hits the down switch.
// once it has found the down limit switch, it will then go quickly most of the way to the other extreme, slowly til it hits the switch and stop there.
// it then "knows" where the end stops are, sets the "initialise" variable to HIGH and goes into the main loop
while (digitalRead(A1) == HIGH) { // down limit switch not pressed
InitDown (1); // find down position and stop - this is slow because it may be "anywhere"
if (digitalRead(A0) == LOW) { // up limit switch has been pressed before the down switch - ie carriage went up, not down
Serial.println ("wrong way - inverting dir ");
Serial.print ("dir =");
Serial.println (dir);
InitUp (50); // back off from the switch - so up is down and vice versa...
dir = !dir; // inverts dir
Serial.print ("dir =");
Serial.println (dir);
delay (1000); // wait, then start again
}
}
totalsteps = 0; // assign zero point
Serial.println ("detected limit switch - down position");
InitUp (50000); // swift travel most of the way to the up/right/far position
totalsteps = 50000;
while (digitalRead(A0) == HIGH) { // up limit switch not pressed
GoUp (1); // find up position and stop
totalsteps = totalsteps + 1; // count the steps!
Serial.print ("totalsteps = ");
Serial.println (totalsteps); // this is about 200 steps x 16 microsteps x 17 turns = 54400
}
initialise = 1; // clear uninitialised flag
Serial.println ("detected limit switch - up position");
Serial.print ("totalsteps = ");
Serial.println (totalsteps);
Serial.print ("accelsteps = ");
Serial.println (accelsteps);
Serial.print ("stepincrement = ");
Serial.println (stepincrement);
pos = HIGH;
Serial.println ("UP, RIGHT, FAR");
} // end of InitEndPos ===============================================================================
void InitDown(long gosteps) { // function to go to down position without acceleration or deceleration =========================
digitalWrite(10, HIGH); // Turn on RED led
digitalWrite(11, LOW); // Turn off GREEN led
digitalWrite(2, dir); // go down
int stp = 0;
while (stp < gosteps) {
digitalWrite(3, HIGH);
delayMicroseconds (2);
digitalWrite(3, LOW);
delayMicroseconds (stepdelay);
stp ++;
}
digitalWrite(11, HIGH); // Turn on GREEN led
digitalWrite(10, LOW); // Turn off RED led
pos = LOW;
}
void InitUp(long gosteps) { // function to go to up position without acceleration or deceleration ================================
digitalWrite(10, HIGH); // Turn on RED led
digitalWrite(11, LOW); // Turn off GREEN led
digitalWrite(2, !dir); // go up
long stp = 0;
while (stp < gosteps) {
digitalWrite(3, HIGH);
delayMicroseconds (2);
digitalWrite(3, LOW);
delayMicroseconds (stepdelay);
stp ++;
}
digitalWrite(11, HIGH); // Turn on GREEN led
digitalWrite(10, LOW); // Turn off RED led
pos = HIGH;
} // =================================================================================================
void checkconnections () { // simple function to check the buttons are connected correctly.
// Only runs if you remove the "//" in the Loop
// Don't forget to put the "//" back again!
for (int n = 0; n < 2000; n++) {
bool j = digitalRead (A3);
Serial.print ("pin A3 =");
Serial.println (j);
j = digitalRead (A2);
Serial.print ("pin A2 =");
Serial.println (j);
j = digitalRead (A0);
Serial.print ("pin A0 =");
Serial.println (j);
j = digitalRead (A1);
Serial.print ("pin A1 =");
Serial.println (j);
Serial.println ("");
Serial.println (n);
Serial.println ("");
delay (500);
}
// the function will call 2000 time and then hand back to the loop, and get called again!
// whilst this function call is not "commented out" by the "//" in the call in Loop, the program can run but badly!
} // end of checkconnections function =======================================================================
void runstepper () { // function to check that the stepper motor is working ==============================================
// Only runs if you remove the "//" in the Loop
// Don't forget to put the "//" back again!
runstepper: // this is a label for the "goto" at the end of this function. ie, it is a closed loop, no escape!
stepdelay = 3500;
int increment = 1;
Serial.println ("accel");
for (int m = 0; m < 3200; m++) { // one turn accelerating
digitalWrite(3, HIGH);
delayMicroseconds (10);
digitalWrite(3, LOW);
delayMicroseconds (stepdelay);
stepdelay = stepdelay - increment;
}
Serial.println (stepdelay);
Serial.println ("const");
for (int m = 0; m < 6400; m++) { // two turns at constant speed
digitalWrite(3, HIGH);
delayMicroseconds (10);
digitalWrite(3, LOW);
delayMicroseconds (stepdelay);
}
Serial.println ("decel");
for (int m = 0; m < 3200; m++) { // one turn decelerating
digitalWrite(3, HIGH);
delayMicroseconds (10);
digitalWrite(3, LOW);
delayMicroseconds (stepdelay);
stepdelay = stepdelay + increment;
}
Serial.println (stepdelay);
Serial.println ("reverse");
dir = !dir; // the "!" means "not" - this will reverse the rotation
digitalWrite (2, dir);
goto runstepper;
// this function is a closed loop and will repeat until turned off
// whilst this function call is not "commented out" by the "//" in the call in Loop, none of the rest of the program can run
} // end of runstepper function =====================================================================================
// end of sketch ====================================================================================================