Stepper Motor tutor needed

Hello!
I'm looking for someone interested in tutoring me in a stepper motor project. I have started this project thinking that it would be something I can do or learn on my own, but it has definitely taken the upper hand and shown me what I DON'T know.

The project consists of controlling one stepper motor of NEMA23 size attached to a linear rail with a joystick. The motor is to correspond to the joystick travel. (i.e. the further you move the joystick, the faster the motor turns) The carriage on the linear rail is to be able to "home" and user will be able to move the carriage to certain positions with the joystick. Once the carriage is where he/she wants it, they can push a button and record that position and be able to return to it at another time. There is a requirement for several of these positions to be recorded.

I believe I have all of the hardware needed. If I don't have something that my tutor recommends, I have no issue purchasing what is needed. I am willing to pay someone to complete this project, but I would really like to learn from it so tutoring is what I'm hoping for.

I would appreciate anyone's help in this if there is anyone interested.
Thank you,
Ron.

In order to do this you need some way for your stepper motor to have a "home" position that your code can find every time you power up the system. You can use a micro switch that the carriage can press or some other type or sensor to consistently tell you program a home or zero starting position.
I do not see any discussion of what is allowing the stepper motor to move along a linear rail. Is it balanced on the rail or do you have two rails to provide stability? More designing is needed.
Good luck,
Paul

Hi Paul.

I appreciate the interest. In fact, thank you again for attempting to help me last week (another thread - same project, but this time I'm admitting I'm in over my head and looking for help through completion).

The motor is attached to a linear rail "system". It is driving a screw that runs through the carriage. The rail is mounted to an extruded aluminum frame with a bearing holding the screw at each end. Photo is below.

I have hall-effect sensors purchased for end stops. I was planning on using one as the home position as well.

I've spent quite a bit of time on this (25 revisions of the code so far) and can't seem to understand what I keep doing wrong.

Where are you located ?
Otherwise, I’m happy to DM a sketch I wrote recently to help someone else…
It uses Accelstepper, up to three concurrent motors…provides a few extra tricks, could be extended to use a a joystick… and stores waypoints in EEPROM

ADDED: you could be better off not using a fancy library, because soft stepping a motor with a joystick will be a lot easier if you control the step frequency.

Is there a second rail, underneath, that keeps the carriage from rotating?
Paul

lastchancename,

I appreciate the response. I am welcoming any help I can get. I'm located in Indianapolis. How do you "DM" a sketch?

I tried using several different approaches to this, but I have a hard time understanding the type of code that uses "timing" or times (millis()??????) to control the steps.

Thank you,
Ron.

Paul,

The carriage block rides on the linear rail. the linear rail is attached to the extruded aluminum. The motor is attached to the aluminum plate at the end which is also attached to the extruded aluminum. The screw/shaft is directly attached to the motor spindle and rotates on bearings, one at each end of the structure. Spinning the screw/shaft causes the carriage to glide back and forth on the linear rail (and yes, without the carriage spinning).

Thank you for your time.
Ron.

Post your best version and tell us what's wrong with it.

Do you need end stops and a home position? Oftentimes, one of the end stops is used as home.

What is this apparatus going to be used for?

wildbill,

First of all, thank you for responding. Below is the code I used to actually get the joystick to successfully move the motor back and forth. There were a couple things wrong with it. One, it wasn't fast enough and two, I didn't know how to incorporate end stops into it and home it. Plus, with the way this one is written, I didn't know how I was going to record positions.

Thank you in advance for any suggestions.
Ron.

#include <AccelStepper.h>

const byte stepPin = D1;
const byte dirPin = D2;
const byte xJoyPin = A0;  
int speedVal = 0;

AccelStepper xStepper(AccelStepper::DRIVER, stepPin, dirPin);

void setup()
{
   Serial.begin(115200);
   xStepper.setMaxSpeed(50000);
   xStepper.setAcceleration(500);
   xStepper.setSpeed(0);
}

