Receiving user input while running stepper motor

Ok, just to clarify I have read the "doing multiple things at once" sticky at the begging of this forum and i understood how it worked but I don't know if it will work for my project. Here is an overview of my project. I have three parts to my program (I'm not on my project computer so I can't post my code) User input function --> input transformation function --> stepper motor function. So basically a user will input a number (on a basic 4x4 key pad), another function will transform that input into a number and stepper will move x number of steps based on that output. So the problem comes in when the stepper is moving x steps. I want the user to be able to change the input variable at any time, but while the stepper motor is doing its thing, wouldn't that prevent any new input? I feel that in the steppers steping loop I could probably have a check to verify if the user input has changed( if inputOld == inputNew then continue), but in doing that I don't think the program will be ready to receive the input so the user input would never change while in the process of stepping. So should I try running two threads(some other forms said this wasn't really efficient on arduino)? will the "do multiple things at once" type of process work just fine? or is there some other better way to keep the program ready to receive to input at all times while still performing the other functions?

"do multiple things at once" is the way it is done.

You step the motor when it is time to step, otherwise move on.

You ask if a key has been pressed, and if not, move on. Else process that key.

"Process that key" will include a step that decides if a complete parameter input has been accepted, in which case motor speed, etc. might be updated.

Disclaimer - I've never used a stepper motor...

I believe the stepper library uses interrupts, so if I understand it correctly you can send it a command (to take a certain number of steps, etc.) and you can go back to reading inputs (or doing other things) while the motor continues to run.

There are [u]examples[/u] where a pot is used to adjust the speed or position, so that should give you an idea of how to read in input and make the motor react while it's running.

You could also single-step the motor and do things between steps. That would involve using millis() or micros() to do more than one thing at a time.

DVDdoug:
I believe the stepper library uses interrupts

No it does not. The supplied library BLOCKS if you do more than one step.

So flow needs top be along the lines

unsigned long StepTimer ; // count millis between each step (or micros)
long StepperCount ;  // the actual position of the Stepper
unsigned int StepInterval = 50 ; // interval between steps => inverse of "speed of stepper"

  : // code in loop
if ( millis() - StepTimer > StepInterval ) {
 StepTimer=millis() ; MyStepper.step(1) ;
    if ( ClockWise ) StepperCount++ ; else StepperCount-- ;
  }
  : // more code in loop

Back to the original question, yes that is entirly dooable, no trouble at all. I would prefer to do my code, but some people perfer using “timer” or “schduler” libraries. It usually takes as much effort to use these as learning how to do it your self, in relativly few lines of code.

Your loop() should do very little

void loop() {
  KeypadDecode() ; // Updates the "Number" variable with last entry
  MoveStepper() ; // Steps the stepper so that its position approaches the current value of "Number"
}

The next challenge is that these functions MUST NOT BLOCK, and that they KEEP STATE. The first means that they get a few miliseconds of time to decide if they need to do anything (like writing to some pins) by reading a few pins, or perhaps look at some variables that the other functions have modified (aka. Global variables) and then they return. In particular it means that using delay() is forbidden - it takes many milliseconds to execute (whatever number you ask it to)

So KeyPadDecode remembers all the buttons pushed, it does contact debounce by using a timer, not delay(), and it accumulates the actual number in a varable. It gets called - say - 5000 times a second.

Here is how it should work: when being called the first 2300 times it notes that nothing has happend on the keypad. On the 2301st time it ses one of the keypad pins has changed state (it stores the state of all keypad pins). Ignoring contact debounce for a while, it notes the new pin state, knows that pin means the digit “5” has been pressed, so it multiplies the so-far-accumulated number by 10 and then adds the 5 and exits. It has probably only run for 0.01 millisecond when the button was pushed, and 0.009 when not pushed.

Then another few thousand iteration until the pin goes low, this is noted in the saved state of pins, but otherwise nothing happens. And later … the Enter Key is seen pressed, this causes the number-accumulated to be passed to the Global variable Number.

The outcome of Keypressed is that number only changes that one moment the Enter key is pushed, even though it is called repeatdly afterwards, too.

