I'm using an **Arduino Mega 2560** to control a **DRV8871** motor driver connected to a **DC brushed motor**. The setup includes: 

- **Three buttons**: UP, DOWN, and FAST 
- **One limit switch input**, where the upper and lower limit switches are connected in series 
- **PWM speed control** using slow decay, as explained in [this TI forum post](https://e2e.ti.com/support/motor-drivers-group/motor-drivers/f/motor-drivers-forum/715789/drv8871-q1-how-to-pwm-the-driver) 

### Goals: 
1. **Speed control**: Run the motor at ~30% speed when UP or DOWN is pressed, and ~70% when UP or DOWN is pressed along with FAST. 
2. **Acceleration**: Implement a configurable acceleration curve. 
3. **Non-blocking code**: Ensure the program does not use `delay()` or block execution. 

### Issue: 
I wrote the following code: [GitHub link](https://github.com/luigi-pi/headMotor.git). However, when pressing UP or DOWN, the motor makes noise but doesn't move (possibly stalling, even with `PWM = 100`). 

Interestingly, if I bypass PWM control and use: 
```cpp
digitalWrite(in1Head, HIGH);
analogWrite(in2Head, LOW);
```
the motor runs correctly. 

### Questions: 
1. Could this issue be due to **incorrect PWM control**? 
2. Is the **motor stalling** due to insufficient startup current? 
3. Any suggestions for debugging or improving the code? 

Any insights would be greatly appreciated!
###update:
 I've updated the code trying to follow suggestions. Please let me know if I understood correctly. 
 1. I put a while loop on the limitswitch. I want that when limitswitch is hit the motor stops, then reverse the direction and disengage the limitswitch moving for the `disengage_ls` time.

```cpp
//Head motor
int in1Head = 44; //on ARDUINO MEGA 
int in2Head = 45;
int limSwHead = 19; //2 normally close limit switches connected in series
int FAST = 16; //push button
int UP = 17; //push button
int DOWN = 15; //push button
volatile bool limSwHeadTriggered = false;
// Direction enum and flag
enum Direction { FORWARD, BACKWARD };
Direction currentDirection = FORWARD; // Initialize with default direction
uint8_t PWM_fast =70; //value in % of motor speed
uint8_t PWM_slow =30; //value in % of motor speed
uint8_t PWM = 20; //min value of PWM (to be changed also below)
unsigned long zero = 0;
uint16_t accel_interval = 10;//time in millis to change the speed in acceleration
uint8_t speedIncrease = 5; //% of speed increase for each accel_interval
uint16_t disengage_ls = 500; //time in millis to disangage Limitswitch when hit

boolean fastState = false;
boolean upState = false;
boolean downState = false;

//----FUNCTIONS----------------------------------------------------------------------------------------
//INTERRUPTS
void headISR() {
 limSwHeadTriggered = true;
}
void HeadForward(uint8_t PWM) { 
 analogWrite(in1Head, 255);
 analogWrite(in2Head,(255 * (100 - PWM)) / 100); //inverse of the PWM in range 0-255
 currentDirection = FORWARD; // Set direction flag
}
void HeadBackward(uint8_t PWM) {
 analogWrite(in1Head,(255 * (100 - PWM))/ 100); //inverse of the PWM in range 0-255
 analogWrite(in2Head, 255);
 currentDirection = BACKWARD; // Set direction flag 
}
void HeadStop() {
 analogWrite(in1Head,255);
 analogWrite(in2Head, 255);
 PWM=20; 
}

void HeadCoast() {
 analogWrite(in1Head,0);
 analogWrite(in2Head, 0);
 PWM=20; 
}
void limSwHit() {
 HeadStop();
 if(currentDirection == FORWARD){
 HeadBackward(PWM_slow);
 }
 else if (currentDirection == BACKWARD){
 HeadForward(PWM_slow);
 }
}
void setup() {
 Serial.begin(9600);
 //head motor
 pinMode(in1Head, OUTPUT);
 pinMode(in2Head, OUTPUT);
 //limitswitch
 pinMode(limSwHead, INPUT_PULLUP);
 attachInterrupt(digitalPinToInterrupt(limSwHead), headISR, RISING); // Trigger on HIGH signal
 //Buttons
 pinMode(FAST,INPUT_PULLUP);
 pinMode(UP,INPUT_PULLUP);
 pinMode(DOWN,INPUT_PULLUP);
}
void loop() {
if(limSwHeadTriggered){
 unsigned long initialMillis = millis();
 while(millis()- initialMillis<= disengage_ls){
 limSwHit();
 }
 HeadCoast()
 limSwHeadTriggered=digitalRead(limSwHead);
}
// read the state of the pushbutton value, inverted due to pullup resistors:
 upState = !digitalRead(UP);
 downState = !digitalRead(DOWN);
 fastState = !digitalRead(FAST);

 if (upState && !downState && (millis()- zero >= accel_interval)){
 if (PWM < (fastState ? PWM_fast : PWM_slow)) {
 PWM += speedIncrease;
 }
 HeadForward(PWM);
 Serial.println("moving up");
 zero = millis();
 } 
 else if(!upState && downState && (millis()- zero >= accel_interval)) {
 if (PWM < (fastState ? PWM_fast : PWM_slow)) {
 PWM += speedIncrease;
 }
 HeadBackward(PWM);
 Serial.println("moving down:");
 zero = millis();
 }
 
 else{
 HeadCoast();
 }
}
```