stepper limit switch

Hello,

i have setup a stepper that moves CW and CCW.

I defined full rotation stepps.

I have one magnet for start and stop.(only start is activated now)

For start condition START magnet must be activated than motor spinns to defined fullrotaton steps, than turns to start position and checks again that START magnet is acivated.
Motors makes as much circles as defined in rounds. At start and stop motor accelerates and decelerates.

All this works ok.

I would like to add STOP button with function:

  • if stop magnet is activated it starts to decelerate the same as in scenario that works now-fullrotation
  • after that it turns to other direction to start position and decelerates

I added this to code:

for (int i = 0; i < numOfSteps && !digitalRead(STOPMAGNET); i++ )

but it stops hard way- no deceleration and after turning to start position it stops because magnet at start is read for stop and not read again for start. (potor shoud pass magnet after read for few stepps)

How to set up stop/start corectly ?

My code that works:

void stepper() {

  for (int i = 0 ; i < (rounds * 2) ; i++) {
    delay(300);
      {

       if (direction == 1)
      {
         lcdI2C.clear();
         lcdI2C.print("WAITING MAGNET");
         delay(100);
         while(digitalRead(STARTMAGNET)==LOW ) ;  // Wait for start magnet
         lcdI2C.selectLine(2);
         lcdI2C.print("  POSITION OK");
         delay(300);
         lcdI2C.clear();
         lcdI2C.print("RUNNING...");
        digitalWrite(HEATLAMP_IR1,HIGH);
        delay(500);
        digitalWrite(HEATLAMP_IR2,HIGH);
        delay(800);
        digitalWrite(STEPPER_PIN_DIR,HIGH);      // set direction 1
        digitalWrite(STEPPER_PIN_ENA,HIGH);
        delayMicroseconds(200);
        direction = 2;
        { delay(50);
          int delay_time = SLOW;
          int numOfSteps = fullRotation;
          int fast = 300 + 12*(100-speed);
          float accSteps = 300; 
          for (int i = 0; i < numOfSteps; i++ )
            {

            if (i < accSteps)
            {
            delay_time = (SLOW - FAST) * pow(float(i - accSteps), 2) / float(accSteps * accSteps) + FAST;
            }
            else if (i > numOfSteps - accSteps)
            {
            delay_time = (SLOW - FAST) * pow(float(i - numOfSteps + accSteps), 2) / float(accSteps * accSteps) + FAST;
            }
            else
            {
            delay_time = fast;
            }
         delayMicroseconds(300);
         digitalWrite(STEPPER_PIN_PUL, HIGH);   //  motor
         delayMicroseconds(delay_time);                       
         digitalWrite(STEPPER_PIN_PUL, LOW);    
         delayMicroseconds(delay_time);   
     
        }
       }
         digitalWrite(HEATLAMP_IR1,LOW);
         delay(500);
         digitalWrite(HEATLAMP_IR2,LOW);
         delay(500);
         digitalWrite(STEPPER_PIN_ENA, LOW);
      }
      else
        {
           digitalWrite(STEPPER_PIN_DIR,LOW);     // set direction 2
           digitalWrite(STEPPER_PIN_ENA,HIGH);
           delayMicroseconds(300);
           direction = 1;
         { delay(50);
           int delay_time = SLOW;
           int numOfSteps = fullRotation;
           float accSteps = 300;
           for (int i = 0; i < numOfSteps; i++ )
           {
             if (i < accSteps)
            {
            delay_time = (SLOW - FAST) * pow(float(i - accSteps), 2) / float(accSteps * accSteps) + FAST;
            }
            else if (i > numOfSteps - accSteps)
            {
            delay_time = (SLOW - FAST) * pow(float(i - numOfSteps + accSteps), 2) / float(accSteps * accSteps) + FAST;
            }
            else
            {
            delay_time = BACK;
            }

            digitalWrite(STEPPER_PIN_PUL, HIGH);   // motor
            delayMicroseconds(delay_time);                       
            digitalWrite(STEPPER_PIN_PUL, LOW);    
            delayMicroseconds(delay_time);   
        }
       }
       digitalWrite(STEPPER_PIN_ENA, LOW);
       }
   }    
}
}

