Homing stepper motor + 4 extra positions

Hello,

In an earlier post I asked how to control a steppermotor using the accelstepper library. Now that I managed to get that to work I am trying to add more functionality to my system. The idea is, is that the arduino + shield act as a kinda of "steppermotor driver". The arduino is controlled by a Siemens logosoft PLC.

Now the problem is that I got all the positions to work except for the homing position.

So the idea is that upon startup the PLC will send a message to the arduino to run the homing cycle. The steppermotor turns CCW until it hits the limit switch. Then according to the PLC code it will go to position 1, 2, 3, 4. When it is done it will return to a waiting stage.

Now my question is, How do I manage to get a "homing" solution into my code? I found some videos and information on forums. But none seem applicable in my case, or atleast to my knowledge.

// Include the AccelStepper library:
#include <AccelStepper.h>

// Define number of steps per revolution:
const int stepsPerRevolution = 200;

// Give the motor control pins names:
#define pwmA 3
#define pwmB 11
#define brakeA 9
#define brakeB 8
#define dirA 12
#define dirB 13
#define Q1IN 23
#define Q2IN 25
#define Q4IN 27
#define Q5IN 29
#define Q6IN 31
#define Q8IN 33
#define I5 35
#define Q1OUT 52
#define Q2OUT 50
#define Q4OUT 48
#define Q5OUT 46
#define Q6OUT 44
#define Q8OUT 22

// Define the AccelStepper interface type:
#define MotorInterfaceType 2

// Create a new instance of the AccelStepper class:
AccelStepper stepper = AccelStepper(MotorInterfaceType, dirA, dirB);

void setup() {
  // Set the PWM and brake pins so that the direction pins can be used to control the motor:
  pinMode(pwmA, OUTPUT);
  pinMode(pwmB, OUTPUT);
  pinMode(brakeA, OUTPUT);
  pinMode(brakeB, OUTPUT);
  pinMode(Q1OUT, INPUT_PULLUP); //HOMING
  pinMode(Q2OUT, INPUT_PULLUP); //POSITION 1
  pinMode(Q4OUT, INPUT_PULLUP); //POSITION 2
  pinMode(Q5OUT, INPUT_PULLUP); //POSITION 3
  pinMode(Q6OUT, INPUT_PULLUP); //POSITION 4
  pinMode(Q8OUT, INPUT_PULLUP); //HOMING DONE
  pinMode(Q1IN, OUTPUT);
  pinMode(Q2IN, OUTPUT);
  pinMode(Q4IN, OUTPUT);
  pinMode(Q5IN, OUTPUT);
  pinMode(Q6IN, OUTPUT);
  pinMode(Q8IN, OUTPUT);
  pinMode(I5, OUTPUT); // POSITION REACHED
  

  digitalWrite(pwmA, HIGH);
  digitalWrite(pwmB, HIGH);
  digitalWrite(brakeA, LOW);
  digitalWrite(brakeB, LOW);

  // Set the maximum steps per second:
  stepper.setMaxSpeed(100);
  stepper.setAcceleration(100.0);
}

void loop()
{ 

  int Homing = digitalRead(Q1OUT);
  int Pos1 = digitalRead(Q2OUT);
  int Pos2 = digitalRead(Q4OUT);
  int Pos3 = digitalRead(Q5OUT);
  int Pos4 = digitalRead(Q6OUT);
  int HomingDone = digitalRead(Q8OUT);
  int move_finished = 1;  // Used to check if move is completed
  long initial_homing = -1;  // Used to Home Stepper at startup
  digitalWrite(Q1IN, HIGH);
  digitalWrite(Q2IN, HIGH);
  digitalWrite(Q4IN, HIGH);
  digitalWrite(Q5IN, HIGH);
  digitalWrite(Q6IN, HIGH);
  digitalWrite(Q8IN, HIGH);

  
  while (digitalRead(Homing && !HomingDone)) 
  {  // Make the Stepper move CCW until the switch is activated   
    stepper.moveTo(initial_homing);  // Set the position to move to
    initial_homing--;  // Decrease by 1 for next move if needed
    stepper.run();  // Start moving the stepper
    delay(5);
  }
    
    if (Pos1 == HIGH)
    {
       stepper.move(25); // 200/second = 1 rps
       stepper.runToPosition(); 
       delay(500);
       digitalWrite(I5, HIGH);
       delay(500);
       digitalWrite(I5, LOW);
    }

    if (Pos2 == HIGH)
    {
       stepper.move(50); // 200/second = 1 rps
       stepper.runToPosition(); 
       delay(500);
       digitalWrite(I5, HIGH);
       delay(500);
       digitalWrite(I5, LOW);
    }

    if (Pos3 == HIGH)
    {
       stepper.move(30); // 200/second = 1 rps
       stepper.runToPosition(); 
       delay(500);
       digitalWrite(I5, HIGH);
       delay(500);
       digitalWrite(I5, LOW);
    }

    if (Pos4 == HIGH)
    {
       stepper.move(60); // 200/second = 1 rps
       stepper.runToPosition(); 
       delay(500);
       digitalWrite(I5, HIGH);
       delay(500);
       digitalWrite(I5, LOW);
    }
    
    stepper.move(0);
    stepper.runSpeed();
}

Currently with this code all the motor will do is turn without end even when passing the limit switch. I would like it to turn until it hits the switch and then to stop

The simplest way to home a stepper motor is to move it one step at a time and check the limit switch between each step. If there nothing else needs to happen you can just time it with a delay() - something like

