Turning actuator on/off changing directions wi/limit switches, basic positioning

I have a linear actuator I'm trying to expand and contract until it hits a limit switch. If it extends and hits the limit switch it should stop and reverse direction, contracting until it hits the other limit switch. For testing purposes I have disconnected the actuator and am only using the motor controller which has indicator LEDs for direction/duty cycle (they get brighter or dimmer depending upon pwm).

Hardware/Software:
Arduino mega -
VNH5019 Motor Driver - https://www.pololu.com/product/1451
Limit switch - https://www.amazon.com/gp/product/B00E0JOTV8/ref=oh_aui_detailpage_o03_s00?ie=UTF8&psc=1
Button library - Robots + Big Data: Arduino Button Docs

Code:

#include <RBD_Timer.h>
#include <RBD_Button.h>

const int INA = 28;  // for motor controller
const int INB = 34;  // wut he said ^
const int PWM = 4;

RBD::Button flexLimit(36, false);  // i have resistors wired in series
RBD::Button extendLimit(38, false);  // so I don't need the pull-up resistors on the board

boolean homed = false;
boolean ableToMove = false;


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

  pinMode(INA,OUTPUT);
  pinMode(INB,OUTPUT);
  pinMode(PWM,OUTPUT);
  
  Serial.print("Able to move: ");
  Serial.println(ableToMove);
}

void loop() {
   if(!homed) {
    homePosition();
    Serial.println("Ready");
    Serial.println();
    ableToMove = true;
  }
  
}

void homePosition() {
  Serial.println("Homing...");
  if(extendLimit.isReleased()) {
    Serial.println("Extending...");
    setDir(1);
    while(extendLimit.isReleased()) {
      Serial.println("Extend pwm");
      analogWrite(PWM, 200);
    }
    Serial.println("End pwm1");
    analogWrite(PWM, 0);
    setDir(0);
  }

  homed = true;
}

void setDir(int d) {
  Serial.println("setting direction");
  switch(d) {
    case 0: // off?
    digitalWrite(INA,LOW);
    digitalWrite(INB,LOW);
    break;
    case 1: // contract actuator (extension)
    digitalWrite(INA,HIGH);
    digitalWrite(INB,LOW);
    break;
    case 2:  // extend actuator (flexion)
    digitalWrite(INA,LOW);
    digitalWrite(INB,HIGH);
    break;
    case 3:  // locked?
    digitalWrite(INA,HIGH);
    digitalWrite(INB,HIGH);
    break;
  }
}

Serial output:
Able to move: 0
Homing...
Ready

No switches are pressed nor do any indicator LEDs turn on

What I want:
Since no switches are on at start the motor driver should set the direction and give power to the motor which would be indicated by a red LED turning on. When I press the switch the LED should turn off.

What's going on?

This is my first post so let me know if you need more or less or different information.

It's very clear.
loop() says if not homed, cal homeposition().

At the end of homeposition(), you unconditionally set homed true. Game over...

I assumed the homePosition() function would first test if the limit switch isReleased() and then execute the body of the if statement. If the body of the if statement has been executed properly it would be homed. The body of the if statement is not being executed and I don't know why. Or perhaps I misunderstood your comment?

We know that homeposition() completed because back at loop() it prints "ready".
Maybe look at your wiring or make a test sketch too see extendlimit.isreleased() is working as you think.

Get in the habit of coding without using loops. Rely on the arduino loop() function to do that for you - each pass through, you only do what you need to do right now.

void loop() {
  if(I'm moving forward) {
    if(it's time to start moving backward) {
      do what I have to do to start moving backward;
    }
  }
  else {
    if(it's time to start moving forward again) {
      do what I have to do to start moving forward;
    }
  }


  do whatever I have to do to make movement happen in the current direction;
  this might be nothing, or it might involve working out stepper timings.
}

Simplified my code to this:

Serial.println("Homing...");
  pinMode(13, LOW);
  if(extendLimit.isReleased()) {
    for(int i = 0;i < 255;i++) {
      analogWrite(13, i);
      delay(10); 
    }
  }

It only worked after I pressed the switch.

Changed to this:

Serial.println("Homing...");
  pinMode(13, LOW);
  if(digitalRead(38) == LOW) {
    for(int i = 0;i < 255;i++) {
      analogWrite(13, i);
      delay(10); 
    }
  }