void loop()
{
   int xJoy = analogRead(xJoyPin);
   
   if (xJoy >= 530 && xJoy <= 550) // ±10 hysteresis for center (0 speed)
   {      
      xStepper.setSpeed(0);  
      speedVal = 0;
      xStepper.runSpeed();   
   }
   else if (xJoy < 530 && xJoy > 50)
   {       
      xStepper.setSpeed((530 - xJoy) * 1); 
      speedVal = (530 - xJoy);    
   }
   else if (xJoy < 51)
   {       
      xStepper.setSpeed((530 - xJoy) * 35); 
      speedVal = ((530 - xJoy) * 35);     
   }
   else if(xJoy > 550 && xJoy < 950)
   {
      xStepper.setSpeed((550 - xJoy) * 1); 
      speedVal = (550 - xJoy);     
   }
   else if (xJoy > 949)
   {       
      xStepper.setSpeed((550 - xJoy) * 35); 
      speedVal = ((550 - xJoy) * 35);     
   }
}

Below is my latest program. I changed it to this because I wanted to be able to use the direction pin on the driver (DM556T). This works in one direction, but when I move the joystick the other way, the motor keeps spinning the same direction it was going but at half the speed. I checked the voltage at the direction pin on the driver and for some reason the direction pin has 3.2 volts to it all of the time. When I push the joystick in one direction, the voltage drops to 0.8 volts and when I push the joystick in the other direction the voltage drops to 1.6 volts. Shouldn't this be "0" for low and 3.3v for high?

#include <AccelStepper.h>

// change pins to match your setup.
const byte stepPin =     D1;
const byte dirPin =      D2;
const byte xJoyPin =     A0;
const byte stopDownPin = D6;
const byte stopUpPin =   D7;

long nextStep = 0;
long lastStep = 0;
float highSpeed = 1000;
float highAccel = 500;
float lowSpeed = 125;
float lowAccel = 50;
float speedVal = 0;
int joyVal = 0;
int dirVal = 1;

long location1 = 0;
long location2 = 0;
long location3 = 0;
long location4 = 0;
long location5 = 0;

AccelStepper xStepper(AccelStepper::DRIVER, stepPin, dirPin);

void setup() {
  Serial.begin(115200);

  xStepper.setMaxSpeed(highSpeed);
  xStepper.setAcceleration(highAccel);
  xStepper.setSpeed(speedVal);

  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
  pinMode(xJoyPin, INPUT);
  pinMode(stopDownPin, INPUT);
  pinMode(stopUpPin, INPUT);

  digitalWrite(dirPin, LOW);
  xStepper.setMinPulseWidth(20);

  delay(5);
}

void loop()
{ joyVal = analogRead(xJoyPin);

  if (joyVal >= 520 && joyVal <= 550) // ±15 hysteresis for center (0 speed)
  {
    xStepper.setSpeed(0);
    speedVal = 0;
    xStepper.stop();
  }

  if (joyVal < 520)
  {
    dirVal = -1;
    digitalWrite(dirPin, LOW);
    setStepper();
    joyVal = map(joyVal, 520, 16, 0, 200);
    slowMove();
    
    if (joyVal < 50)
    {
      fastMove();
    }
  }

  if (joyVal > 550)
  {
    dirVal = 1;
    digitalWrite(dirPin, HIGH);
    setStepper();
    joyVal = map(joyVal, 550, 1024, 0, 200);
    slowMove();
    
    if (joyVal > 150)
    {
      fastMove();
    }
  }

    xStepper.run();
}

void setStepper()
{
  nextStep = (xStepper.currentPosition() + dirVal);
  xStepper.moveTo(nextStep);
  lastStep = nextStep;
}

void slowMove()
{
  digitalWrite(dirPin, LOW);
  xStepper.setMaxSpeed(lowSpeed);
  xStepper.setAcceleration(lowAccel);
  xStepper.setSpeed(lowSpeed);
}

void fastMove()
{
  digitalWrite(dirPin, HIGH);
  xStepper.setMaxSpeed(highSpeed);
  xStepper.setAcceleration(highAccel);
  xStepper.setSpeed(highSpeed);
}

Your move functions both set the dir pin, overwriting your intent to set direction in loop.

