Help with User Input Inside of While loop

Hi,

I am new to arduino and C++.
I am using an Arduino Mega 2560 with a LCD shield, which can be found at the link below.

I am looking to power two stepper motors with the arduino while allowing user input through the LCD Shield.
I have created a menu which the user can cycle through, but my specific questions lies when using the stepper motors.

I would like to have the ability to pause the stepper motors during use if the user desires.

In the code below, I have a set up where I ask the arduino to look at analogread to get some values. Basically my question is about how does this function work. So, currently I think the arduino only looks for a value when it passes over this line of code. I was wondering if this meant that it does not see any input unless I press it at the exact time, and if it does work like this is there anyway to get around it?

More explanation of the code is below.

while ((check1  > MIN) && (pauseval < 1)) // while the time is less than the required time to finish run code
        {
         // int keyEvent = detectKey(); // sets value if key is pressed
          int     curKeyEvent  = 0;
          int     adc_key_in   = 0;

            adc_key_in=analogRead(0);

            curKeyEvent = get_key(adc_key_in);      // convert into key press
          // int key = curKeyEvent;
          if (curKeyEvent > 0)
        {
             int key = curKeyEvent; 
             lcd.setCursor(4,1);
             lcd.print(key);  
        }
            lcd.setCursor(0,1);
            lcd.print(curKeyEvent);
                     
            lcd.setCursor(8,1);
            digitalClockDisplay();
          
          MIN=mins(); // continues to update MIN until it reaches check
                // step one step: 
                 
                  MIN=mins(); // continues to update MIN until it reaches check
                  myStepper.step(0); // needed to call step before first time or motor did not move
                  myStepper.setSpeed(60); // sets speed of motor
                  myStepper.step(-100);
                  myStepper.setSpeed(60);
                  delay(50);
                  myStepper.step(100);
                  myStepper.setSpeed(60);
              
                  delay(5000); // this will be equal to timeperiod/2
                  MIN=mins(); // continues to update MIN until it reaches check
                  myStepper2.step(0);
                  myStepper2.setSpeed(60);
                  myStepper2.step(100);
                  myStepper2.setSpeed(60);
                  delay(50);
                  
                  myStepper2.step(-100);
                  myStepper2.setSpeed(60);
                  delay(5000); // this will be equal to timeperiod/2
                  
                  
        }
       
        
        
       lcd.setCursor(0,0);
       lcd.print(" Job Complete   "); // tells the user the Job is complete

This is the specific portion of my code because the entire thing is just over 1000 lines, and I do not think anyone wants to read through the entire thing but to explain this portion:

The while loops runs while MIN is less than check. Check is hard coded to be 1, but eventually it can be changed by the user. MIN is a value that changes based on a timer already set out in the code, which means while the code is running it is also counting time so when MIN gets to 1 minute the while loop exits. This portion of the code works fine.

The other condition of the while loop is what I would like to add as of now it does not really do anything, but basically I want it to work such that when I press a button on the LCD the pauseval changes to 1 and thus the while loop will be exited.

          if (curKeyEvent > 0)
        {
             int key = curKeyEvent; 
             lcd.setCursor(4,1);
             lcd.print(key);  
        }

Why not just print curKeyEvent? Creating a local variable that goes out of scope as soon as it is printed is a waste.

          MIN=mins(); // continues to update MIN until it reaches check
                // step one step: 
                 
                  MIN=mins(); // continues to update MIN until it reaches check

If the assignment didn't work once, what makes you think it will work the second time? Maybe you need 4 or 5 of these statements before one actually sticks. Not.

The other condition of the while loop is what I would like to add as of now it does not really do anything, but basically I want it to work such that when I press a button on the LCD the pauseval changes to 1 and thus the while loop will be exited.

What part of reading a switch state and assigning a value to pauseval are you having problems with?

Why not just print curKeyEvent? Creating a local variable that goes out of scope as soon as it is printed is a waste.

I was hoping to create key which would hold the value. curKeyEvent constantly got updated by that I mean. at default curKeyEvent is -1 when a button is not pressed. I wanted to isolate events when curKeyEvent would be >0 this would signal a button press. Then, I would use that value to signal an update in pauseval to exit the loop.

If the assignment didn't work once, what makes you think it will work the second time? Maybe you need 4 or 5 of these statements before one actually sticks. Not.