You have not posted a complete program. It is much easier to help if you post a complete program that illustrates the problem.

You have big chunks of repeated code - put that into a function so it only needs to be written once.

You seem to have a lot of stuff in your stepper() function that is not concerned with the actual movement of the motor. I suggest you make a short function whose only role is to move the motor. Things like waiting for switches and printing can be done elsewhere.

If you want to stop with deceleration then your switch must cause the deceleration process to start. I can't figure from your code how that normally works.

Have you considered the AccelStepper library ?

...R

Hello,

i modified code from one example. All works acceleration/deceleration with START magnet.

I installed STOP magnet and it is not working as i would like. Description in my firs post.

Full code in attachement.

CODE.txt (8.63 KB)

OP’s code from Reply #2 so others don’t have to download it

// Include Libraries
#include "Arduino.h"
#include "LiquidCrystal_PCF8574.h"
#include "IRremote.h"
#include "Encoder.h"
#include "Button.h"
#include "math.h"


// Pin Definitions
//ROTARY KNOF
#define RotaryEncoder_PIN_D  4  
#define RotaryEncoder_PIN_CLK 2  
#define RotaryEncoder_PIN_S1  5 
//HEATLAMP IR
#define HEATLAMP_IR1  10  
#define HEATLAMP_IR2  11  
//#define HEATLAMP_IR3  13  
//MAGNETNI KONTAKTI
#define STARTMAGNET  6  
#define STOPMAGNET  7   
//KONTROLA MOTORJA TB6600
#define STEPPER_PIN_PUL  9
#define STEPPER_PIN_DIR  8
#define STEPPER_PIN_ENA  12

#define SLOW 2500
#define FAST 1100
#define BACK 350

// set default 
int speed = 65;
int angles = 4;
int direction = 1;
const int fullRotation = 16940;   /



// Global variables and defines
// lcd 

#define LCD_ADDRESS 0x3F
//#define LCD_ADDRESS 0x27

// Define LCD characteristics
#define LCD_ROWS 2
#define LCD_COLUMNS 16
#define SCROLL_DELAY 150
#define BACKLIGHT 255
long rotaryEncDOldPosition  = 0;
// object initialization
Encoder rotaryEncD(RotaryEncoder_PIN_D, RotaryEncoder_PIN_CLK);
Button rotaryEncDButton(RotaryEncoder_PIN_S1);
LiquidCrystal_PCF8574 lcdI2C;
IRsend ir_led;

enum menuState {HOME, VIDEO, STILLS, VIDSTART, STILSTART, SPEED, ANGLES, VIDBACK, STILBACK, CHANGESPEED, CHANGEANGLES} state = STILLS, oldState = 10;

// to se naloži ko je powered
void setup()
{
  // Setup Input/Output pin definitions  
  pinMode(STEPPER_PIN_PUL, OUTPUT);
  pinMode(STEPPER_PIN_DIR, OUTPUT);
  pinMode(STEPPER_PIN_ENA, OUTPUT);
  pinMode(HEATLAMP_IR1, OUTPUT);
  pinMode(HEATLAMP_IR2, OUTPUT);
  //  pinMode(HEATLAMP_IR3, OUTPUT);
  pinMode(STARTMAGNET, INPUT);
  pinMode(STOPMAGNET, INPUT);
   
    // Setup Serial which is useful for debugging
  // Use the Serial Monitor to view printed messages
  Serial.begin(9600);
  while (!Serial) ; // wait for serial port to connect. Needed for native USB
  Serial.println("start");

  // initialize the lcd
  lcdI2C.begin(LCD_COLUMNS, LCD_ROWS, LCD_ADDRESS, BACKLIGHT);
  rotaryEncDButton.init();
  pinMode(RotaryEncoder_PIN_S1, INPUT_PULLUP);

  lcdI2C.print("WAITING START");
  lcdI2C.selectLine(2);
  lcdI2C.print("POSITION");
  delay(300);
  while(digitalRead(STARTMAGNET)==LOW ) ;  // Wait for startni magnet JA ALI NE
  lcdI2C.clear();
  lcdI2C.selectLine(2);
  lcdI2C.print("START POSITION OK");
  delay(50);
}