wildbill,

I knew it was redundant on the slowMove(), but all of these are embedded in "if" statements. Wouldn't the condition determine which "if" statement gets used?

I'm not arguing, just trying to understand.

No.

In loop, depending on the position of the joystick you set the direction pin appropriately. Then you call slowmove which unconditionally sets dirpin LOW. Similar problem in fastmove.

Okay. I believe I understand.

I took the dirPin setting out of both move functions, but the motor still only turns in one direction.

When I push the joystick in one direction, I can get both fast and slow moves, but in the other direction I only get slow move (still spinning motor in the same direction, though).

When you make changes to your code, make a post with the latest version so that we can keep up.

I just checked the voltage again. I get 3.1 volts in one direction and 0.8 volts in the other. This driver is supposed to operate on 5 - 7 volt signal input. This may be the issue. I don't know how to get that much voltage using these micro-controllers. I've tried a logic level-converter, but I ended up getting LESS voltage when I went through it. I know I hooked it up as instructed and I even tried two separate, brand new boards and it was always the same.... 2.67 volts in one direction and 0.7 milli-volts in the other.

If joyval > 550 it will always be greater than 150 too. So the second section of loop always calls fastmove.

groundFungus,

Okay. Sorry about that. Code is below....


#include <AccelStepper.h>

// change pins to match your setup.
const byte stepPin =     D1;
const byte dirPin =      D2;
const byte xJoyPin =     A0;
const byte stopDownPin = D6;
const byte stopUpPin =   D7;

long nextStep = 0;
long lastStep = 0;
float highSpeed = 1000;
float highAccel = 500;
float lowSpeed = 125;
float lowAccel = 50;
float speedVal = 0;
int joyVal = 0;
int dirVal = 1;

long location1 = 0;
long location2 = 0;
long location3 = 0;
long location4 = 0;
long location5 = 0;

AccelStepper xStepper(AccelStepper::DRIVER, stepPin, dirPin);

void setup() {
  Serial.begin(115200);

  xStepper.setMaxSpeed(highSpeed);
  xStepper.setAcceleration(highAccel);
  xStepper.setSpeed(speedVal);

  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
  pinMode(xJoyPin, INPUT);
  pinMode(stopDownPin, INPUT);
  pinMode(stopUpPin, INPUT);

  digitalWrite(dirPin, LOW);
  xStepper.setMinPulseWidth(20);

  delay(5);
}

void loop()
{ joyVal = analogRead(xJoyPin);

  if (joyVal >= 520 && joyVal <= 550) // ±15 hysteresis for center (0 speed)
  {
    digitalWrite(dirPin, LOW);
    xStepper.setSpeed(0);
    speedVal = 0;
    xStepper.stop();
  }

  if (joyVal < 520)
  {
    dirVal = -1;
    digitalWrite(dirPin, LOW);
    setStepper();
    joyVal = map(joyVal, 520, 16, 0, 200);
    slowMove();
    
    if (joyVal < 50)
    {
      fastMove();
    }
  }

  if (joyVal > 550)
  {
    dirVal = 1;
    digitalWrite(dirPin, HIGH);
    setStepper();
    joyVal = map(joyVal, 550, 1024, 0, 200);
    slowMove();
    
    if (joyVal > 150)
    {
      fastMove();
    }
  }

    xStepper.run();
}

void setStepper()
{
  nextStep = (xStepper.currentPosition() + dirVal);
  xStepper.moveTo(nextStep);
  lastStep = nextStep;
}

void slowMove()
{
  xStepper.setMaxSpeed(lowSpeed);
  xStepper.setAcceleration(lowAccel);
  xStepper.setSpeed(lowSpeed);
}

void fastMove()
{
  xStepper.setMaxSpeed(highSpeed);
  xStepper.setAcceleration(highAccel);
  xStepper.setSpeed(highSpeed);
}

wildbill,

Ah! Good catch. I'll edit that and give it a go.

wildbill,

I just realized that I "mapped" joyVal before the second "if" statement. Wouldn't that reset joyVal to a new value?