I actually stated earlier that this portion of the code does work. Basically, it updates the value of min. As the code is running I have delays and such such that seconds pass, which means MIN=mins() at the beginning of the loop will not necessarily be the same value of MIN=mins() at the middle of the loop; however, if the while loop only checks its conditions at the end of the loop then technically I only need one MIN=mins() at the end of the loop because all of the others are useless. I just havent focused on determining this because its an easy problem to fix while the pause button is not...

What part of reading a switch state and assigning a value to pauseval are you having problems with?

The problem is that the switch needs to come from user input, and currently, user input is either only taken when analogread is called or user input is constantly being overrun by the no button pressed state. I would like the pauseval to be updated if a button is pressed. The current problem is finding a way to isolate that button press because right now I can repeatedly press buttons but unless I hold the button down for the entire duration of the while loop which i currently set to 12 seconds the device does not recognize that there was a button press.

Thanks for responding especially since its a holiday!

I was hoping to create key which would hold the value.

By declaring a variable that immediately goes out of scope? I don't see how that will work. Perhaps you need to read up on scope.

which means MIN=mins() at the beginning of the loop will not necessarily be the same value of MIN=mins() at the middle of the loop;

Those two statements have nothing between them but a comment that gets stripped out by the compiler. mins() will return the same value on both calls.

The current problem is finding a way to isolate that button press because right now I can repeatedly press buttons but unless I hold the button down for the entire duration of the while loop which i currently set to 12 seconds the device does not recognize that there was a button press.

Might I respectfully suggest, then, that Ctrl-A, Ctrl-X is what is needed, and that you start over. That the while loop takes 12 seconds is no reason not to read the switch 10,000,000 times in those 12 seconds.

Read, understand, and embrace the blink without delay example. There is no reason to use delay() anywhere in your code.

By declaring a variable that immediately goes out of scope? I don't see how that will work. Perhaps you need to read up on scope.

I will read up on scope as I said I first began look at C++ 2 weeks ago lol

Those two statements have nothing between them but a comment that gets stripped out by the compiler. mins() will return the same value on both calls.

This is true and 2nd one is deleted but again calling something one more time is a waste of code lol but in the grand scheme of the device working it does not matter...

Might I respectfully suggest, then, that Ctrl-A, Ctrl-X is what is needed, and that you start over. That the while loop takes 12 seconds is no reason not to read the switch 10,000,000 times in those 12 seconds.

Read, understand, and embrace the blink without delay example. There is no reason to use delay() anywhere in your code.

I said that I wanted to make this device turn 2 stepper motors, but those stepper motors need to do a job. That job is moving to pawls on a ratchet gear. They need to turn periodically. This period is determined by delays. If there is another way to create periods between stepper motor movements I could look into it, but I believe the delays are very useful and eventually the time of the delay will be varied based on the user input.

Also, what I hear you saying is that when I call analogread it continuously updates 0.0001 seconds after it is called initially?

Thanks again for the feedback

This period is determined by delays. If there is another way to create periods between stepper motor movements I could look into it, but I believe the delays are very useful and eventually the time of the delay will be varied based on the user input.

If your job was to move the stepper motors to new positions once a week, instead of once a second, how would YOU do it? Would you sit and stare at a clock the whole interval? That's what delay() does. Or, would you write down the last time you moved the stepper, and periodically see if it was time to move it again? That is the approach that blink without delay illustrates.

Periodically, for the Arduino is several million times per second, if delay() is not used (and no other blocking function is used). millis() is the watch, and variables replace the pen and paper.

Using millis() and a lastTimeSomethingHappened variable is not a direct replacement for delay(), but the methodology does let you do other things, like look at switches, etc. while also stepping the stepper motors.

The step() function of the Stepper library is a blocking function. You might want to look at the AccelStepper library, instead. With that library, calling the moveTo() methods gets the stepper moving, and the function returns right away. Periodically, you check to see if the stepper is done (while also reading switches, updating LCDs, etc.).

Ohhh ok thank you!

I had a feeling something was a blocking function I accidentally assumed it was the while loop and never checked the other calls I was doing in StepperMotor...

I will investigate using millis and a lasttimesomething happened because that should work for what I would like along with the moveTo call.

Thanks again for the advice!