Run a bipolar stepper motor and stop with limit switches

Hi,

I am a student and new to programming. I am working on a project, where I have to run a bipolar stepper motor which drives a linear guide, and stop the stepper motor when one of the components of linear guide touches limit switch. Please help me if anyone knows how to construct the C++ code (arduino) . I am able to run the stepper motor with one of the inbuilt arduino C++ code, but don't know how to include code for limit switch.
Following are the hardware I am using,

  • lattepanda V1
  • Nema 17 bipolar stepper motor (RS)
  • L298N motor driver
  • limit switch (V-155-1C25)
    And following is the C++ code as of now.

/*
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 = 200;  // change this to fit the number of steps per revolution
// for your motor

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

void setup() {
  // set the speed at 60 rpm:
  myStepper.setSpeed(60);
  // 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);
}

Note use a code tags when insert the code to the forum

a limit switch is just a momentary button. read tutorials on buttons here or there or use a button library such as Button in easyRun or OneButton or Toggle from @dlloyd.

please edit your post, select the code part and press the </> icon in the tool bar to mark it as code. It's barely readable as it stands. (also make sure you indented the code in the IDE before copying, that's done by pressing ctrlT on a PC or cmdT on a Mac)

Drop the L298. It's a DC motor driver not suitble for stepper motors requiring the current control likely needed for that stepper.

Please provide links to your components, especially to your stepper. Nema17 tells us nothing about the electrical specifications of that motor. As already mentioned by @Railroader, its very likely that the stepper doesn't fit to your driver. The L298N is a really ancient motor driver.

Isn't that a windows board?
Which Arduino board are you using?

Specifications of stepper motor are as follows..
Step Angle 0.9
Step Angle Accuracy (Full Step, No Load) ±5 %
Rated Voltage 2.8 V
Current/Phase 1.68 A
Resistance/Phase 1.65Ω
Inductance/Phase 2.8 MH
Detent Torque 25 mNm
Holding Torque 44 Ncm
Rotor Inertia 68 G-CM²
Weight 0.35 Kg
Number of Leads 4 N°.

And, lattepanda is a windows borad which has inbuilt arduino.

As has been said, the L298 is not an ideal driver for that stepper. If you are using L298, what are you powering it from? If the 5v from the Arduino then you are just about within the rating of the motor since the L298 drops ~2v, but that motor is designed to be driven by a modern current-controlled driver. DRV8825 is specifically designed for modern steppers which are microstep capable but would require probably a 12v supply, it takes care of regulating the current and voltage to the motor. If you really want to use a 5v supply then the DRV8834 could be used. Both these are available on carrier boards from Pololu. You would need to set the motor coil current on the driver board and there is an excellent video tutorial on the Pololu website on how to do this. I suspect that you will not need to set the current to the full rated value, I suggest you start at 0.5A and increase it if you need more torque.

Do NOT try to supply the motor driver from the 5v pin of the arduino since that isn't designed for high currents.

The stepper you have by the way has 360/0.9 = 400 steps per rev rather than 200 which you entered in your code. With a modern drivier you can also add microstepping to get finer resolution but that's probably a refinement you don't need yet.

hi,

I could not change the L298 at the moment, but later i will try with suggested driver. Please help me out with the code. how can i callout limit switch to stop the motor. any ideas on the coding?

Hi,

As i mentioned before, i am working on Arduino coding to run stepper motor and stop it when touches the limit switch.
So far i developed a code. but the problem is, i would like to include a case where i can to stop and start the motor manually when i want to.
can anyone help me with writing a switch case ? i am attaching the developed code, but it has some error i believe. any thoughts on developing code is appreciated.
Thank you.

#include <ezButton.h>
#include <AccelStepper.h>

#define DIRECTION_CCW -1
#define DIRECTION_CW   1
#define MAX_POSITION 0x7FFFFFFF // maximum of position we can set (long type)

ezButton limitSwitch(7); // create ezButton object that attach to pin 7;
AccelStepper stepper(AccelStepper::FULL4WIRE, 8, 9, 10, 11);

int direction  = DIRECTION_CW;
long targetPos = 0;
String command;

// States descriptive names
enum {motorStop, motorRun};
unsigned char motorState;  // What the door is doing at any given moment.

void setup() {
  Serial.begin(9600);
  delay(20);
  
  motorState = motorStop;
  limitSwitch.setDebounceTime(50); // set debounce time to 50 milliseconds

  stepper.setMaxSpeed(60.0);   // set the maximum speed
  stepper.setAcceleration(40.0); // set acceleration
  stepper.setSpeed(50);         // set initial speed
  stepper.setCurrentPosition(0); // set position

  targetPos = direction * MAX_POSITION;
  stepper.moveTo(targetPos);
}

void loop() {
    
  switch (motorState) {
      
    case motorStop: // Nothing happening, waiting for switchInput
      stepper.stop();
      Serial.println("motor stop");
      
      if (Serial.available()) {
        command = Serial.readStringUntil('\n');
        if (command.equals("start")) {
          Serial.println("Start");
          motorState = motorRun;
          break;
        }
        else {
          Serial.println("Invalid command");
          break; // State remains the same
        }
      }
    break;  
    case motorRun: // Nothing happening, waiting for switchInput
      stepper.run();
      Serial.println("motor run");
        
      limitSwitch.loop(); // MUST call the loop() function first
      if (limitSwitch.isPressed()) {
        Serial.println(F("The limit switch: TOUCHED"));
        motorState = motorStop;
        direction *= -1; // change direction
        Serial.print(F("The direction -> "));
        if (direction == DIRECTION_CW)
          Serial.println(F("CLOCKWISE"));
        else
          Serial.println(F("ANTI-CLOCKWISE"));
        targetPos = direction * MAX_POSITION;
        stepper.setCurrentPosition(0); // set position
        stepper.moveTo(targetPos);
        break;
      }
       
      if (Serial.available()) {
        command = Serial.readStringUntil('\n');
        if (command.equals("s")) {
          Serial.println("STOP");
          motorState = motorStop;
          break;
        }
        else {
          Serial.println("Invalid command");
          break; // State remains the same,
        }
      }
      
      // without this part, the move will stop after reaching maximum position
      //  if (stepper.distanceToGo() == 0) { // if motor moved to the maximum position
      //    stepper.setCurrentPosition(0);   // reset position to 0
      //    stepper.moveTo(targetPos);       // move the motor to maximum position again
      //  }
      
      //  stepper.run(); // MUST be called in loop() function
  }
  delay(5);  // delay in between reads for stability
}