Control of a Linear Can Stack Stepper Motor with a ULN2003 with a Home Sensor

Hey everyone,

I am try to make a little breadboard setup to test out a linear can stack motor for an application I am working on. I want to be able to control the motor based off a home sensor and I am planning on using an omron optical sensor

I am trying to use a MEGA2560 with a ULN2003 Stepper Motors and Motor Driver Boards.

I have figured out my first issue which was how to get power to the linear can stack motor. The connector only has 4 wires out so I need to bring in v+ through a parallel circuit with the phase pair wires. This "should" get the motor up and running but need to build the circuit and try it out.

I am newish to programing so the next challenge I need some help with is writing the code for controlling this motor and wiring up the flag sensor. The code I am using to start off is below. I appreciate the help in advance!

//www.elegoo.com
//2018.10.25

/*
  Stepper Motor Control - one revolution

  This program drives a unipolar or bipolar stepper motor.
  The motor is attached to digital pins 8 - 11 of the Arduino.

  The motor should revolve one revolution in one direction, then
  one revolution in the other direction.

*/

#include <Stepper.h>

const int stepsPerRevolution = 24;  // change this to fit the number of steps per revolution
const int RevolutionsPerMinute = 15;         // Adjustable range of 28BYJ-48 stepper is 0~17 rpm

// initialize the stepper library on pins 8 through 11:
Stepper myStepper(stepsPerRevolution, 8, 10, 9, 11);

void setup() {
  myStepper.setSpeed(RevolutionsPerMinute);
  // initialize the serial port:
  Serial.begin(9600);
}

void loop() {  
  // step one revolution  in one direction:
  Serial.println("clockwise");
  myStepper.step(stepsPerRevolution);
  delay(500);

  // step one revolution in the other direction:
  Serial.println("counterclockwise");
  myStepper.step(-stepsPerRevolution);
  delay(500);
}


how system know when it should start ?
does this sketch move the motor?

The stepper.h library is a terrible choice if you want to also be looking at a limit switch. While it is executing a myStepper.set(stepsPerRevolution) it cannot notice if it triggered the limit switch.

Maybe start with a non-blocking library like AccelStepper.h or MobaTools.

Here's a sloppy simulation of AccelStepper moving a stepper with a physical and simulated limit switches.

A ULN2003 cannot drive a bipolar motor.

1 Like

The stepper in your link and the stepper in your picture are totally different. You cannot use the ULN2003 to drive the bipolar motor in your picture. The ULN can only be used for unipolar steppers.
Which of the motors in that datasheet do you use?

2 Likes

The ubiquitous A4988 would work.

A4988

1 Like

I intend to use the linear can stepper motor. I added the other link because that is the controller I have on hand but looks like it won't work. Sounds like the A4988 will work with a bipolar according to JCA34F

The A4988 is designed to work with low impedance steppers. Your stepper looks like a high impedance stepper. Du you have the 5V or 12V version? The 5V version may work with an A4988 and a Vmot of at least 12V.
These steppers have a fairly high angle per step. Microstepping usually doesn't work well with those steppers. I think a simple H-bridge may work well.

I have the 5v version of the motor. Do you think the A4988 will work with the 5V?

With at least 12V and correct current setting it should work.

Hey DaveX. Thanks for the diagram for wiring and code. I have since sourced some 4988 controllers and have wire up a breadboard (see photos). I have an externa power supply hooked up at 12V and 0.34a. However I am still struggling to get the motor to move even with just absolute moves. I tried writing another code base to try and get it to move. Could you take a look at my code an give me some pointers?

#include <AccelStepper.h>

// Define motor interface type
#define motorInterfaceType 1 // Use 1 for a driver like A4988, DRV8825, etc.

// Define the pins for the stepper motor
const int stepPin = 10;
const int dirPin = 7;

// Create an instance of the AccelStepper class
AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin);

// Define constants for the stepper motor
const float stepAngle = 15.0; // degrees per step
const float travelPerStep = 0.0254; // mm per step

void setup() {
  // Set the maximum speed and acceleration
  stepper.setMaxSpeed(100); // Max speed in steps per second
  stepper.setAcceleration(50); // Acceleration in steps per second^2
  
  Serial.begin(9600); // Initialize serial communication
  Serial.println("Enter the distance to move in mm:");
}