while (digitalRead(Homing && !HomingDone)) 
  {                 // Make the Stepper move CCW until the switch is activated   
    
    stepper.runSpeedToPosition();  // Start moving the stepper
    if (stepper.distanceToGo == 0) {
        limitSwitchState = digitalRead(limitSwitchPin);
        if (limitSwitchState == LOW) {  // assumes LOW when triggered
           HomingDone = true;
        }
        else {
           stepper.move(1);  
        }
        delay(50); // not sure of this is needed to control the speed of single steps
  }

I have not tested this and there may well be a better way to do single steps with Accelstepper

...R

1 Like

Normally when HOMING something the stepper runs at full (or close to) speed until it triggers something.

From there there are two approaches.

  1. First trigger switch tells it, it is close to home and to decel until it triggers a second home switch then back off that trigger X amount and use that as absolute zero.

  2. Hit only one switch/position and come to a dead stop then back off X amount. ( may need half to three quarter speed ) and the trigger should be called before and during movement NOT AFTER !

A lot of more reliable full size CNC machines used method one but with super reliable encoders today
(closed loop) most use method 2

Both methods are used to enable a fast return to zero

EDIT is using either method you should allow for a small margin of "over run"

Thank you Robin,

At first I didn't really understand the code but yours guided me to the correct one!

I managed to get my code to work.

A short summary of the setup:

I have a steppermotor, arduino mega and an arduino rev3 motor shield.
Once a button (button 0) is pressed the motor is supposed to rotate towards the limit switch. Once it hits the limit switch it will move 10 steps away from the switch.
if button 1 is pressed it will move to position 1 and reset the step count
if button 2 is pressed it will move to position 2 and reset the step count
if button 3 is pressed it will move to position 3 and reset the step count
if button 4 is pressed it will move to position 4, wait 1 second, go back to position 0 and reset the step count

The code I managed to mustar up is as followed

/* Example sketch to control a stepper motor with Arduino Motor Shield Rev3, Arduino UNO and AccelStepper.h library: number of steps or revolutions. More info: https://www.makerguides.com */

// Include the AccelStepper library:
#include <AccelStepper.h>

// Define number of steps per revolution:
const int stepsPerRevolution = 200;

// Give the motor control pins names:
#define pwmA 3
#define pwmB 11
#define brakeA 9
#define brakeB 8
#define dirA 12
#define dirB 13

// Define the AccelStepper interface type:
#define MotorInterfaceType 2

// Create a new instance of the AccelStepper class:
AccelStepper stepper = AccelStepper(MotorInterfaceType, dirA, dirB);

void setup() {
  // Set the PWM and brake pins so that the direction pins can be used to control the motor:
  pinMode(pwmA, OUTPUT);
  pinMode(pwmB, OUTPUT);
  pinMode(brakeA, OUTPUT);
  pinMode(brakeB, OUTPUT);
  pinMode(52, INPUT_PULLUP);
  pinMode(50, INPUT_PULLUP);
  pinMode(48, INPUT_PULLUP);
  pinMode(46, INPUT_PULLUP);
  pinMode(44, INPUT_PULLUP);
  pinMode(42, INPUT_PULLUP);
  pinMode(53, INPUT_PULLUP);
  pinMode(22, OUTPUT);

  digitalWrite(pwmA, HIGH);
  digitalWrite(pwmB, HIGH);
  digitalWrite(brakeA, LOW);
  digitalWrite(brakeB, LOW);
  

  // Set the maximum steps per second:
  stepper.setMaxSpeed(600);
}

void loop() 
{

  
  digitalWrite(22, LOW);                          //Homing
  if (digitalRead(52) == HIGH)
  {
     while (digitalRead(53) == LOW)
    {
      stepper.setSpeed(-100);
      stepper.runSpeed();
    }
  }
  
  stepper.setCurrentPosition(0);                  //Limit switch
  if (digitalRead(53) == HIGH)
  {
     while (stepper.currentPosition() != 10) 
     {
      stepper.setSpeed(200);
      stepper.runSpeed();
     }
  }

  stepper.setCurrentPosition(0);                  //Position 1
  if (digitalRead(50) == HIGH)
  {
    while (stepper.currentPosition() != 50)
     {
      stepper.setSpeed(100);
      stepper.runSpeed();
     }
    stepper.setCurrentPosition(0);
  delay(1000);
  }
  
  stepper.setCurrentPosition(0);                  //Position 2
  if (digitalRead(48) == HIGH)
  {
    while (stepper.currentPosition() != 25)
     {
      stepper.setSpeed(100);
      stepper.runSpeed();
     }
    stepper.setCurrentPosition(0);
  delay(1000);
  }
  
  stepper.setCurrentPosition(0);                  //Position 3
  if (digitalRead(46) == HIGH)  
  {
    while (stepper.currentPosition() != -35)
    {
      stepper.setSpeed(-100);
      stepper.runSpeed();
    }
    stepper.setCurrentPosition(0);
  delay(1000);
  }
  
  stepper.setCurrentPosition(0);                  //Position 4
  if (digitalRead(44) == HIGH) 
  {
    while (stepper.currentPosition() != 75)
    {
      stepper.setSpeed(100);
      stepper.runSpeed();
    }
  delay(1000);
     while (digitalRead(53) == LOW)
    {
      stepper.setSpeed(-100);
      stepper.runSpeed();
    }
  }
  
  stepper.setCurrentPosition(0);                  //Limit switch
  if (digitalRead(53) == HIGH)
  {
     while (stepper.currentPosition() != 10) 
     {
      stepper.setSpeed(200);
      stepper.runSpeed();
     }
  }
}

hope this will help anybody in the future if they have a similar project

Thanks for the update

...R

Hint for the future: give the pins meaningful names.