// Main logic IR 
void loop()
{
  //Read encoder new position
  long rotaryEncDNewPosition = rotaryEncD.read() / 2;
  bool select = rotaryEncDButton.onPress();
  char menuDir = ' ';
  if (rotaryEncDNewPosition != rotaryEncDOldPosition) {
    //Serial.println(rotaryEncDNewPosition);
    if (rotaryEncDNewPosition < rotaryEncDOldPosition)
    {
      menuDir = 'L';
    }
    else if (rotaryEncDNewPosition >= rotaryEncDOldPosition)
    {
      menuDir = 'R';
    }
    rotaryEncDOldPosition = rotaryEncDNewPosition;
  }

  if (state != oldState)
  {
    lcdI2C.clear();

    oldState = state;
  }

  lcdI2C.selectLine(1);
  lcdI2C.print(printState(state));

  switch (state)
  {
     case STILLS:
      if (select)
        state = STILSTART;
      break;

     case VIDSTART:
      if (menuDir == 'R')
       state = SPEED;
      else if (menuDir == 'L')
        state = VIDBACK;
      if (select) {
        }
     break;


    case SPEED:
      if (menuDir == 'L')
        state = ANGLES;
      else if (menuDir == 'R')
        state = STILBACK;
      if (select)
        state = CHANGESPEED;
      break;

    case CHANGESPEED:
      if (menuDir == 'L')
      {
        speed-=5;
        lcdI2C.selectLine(2);
        lcdI2C.print("     ");
      }
      else if (menuDir == 'R')
      {
        speed+=5;
        lcdI2C.selectLine(2);
        lcdI2C.print("     ");
      }
      speed=constrain(speed,0,100);
      lcdI2C.selectLine(2);
      lcdI2C.print(speed);
      lcdI2C.print("%");


      if (select)
        state = STILSTART;
      break;

    case VIDBACK:
      if (menuDir == 'L')
        state = SPEED;
      else if (menuDir == 'R')
        state = VIDSTART;
      if (select)
        state = VIDEO;
      break;


    case STILSTART:
      if (menuDir == 'R')
        state = ANGLES;
      else if (menuDir == 'L')
        state = STILBACK;
      if (select)
        stills();
      break;

    case ANGLES:
      if (menuDir == 'L')
        state = STILSTART;
      else if (menuDir == 'R')
        state = SPEED;
      if (select)
        state = CHANGEANGLES;
      break;

    case CHANGEANGLES:
      if (menuDir == 'L')
      {
        angles--;
        lcdI2C.selectLine(2);
        lcdI2C.print("     ");
      }
      else if (menuDir == 'R')
      {
        angles++;
        lcdI2C.selectLine(2);
        lcdI2C.print("     ");
      }

      lcdI2C.selectLine(2);
      lcdI2C.print(angles);

      if (select)
        state = STILSTART;
      break;

    case STILBACK:
      if (menuDir == 'L')
        state = ANGLES;
      else if (menuDir == 'R')
        state = STILSTART;
      if (select)
        state = STILLS;
      break;

  }
}

String printState(int curstate)
{
  switch (curstate) {
    case 0:
      return "HOME";
    case 1:
      return "IR";
    case 2:
      return "  IR ONE";
    case 3:
      return "  START";
    case 4:
      return "START ";
    case 5:
      return "SPEED";
    case 6:
      return "PASSES";
    case 7:
      return "BACK";
    case 8:
      return "BACK1";
    case 9:
      return " SPEED:";
    case 10:
      return "NR. PASSES:";
  }
}


