-1

I am using an Arduino 2560, NEMA23 Stepper motor with a TB6600 driver. The driver is set to 1/32 step division. The motor by default is 200 steps per revolution.

I want to input step size, number of steps and settling time. Once the loop completes the number of steps i want to return to the starting point. The plan is to take multiple images and stack them in Photoshop.

So far everything works except for the return to starting point ...some of the time. If I don't step too far, meaning a combination of step size and number of steps, the motor returns to the starting point. If I exceed "X" distance the last step continues to move forward instead of backwards. I haven't fully tested what "X" distance is.

Example: If I use 5 steps with a step size of 5000 then the code returns to the starting point. If I change the steps to 7 and keep the step size at 5000 it does not return but moves forward.

Here is the complete code:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <Stepper.h>

LiquidCrystal_I2C lcd(0x27,20,4);

//parameters for keypad
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
char keys[ROWS][COLS] = 
{
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[ROWS] = {3,4,5,6}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {7,8,9,10}; //connect to the column pinouts of the keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

int j;
long stepSize=0;
long numSteps=0;
int settleTime=0;
int stepsPR=6400;
int DelayCamClose=10;
int DelayAfterCam=500;
int relayCam=A0;  //pin to relay to trigger camera

Stepper focusStack(stepsPR, 13,12);

//get keypad entry
int GetNumber()
{
  int num = 0;
  char key = keypad.getKey();
  while(key != '#')
   {
    switch (key)
     {
       case NO_KEY:
        break;
         case '0': case '1': case '2': case '3': case '4':
         case '5': case '6': case '7': case '8': case '9':
            lcd.print(key);
            num = num * 10 + (key - '0');
            break;
         case '*':
            num = 0;
            lcd.setCursor(0,1);
            lcd.print("          ");
            lcd.setCursor(0,1);
            break;
        }
      key = keypad.getKey();
   }
   return num;
}
void setup()
{  
    lcd.init();  //initialize the lcd
    lcd.backlight();  //open the backlight
    pinMode(relayCam, OUTPUT);
    digitalWrite (relayCam,HIGH); 
}

void loop()
{   
   {
     lcd.clear();
     lcd.setCursor (0,0);
     lcd.print("Set Settle Time");    
     lcd.setCursor (0,1);
     settleTime = GetNumber();
    }
   {
     lcd.clear();
     lcd.setCursor (0,0);
     lcd.print("Set Step Size");    
     lcd.setCursor (0,1);
     stepSize = GetNumber();
    }
    {
     lcd.clear();
     lcd.setCursor (0,0);
     lcd.print("Set Number Of Steps");    
     lcd.setCursor (0,1);
     numSteps = GetNumber();
    }
    j=1;
    while (j<=numSteps)
    {
     focusStack.step(stepSize);
     delay(settleTime);
     digitalWrite (relayCam,LOW);  //opens the camera shutter
     delay  (DelayCamClose);  //wait time to close camera shutter
     digitalWrite (relayCam,HIGH);  //close camera shutter
     delay (DelayAfterCam);
     j=j+1;
    } 
    { 
     focusStack.step(-stepSize*numSteps); //returns to start
    }
 }

The issue is with the math in the last line bit I'm not sure what it is. I've tried setting

long stepSize=0;
long numSteps=0;

as int and float but that did not solve the problem. I also changed

focusStack.step(-stepSize*numSteps); //returns to start

to

focusStack.step(stepSize*numSteps); //returns to start

but that only reverses the problem, as expected it might.

I have also tried using the AccelStepper Library but that introduced a whole different set of issues.

Any help would be greatly appreciated. I am still fairly new to programming.

  • Learn about steppers and then reconsider. Partial stepping is not your friend here. Open-loop steppers do not have a "zero." – TomServo Mar 31 '21 at 01:15
  • I understand steppers, maybe not to the extent that you do. I also know that they do not have a zero. The problem is that I can return to "zero" under certain cases. I just don't understand why if I exceed x distance the motor moves forward the same distance it should have moved back. The problem is the math in the last line, I just don't know what the problem is or how to fix it. Thanks for reading anyway. – brichardson Mar 31 '21 at 02:06
  • This can happen due to cogging when using microsteps, especially when changing direction. Experiment to see if this is true. Change your code (and probably DIP switch settings on your driver module to do full steps, native 200. Then repeat. If your return to zero problem disappears, then microsteps was the problem. Also, some acceleration curves (particularly when changing direction) can cause loss of zero. Remember even with no resistance, the armature itself has rotational momentum. – TomServo Mar 31 '21 at 13:36
  • Thanks. I tried pretty much every combination of microsteps and everything pointed back to the flipped sign when I exceeded 32767. It's now working as I would like it to. After the loop finishes the steps it now returns to the starting point. Next thing is to convert steps to actual distance. – brichardson Mar 31 '21 at 15:53

1 Answers1

0

Found the problem. Since stepSize and numSteps are integers the math flips any result over 32767 (16 bit). Anything over 32767 results in an overflow and is converted to a negative.

I now just need to set the stepper microsteps to a value that will allow enough travel and stay under the 32767 limitation.