void loop() {
  if (Serial.available() > 0) {
    // Read the input distance in mm
    float distanceToMove = Serial.parseFloat();
    
    // Wait until the input is fully received before prompting for direction
    delay(1000); // Short delay to allow buffer to clear
    
    Serial.println("Enter the direction (1 for up, -1 for down):");
    while (Serial.available() == 0); // Wait for direction input
    int direction = Serial.parseInt();
    
    // Calculate the number of steps needed
    int stepsToMove = distanceToSteps(distanceToMove) * direction;

    // Set the target position
    stepper.moveTo(stepper.currentPosition() + stepsToMove);

    // Move the motor to the target position
    while (stepper.distanceToGo() != 0) {
      stepper.run();
    }

    Serial.println("Movement complete!");
    Serial.println("Enter the next distance to move in mm:");
  }
}

// Function to convert distance in mm to steps
int distanceToSteps(float distanceInMM) {
  return round(distanceInMM / travelPerStep);
}


Is it a problem with the parsing or is it a problem with the motion?

In the pic it is unclear if there's a signal ground from the Mega to the driver. Pololu says:

Success! Thanks for all the help everyone! Getting some power to the A4988 was a great idea @DaveX :sweat_smile: . I got my motor moving and fully functional with an initialization homing procedure and can input distance I want to move in mm and the direction!



Below is the code I put together (with a lot of help from ChatGPT).

#include <AccelStepper.h>

// Define the pins for the stepper motor
const int motorInterfaceType = 1;  // Interface type: 1 for a driver like A4988 or DRV8825
const int stepPin = 10;
const int dirPin = 7;
const int flagPin = A1;  // Analog pin for the flag sensor

// Create an instance of the AccelStepper class
AccelStepper stepper(motorInterfaceType, stepPin, dirPin);

// Define constants for the stepper motor
const float stepAngle = 15.0;       // degrees per step
const float travelPerStep = 0.0254; // mm per step

void setup() {
  Serial.begin(9600);              // Initialize serial communication

  // Wait until the input is fully received before prompting for direction
  delay(2000); // Short delay to allow buffer to clear
    
  Serial.println("Initializing...");

  // Set the maximum speed and acceleration
  stepper.setMaxSpeed(1000);        // Max speed in steps per second
  stepper.setAcceleration(500);     // Acceleration in steps per second^2
  
  pinMode(flagPin, INPUT);         // Set the flag sensor pin as input
  
  // Stop any residual movement and reset position
  stepper.stop();
  stepper.setCurrentPosition(0);
  
  Serial.println("Homing the motor to the flag sensor...");
  homeMotor(); // Home the motor to the sensor

  Serial.println("Enter the relative distance to move in mm:");
}

void loop() {
  if (Serial.available() > 0) {
    // Read the distance to move in mm
    String distanceStr = Serial.readStringUntil('\n');
    float distanceToMove = distanceStr.toFloat();

    // Prompt for the direction
    Serial.println("Enter the direction (1 for up, -1 for down):");
    while (Serial.available() == 0); // Wait for direction input
    String directionStr = Serial.readStringUntil('\n');
    int direction = directionStr.toInt();

    // Calculate the number of steps needed
    int stepsToMove = round(distanceToMove / travelPerStep) * direction;

    // Debugging information
    Serial.print("Distance to move (mm): ");
    Serial.println(distanceToMove);
    Serial.print("Direction: ");
    Serial.println(direction);
    Serial.print("Steps to move: ");
    Serial.println(stepsToMove);

    // Move the motor by the specified relative distance
    stepper.move(stepsToMove);

    // Move the motor to the target position
    while (stepper.distanceToGo() != 0) {
      stepper.run();
    }

    Serial.println("Movement complete!");
    Serial.println("Enter the relative distance to move in mm:");
  }
}

// Homing function
void homeMotor() {
  int sensorValue = analogRead(flagPin);

  // Check if the sensor is already triggered
  if (sensorValue > 1) {  // Adjust the threshold as needed
    Serial.println("Sensor triggered during initialization. Moving up 5mm.");
    
    // Calculate the number of steps to move up 5mm
    int stepsToMoveUp = round(2.0 / travelPerStep);
    
    // Move the motor up by 5mm
    stepper.move(stepsToMoveUp);
    while (stepper.distanceToGo() != 0) {
      stepper.run();
    }
  }
  
  // Wait until the input is fully received before prompting for direction
  delay(2000); // Short delay to allow buffer to clear
  Serial.println("Starting homing procedure...");

  // Set speed for homing
  stepper.setSpeed(-1000);  // Set a negative speed to move towards the flag

  // Move towards the flag sensor until it's triggered
  while (true) {
    sensorValue = analogRead(flagPin);
    Serial.print("Sensor value: ");
    Serial.println(sensorValue);

    if (sensorValue > 5) {  // Adjust threshold as needed
      break;
    }
    
    stepper.runSpeed();
  }

  // Stop the motor and set the current position as zero
  stepper.stop();
  stepper.setCurrentPosition(0);
  Serial.println("Homing complete. Position set to zero.");
}


This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.