The MoveStepper needs to do the timer thing (see previous post). If the time to do a step has not yet come, it simply returns. If the time has come then do the step. A step involves comparing the Stepper position value with number (updated by the Keypad routine). If greater do a left step if less to a right step - and by implication - if neither, no step. Always reset the timer, so we will examine the next step.

The stepper routine is called 5000 times a second too. Most of the time, the step-timer value is too low, so nothing happens. When it does, it only does one step (the stepper library sets the motor pins appropiatly) and only so that it brings the stepper closer to the number. It probably executes 0.002 milliseconds on the “too soon to step” case and 0.01ms on a step.

You see the loop thing shoud run very fast, with all the functions only doing something when neded, and NEVER waiting.

Of course, you start of with the bare minimal code above that works, then you end up adding frills like end stops, being able to enter speed, too.

Good programming means that before the loop() where you declare variles you only need to declare the Stepper and the “number”. Inside the functions you use the static attribute. THat means the variable keep their value after the exit until they are called again.

int Number ; // Keypad communicates position to Stepper ;

loop() {  as shown above }

void KeypadDecode() {
 static int partialNumber ;
 static int pinState[16] ;
 :
  partialNumber = partialNumber*10 + digitValue ;
 :
 Number = partialNumber ; // Enter was pressed, new number for the stepper to aim for !
 :
}

void MoveStepper() {
  static unsigned long stepInterval ;
  static long stepperPosition ;
  :
  if ( stepperPosition > Number ) {
    MyStepper.step(+1) ; 
    stepperPosition++ ;
  }
  if ( stepperPosition < Number ) {
    MyStepper.step(-1) ; 
    stepperPosition-- ;
  }
  :
}

The point being that if you (accidentally) use a name like “count” in both functions, they are differnet variable local to the function only.

This will work, that if you enter a number whatevere the stepper was trying to do, it will stop doing that and start following the new number.

Many or most of the libraries provided are "blocking" and cannot be used for real-time applications.

The "do multiple things at once" is a guide to the general process of real-time operation; you have to include all of your functions in that form. There is nothing about "Arduino" that limits the efficiency of doing this but you have to write the "threads" as non-blocking steps in your main "loop". You cannot use "while" and you cannot use "for" loops or the like.

The critical question for this application is the time interval between steps. Is that comfortably long enough for the Arduino to check for a key press?

If it is then the concept in Several Things at a Time can be used to make both things happen in parallel. It may be necessary to use micros() rather than millis(), but the process is identical.

If the interval between steps is NOT big enough (which is unlikely) then you will have to choose between running the motor or reading the keypad.

You should be aware that the AccelStepper library can control a stepper without blocking.

...R

Thanks everyone for the advice! This really helps a lot!

There are also non-blocking stepper libraries available. I believe that AccelStepper is one of these, although I haven't used it myself (yet).

OldSteve:
I believe that AccelStepper is one of these [non-blocking]

Faith is good for things that are hard/impossible to know. In this case knowledge is possible and better :slight_smile: : It's own documentation says it is non blocking.

Exmining the code & documentation, it is non blocking, but it relies on the same principle I described : You have a loop() where you call the AccelStepper Step function real often, and all the other functions you use in in your loop() code must not block either. If you do, like use delay(1000) in some other part of your code, the stepper will stop for one second, too.

Msquare:
Faith is good for things that are hard/impossible to know. In this case knowledge is possible and better :slight_smile: : It's own documentation says it is non blocking.

What's the problem here? I was in a hurry and didn't have time to go searching for the documentation and reading up on a library that I don't intend to use.
I thought I had read that AccelStepper was non-blocking, and felt that I should mention that fact since no one else had. I also thought that since it claimed to be non-blocking, it might have been timer-based. Get off your high-horse.

OldSteve:
I thought I had read that AccelStepper was non-blocking, and felt that I should mention that fact since no one else had.

I have no problem with people providing suggestions for an OP to explore.

However it was already mentioned in Reply #6

...R

Robin2:
I have no problem with people providing suggestions for an OP to explore.

However it was already mentioned in Reply #6

...R

Sorry Robin, I missed that.