It works as intended without having to press the switch to get it started.

I was only intending to have a loop in the homePosition function. The rest would be controlled by the difference in time using millis(). I only want the homePosition function to run once at the beginning of the program. I don't know where the motor will be when it starts. I could change the code to run through without a while loop and when it gets to the limit switch I can change the homed variable to true that way. What's the advantage?

Endeavoring to program without loops will help prevent you getting stuck when your condition doesn't let you come out of the loop.

Of course looping to iterate through an array or similar is necessary.

Duly noted. And with that in mind I changed my code a bit. Used for loops on pin 13 as indicators but those will be gone in production.

The point of using the button library was so I didn't have to write my own debounce function. I don't seem to need it in this code. The only thing I'm questioning is why I have to hold the limit switch for 2 mississippi's in order for my homePosition function to read it as HIGH. After I home the actuator I will continue to contract and extend it and if it continues to extend for 2 seconds while my program reads the limit switch position it will break.

Revised code:

boolean extendLimitReached = false;
boolean timerSet = false;


void loop() {
  if(!homed) {
    homePosition();
  } else if(homed && !ableToMove) {
    Serial.println("Ready");
    Serial.print("Homed = ");
    Serial.println(homed);
    ableToMove = true;
  }
  
}

void homePosition() {
  Serial.println("Homing...");
  digitalWrite(13, LOW);
  if(!extendLimitReached) {
    if(digitalRead(38) == LOW) {
      for(int i = 0;i < 255;i++) {
        analogWrite(13, i);
        delay(10); 
      }
    } else if(digitalRead(38) == HIGH) {
      Serial.println("Extend limit reached");
      extendLimitReached = true;
    }
  } else if(extendLimitReached) {
    if(!timerSet) {
      startTime = millis();
      timerSet = true;
      Serial.println("Timer set");
    }
    if(millis() - startTime < 250) {
      Serial.println("Contracting...");
      for(int i = 0;i < 3;i++) {
        digitalWrite(13, HIGH);
        delay(250);
        digitalWrite(13, LOW);
        delay(250);
      }
    } else {
      homed = true;
    }
  }

Sigh. The delay is probably caused buy those for loops, huh? Right after being told to avoid them...

While you're not extended, you're running a for loop WITH A DELAY:

  if(!extendLimitReached) {            // not extended yet
    if(digitalRead(38) == LOW) {       // not on the extended limit
      for(int i = 0;i < 255;i++) {     // what is this?????
        analogWrite(13, i);            // and this ??????
        delay(10);                     // AND A DELAY?? 255 times??
      }
    } else if(digitalRead(38) == HIGH) {   // now EXTENDED
      Serial.println("Extend limit reached");
      extendLimitReached = true;              // see - we're now extended
    }
  }

You really need to work on this - I'm really unsure of your intent.

That's a totally legit point. I was using pin 13's LED to give visual confirmation that I was reaching the correct points in my code. I realize the loop and delay is causing problems so I replaced it with actual code (setting direction and pwm). Code runs smoother and switch is immediately read. I'm using a different button library now btw.

Code:

void homePosition() {
  byte extendLimitState = extendLimit.checkButton(extendLimitPin);
  if(!extendLimitReached) {
    if(!extendLimitState) {  //digitalRead(38) == LOW)  if equals 0, not pressed or held or w/e
      Serial.println("Extend limit not reached");
      setDir(1);
      analogWrite(PWM, 250);
    } else if(extendLimitState) {  //digitalRead(38) == HIGH)  if not 0, its pressed or held or w/e
      Serial.println("Extend limit reached");
      setDir(0);
      analogWrite(PWM, 0);  // should I set pwm before setting direction?
      extendLimitReached = true;
    }
  } else if(extendLimitReached) {
    if(!timerSet) {
      startTime = millis();
      timerSet = true;
      Serial.println("Timer set");
    }
    if(millis() - startTime < 500) {
      Serial.println("Contracting...");
      setDir(2);
      analogWrite(PWM, 250);  // do I need to set direction every time?
    } else {
      setDir(0);
      analogWrite(PWM, 0);
      homed = true;
    }
  }
}

Problem now is that the inidcator LED does not turn on when extending but does turn on when contracting. extendLimitState is equal to 0 at start and the serial output reads "Extend limit not reached."

Turned out to be a hardware issue. Everything seems to be working fine now. I appreciate the help.