void stills() {

  for (int i = 0 ; i < (angles * 2) ; i++) {
    delay(300);
      {

       if (direction == 1)
      {
         lcdI2C.clear();
         lcdI2C.print("WAITING MAGNET");
         delay(100);
         while(digitalRead(STARTMAGNET)==LOW ) ;  // Wait for startni magnet
         lcdI2C.selectLine(2);
         lcdI2C.print("  OK !");
         delay(300);
         lcdI2C.clear();
         lcdI2C.print("RUNNING...");
        digitalWrite(HEATLAMP_IR1,HIGH);
        delay(500);
        digitalWrite(HEATLAMP_IR2,HIGH);
        delay(800);
        digitalWrite(STEPPER_PIN_DIR,HIGH);      // set direction 1
        digitalWrite(STEPPER_PIN_ENA,HIGH);
        delayMicroseconds(200);
        direction = 2;
        { delay(50);
          int delay_time = SLOW;
          int numOfSteps = fullRotation;
          int fast = 300 + 12*(100-speed);
          float accSteps = 300; 
          for (int i = 0; i < numOfSteps; i++ )
            {

            if (i < accSteps)
            {
            delay_time = (SLOW - FAST) * pow(float(i - accSteps), 2) / float(accSteps * accSteps) + FAST;
            }
            else if (i > numOfSteps - accSteps)
            {
            delay_time = (SLOW - FAST) * pow(float(i - numOfSteps + accSteps), 2) / float(accSteps * accSteps) + FAST;
            }
            else
            {
            delay_time = fast;
            }
         delayMicroseconds(300);
         digitalWrite(STEPPER_PIN_PUL, HIGH);   //  motor
         delayMicroseconds(delay_time);                       // wait for a second
         digitalWrite(STEPPER_PIN_PUL, LOW);    
         delayMicroseconds(delay_time);   
     
        }
       }
         digitalWrite(HEATLAMP_IR1,LOW);
         delay(500);
         digitalWrite(HEATLAMP_IR2,LOW);
         delay(500);
         digitalWrite(STEPPER_PIN_ENA, LOW);
      }
      else
        {
           digitalWrite(STEPPER_PIN_DIR,LOW);     // set direction 2
           digitalWrite(STEPPER_PIN_ENA,HIGH);
           delayMicroseconds(300);
           direction = 1;
         { delay(50);
           int delay_time = SLOW;
           int numOfSteps = fullRotation;
           float accSteps = 300;
           for (int i = 0; i < numOfSteps; i++ )
           {
             if (i < accSteps)
            {
            delay_time = (SLOW - FAST) * pow(float(i - accSteps), 2) / float(accSteps * accSteps) + FAST;
            }
            else if (i > numOfSteps - accSteps)
            {
            delay_time = (SLOW - FAST) * pow(float(i - numOfSteps + accSteps), 2) / float(accSteps * accSteps) + FAST;
            }
            else
            {
            delay_time = BACK;
            }

            digitalWrite(STEPPER_PIN_PUL, HIGH);   // motor
            delayMicroseconds(delay_time);                       // wait for a second
            digitalWrite(STEPPER_PIN_PUL, LOW);    
            delayMicroseconds(delay_time);   
        }
       }
       digitalWrite(STEPPER_PIN_ENA, LOW);
       }
   }    
}
}

…R

Your program does not attempt to do anything with the stopMagnet pin.

You are using the startMagnet as a blocking device so nothing can happen until it is triggered

while(digitalRead(STARTMAGNET)==LOW ) ;  // Wait for startni magnet

What I can't see is where the deceleration starts, or what causes it to start. Like I said earlier, your code is very difficult to make sense of.

IMHO the code needs a complete re-write. There should be a function (called from loop() ) that checks and saves the state of all the inputs - that should not be part of the stepper code. There should be another function called from loop() to see if it is time for the next step. That way if there is a change in the inputs it can be applied to the calls for steps. Have a look at this Simple acceleration code.

...R