Stopping State Machine with keypad

Hello folks I have a particular problem with one of my projects.

The idea for this project is I have a keypad (4x4) along with a motor.

The 'A' 'B' and 'D' keys are given special functions
A = Run Once
B = Run Looping
D = Stop Loop

I first started my code using a while loop to do this, but in these forums I found someone with a similar problem using statemachines

Using a state machine was supposed to help by not blocking the LOOPING function.

 if (key != NO_KEY) 
  {
    Serial.println(key);
  }
  
  switch(current_state) {
  case WAITING:
    
    break;
  case LOOP_ONCE:
  // set some parameters.  this set of code will be processed until no longer
  // LOOPING, as set by the keyPadEvent.
    stop_position = ((start_position + (setdeg*12))/2); // This value will control the degree of the movement (setdeg*(12))
    stepper.moveTo(stop_position);
    stepper.runToPosition();
    stepper.moveTo(-stop_position);
    stepper.runToPosition();
    stepper.moveTo(start_position);                         // Set motor back to star_position!
    stepper.runToPosition();
    counter = counter + 1;                              // Main counter increment valve
    Serial.println(counter);                            // Debug mode only
    lcd.setCursor(14,1);                                // Start at character 14 on line 2
    lcd.print(counter);
    delay(100); 
    current_state = WAITING;
    break;   
    
  case LOOPING:
  // set some parameters.  this set of code will be processed until no longer
  // LOOPING, as set by the keyPadEvent.
    stop_position = ((start_position + (setdeg*12))/2); // This value will control the degree of the movement (setdeg*(12))
    stepper.moveTo(stop_position);
    stepper.runToPosition();
    stepper.moveTo(-stop_position);
    stepper.runToPosition();
    counter = counter + 1;                              // Main counter increment valve
    Serial.println(counter);                            // Debug mode only
    lcd.setCursor(14,1);                                // Start at character 14 on line 2
    lcd.print(counter); 
    break;
  }

So basically when I press 'B' and go into the looping STATE, I can't consistently leave the loop by pressing 'D', I seem to catch it once and a while after repeatedly mashing the button.

What am I missing in all this?

Thank you in advanced!

How do you think you will leave state WAITING?

  case WAITING:
   
    break;

The key to a state machine not blocking is to not use any blocking code in the states. If you use delay or the functions for the stepper that don't return until they get to a given position then you have defeated that purpose. Just because you arrange the code a certain way doesn't mean that the processor is going to see your key press in the middle of the stepper function or the delay. You have to arrange the code so that it does something fast and then gets back to look for input. Take one step, look at the input, take another step, look at the input, take another step, etc etc.

Have a look at how the code is organized in Several Things at a Time so as not to block any of the other activities.

...R

Whandall I was so focused on leaving LOOPING that I didn't really finish the rest of the switch case :slight_smile:

Thank you to the others I will look over several things at once!!

You can not test a state machine without at least trying to implement all transitions and inputs.
You can cheat on the actions however. :wink:

So this is my new code and it gives me the same result as having 2 .getKey():

switch(current_state) {
  case WAITING:
     key = numpad.getKey();
    break;
  case LOOP_ONCE:
  // set some parameters.  this set of code will be processed until no longer
  // LOOPING, as set by the keyPadEvent.
    stepper.moveTo(stop_position);
    stepper.runToPosition();
    stepper.moveTo(-stop_position);
    stepper.runToPosition();
    stepper.moveTo(start_position);                         // Set motor back to star_position!
    stepper.runToPosition();
    counter = counter + 1;                              // Main counter increment valve
    current_state = WAITING;
    break;   
    
  case LOOPING:
  // set some parameters.  this set of code will be processed until no longer
  // LOOPING, as set by the keyPadEvent.
    key = numpad.getKey();
    key = numpad.getKey();
    key = numpad.getKey();
    key = numpad.getKey();
    key = numpad.getKey();
    stepper.moveTo(stop_position);
    key = numpad.getKey();key = numpad.getKey();
    stepper.runToPosition();
    key = numpad.getKey();
    key = numpad.getKey();
    stepper.moveTo(-stop_position);
    key = numpad.getKey();
    key = numpad.getKey();
    key = numpad.getKey();
    stepper.runToPosition();
    key = numpad.getKey();
    counter = counter + 1;
    key = numpad.getKey();
    key = numpad.getKey();key = numpad.getKey();key = numpad.getKey();key = numpad.getKey();
    break;
  }

common I know this would work with a physical button and not a matrix so what's the difference.

  case LOOPING:
  // set some parameters.  this set of code will be processed until no longer
  // LOOPING, as set by the keyPadEvent.
    key = numpad.getKey();
    key = numpad.getKey();
    key = numpad.getKey();
    key = numpad.getKey();
    key = numpad.getKey();

What is the point of this? How many times do you suppose getKey() will return something other than no key, in this set of calls?

I was frustrated, I read more into the library and started using the keyStateChanged() to detect the pressed button. I'll post the solution once I get it.