Button press detection during other functions.

Hi guys,

I’m building a barn door tracker for astrophotography. Basically just a platform that moves to follow the movement of the stars.

Using a small stepper (28 BYJ-48 stepper) to drive a curved rod.

My goal is the following:

Button 1: Start the stepper
Button 2: Stop the stepper
Button 3: Rewind the stepper

I would also like a limit switch detection for the forward and reverse stepper functions.

I have attached my current coding which is only to drive the stepper forwards. (I know how to make it reverse also).

But how do I get it to detect the stop button whilst running in forward/reverse? I know using delays causes issues with how the button press is detected.

I’m thinking of using If statements to detect button press, and then do required action. But if the stepper is already running how can I check for the stop button press?

Can anyone tell me if I’m on the right track or throw me some ideas on how to attack this? I would like to try and work this out myself but if some of you can throw me some pointers or example code, it will be much appreciated.

/*-----( Import needed libraries )-----*/
#include <Stepper.h>

/*-----( Declare Constants, Pin Numbers )-----*/
//---( Number of steps per revolution of INTERNAL motor in 4-step mode )---
#define STEPS_PER_MOTOR_REVOLUTION 32   

//---( Steps per OUTPUT SHAFT of gear reduction )---
#define STEPS_PER_OUTPUT_REVOLUTION 32 * 64  //2048  
 

/*-----( Declare objects )-----*/
// create an instance of the stepper class, specifying
// the number of steps of the motor and the pins it's
// attached to

//The pin connections need to be 4 pins connected
// to Motor Driver In1, In2, In3, In4  and then the pins entered
// here in the sequence 1-3-2-4 for proper sequencing
Stepper small_stepper(STEPS_PER_MOTOR_REVOLUTION, 8, 10, 9, 11);

/*-----( Declare Variables )-----*/
int  Steps2Take;

void setup()   /*----( SETUP: RUNS ONCE )----*/
{
// Nothing  (Stepper Library sets pins as outputs)
}/*--(end setup )---*/

void loop()   /*----( LOOP: RUNS CONSTANTLY )----*/
{
  Steps2Take  = STEPS_PER_OUTPUT_REVOLUTION ;  // Rotate CW 1 turn
  small_stepper.setSpeed(624);   
  small_stepper.step(Steps2Take);
  
  

}/* --(end main loop )-- */

/* ( THE END ) */

You need to use the AccelStepper library and its non-blocking stepper.run() function.

That allows the program to check the state of the buttons even while the motor is moving.

If you want a responsive program do NOT use the delay() function. If you need to manage timing use millis() as illustrated in Several Things at a Time

...R

AccelStepper in combination with your motor, see the wiki here:
https://arduino-info.wikispaces.com/SmallSteppers

But how do I get it to detect the stop button whilst running in forward/reverse?

Move 1 step, check the input, repeat until the input changes state.

jasp05:
Hi guys,
I have attached my current coding which is only to drive the stepper forwards.

Your code seems to be an endless looping of blocking function calls " small_stepper.step(Steps2Take);"

The function seems to do "busy waiting" while doing one revolution of the stepper until finished.
As soon as it is finished with one revolution, it will start another one and block the rest of the code.

For a "cooperative multitasking" you would have to do a completely different (non-blocking) programming logic, instead of calling the same lame "busy waiting" functions all the time again and again and again, blocking all other action, like detecting button presses.

Wrong non-cooperative programming logic has brought your program to a dead end where no extended function tasks can be put in between.

I'm afraid you will have to create a completely different program for what you want.

Perhaps a "finite state machine" (FSM") with three operating states (CLOCKWISE,ANTICLOCKWISE and STOP), which can be changed from one state to the other using pressed button(s).

To get started, take the blink without delay code from the examples and adapt it a bit. Declare a RemainingSteps variable and set it to the number of steps you want to take.

Replace the code that handles the led with stepper.step(1) and decrement remaining steps. Then at the top of loop you can check for the stop button & if you detect it, set RemainingSteps zero.

That'll get you running with non-blocking code at least.

Is there somewhere I can read up on the AccelStepper library functions and how they work? I've really only dabbled in arduino coding and have no other programming experience, so still learning.

I get the "Non-blocking" thing, (I didn't know my code was blocking) but for future reference how would I know if it was blocking or non-blocking code? I'm assuming there is some other background knowledge to understand what is and isn't blocking code, especially when it comes to functions in libraries.

And how would I structure the code for the button detection? Would using the state change detection example code work? and then execute the stepper functions in the if statements?

and given the state change detection example is written with only one input, I can add additional buttons into this code?

This is how I'm thinking it will go. I'm just quick drafting this out in my head, so some small bits like the button state for previous and current are left out.

const int buttonPin1
const int buttonPin2
const int buttonPin3

int buttonPushCounter1 
int buttonPushCounter2 
int buttonPushCounter3 




void loop(){

buttonState1 = digitalRead(buttonPin1);
buttonState2 = digitalRead(buttonPin2);
buttonState3 = digitalRead(buttonPin3);

if(buttonstate1 != lastButtonState1){

 if (buttonState1==HIGH) {
     
     buttonPushCounter1++;
     (Insert stepper function here, using the accelstepper library)

} else if (buttonState2 != lastButtonState2){

if (buttonState2 == HIGH) {

buttonPushCounter2++;
     (Insert stepper function here)

Ill end it here as I think you get where I'm going with this. If this is wrong or if I may of produced some other problems by doing it this way let me know.

jasp05:
Is there somewhere I can read up on the AccelStepper library functions and how they work

The AccelStepper website has good documentation and several examples for you to experiment with.

...R

jasp05:
Is there somewhere I can read up on the AccelStepper library functions and how they work?

Is it "open source"?

If yes, then you can READ THE SOURCE CODE!

Sometimes it contains comments containing further information than the source code itself is telling.

jurs:
If yes, then you can READ THE SOURCE CODE!

That advice is only useful for a person who already knows enough programming to make sense of the source code. Unfortunately, for many libraries it is the only source of information. However the AccelStepper library has good documentation.

...R

so after reviewing the accelstepper documentation ive got the non blocking code to run what i need.

#include <AccelStepper.h>
AccelStepper stepper; // Defaults to AccelStepper::FULL4WIRE (4 pins) on 2, 3, 4, 5
void setup()
{  
   stepper.setMaxSpeed(1000);
   stepper.setSpeed(50);        
}
void loop()
{  
   stepper.runSpeed();
}

however can i just now plug this into the state change detection example as mentioned in my previous post?

i didn’t find anything on the accelstepper site with reference to state change or input detection other than a potentiometer to control stepper location/speed.

i didn't find anything on the accelstepper site with reference to state change

The StateChangeDetection example principle will work if you read the input in loop() as long as the code you posted is non blocking.

jasp05:
however can i just now plug this into the state change detection example as mentioned in my previous post?

What happens when you try that?

The Arduino system is great for learning-by-doing

...R

Thanks UKHeliBob. I'm more than happy to learn by doing but it seems a bit redundant to try it if its not going to work.

As mentioned previously, I'm very new to programming, and wasting time on a project that isn't going to work is not going to teach alot at all. Especially when you don't know why it's not working..

But I do appreciate the help that's been given. :slight_smile:

jasp05:
and wasting time on a project that isn't going to work is not going to teach alot at all. Especially when you don't know why it's not working..

I suspect you will learn a great deal more than you would learn if the program worked and did not need any further investigation :slight_smile:

...R

Especially when you don't know why it's not working.

Try it. If it doesn't work then post your code here and describe what should happen and what does happen. You will, I am sure, get plenty of help and explanations of the problem.

In addition, as Robin says, you will learn something even if it is how not to do something.

jasp05:
As mentioned previously, I'm very new to programming, and wasting time on a project that isn't going to work is not going to teach alot at all. Especially when you don't know why it's not working..

So you are new with programming, but what about your knowledge of circuit design?

Which of those circuits do you prefer for your dhree buttons?

I have made some kind of "ASCII art circuit schematic"

1. buttton circuit with pull-down resistor:
                   
                    _______
GND----------------|_______|-----------------+--------------- o/o--------  +5V
|                    4K7                     |               Switch
|                                            |
|                                            |
|                                            |
|                                            |
|                                            |
|                                            |
|                                            |
|                                            |
                                         INPUT(Arduino)


c



2. buttton circuit with pull-up resistor:
                   
                    _______
+5V----------------|_______|-----------------+--------------- o/o-------  GND
|                    4K7                     |               Switch
|                                            |
|                                            |
|                                            |
|                                            |
|                                            |
|                                            |
|                                            |
|                                            |
                                         INPUT(Arduino)



3. non-working button circuit without any external resistor (DO NOT USE THIS AS IT DOESN'T WORK!):

                  
                           
                                             +--------------- o/o--------  +5V
|                                            |               Switch
|                                            |
|                                            |
|                                            |
|                                            |
|                                            |
|                                            |
|                                            |
|                                            |
                                         INPUT(Arduino)

4. working button circuit without any external resistor (INPUT_PULLUP must be activated in software):

                  
                           
                                             +--------------- o/o--------  GND
|                                            |               Switch
|                                            |
|                                            |
|                                            |
|                                            |
|                                            |
|                                            |
|                                            |
|                                            |
                                         INPUT_PULLUP(Arduino)

Which of those circuits do you prefer? And DO NOT tell us , that you like circuit 3. as the best for your buttons! :wink:

Im using the pulldown circuit for my momentary switch Jurs. using 10k resistor between arduino input and ground. +5v to other side of the switch.

I’ve replaced the old code with the basic constant speed example from the accelstepper library. (as i only ever need a constant speed). I’ve also gone with the switch example from Arduino for my button detection.

Now these 2 pieces of code work independently of each other. However when I try to combine them, neither the stepper or the button detection work. (I’ve got an led setup to show the detection).

It compiles fine. Can anyone point out something I am missing??

only thing I can think of is the placement of my code to run the steppers. (as when i put them in I need to insert more {} to get the code to compile. Not sure what effect they are having on the code to be honest.)

If I remove the lines of stepper.runspeed() and stepper.stop along with the associated { } the code compiles and button detection works.

can anyone throw some ideas as to where I should place the stepper functions? Is there a way I can attach the stepper functions to the “State” like the outpin (LED) is?

int inPin = 8;         // the number of the input pin
int outPin = 7;       // the number of the output pin

int state = LOW;      // the current state of the output pin
int reading;           // the current reading from the input pin
int previous = LOW;    // the previous reading from the input pin

// the follow variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.

long time = 0;         // the last time the output pin was toggled
long debounce = 200;   // the debounce time, increase if the output flickers

#include <AccelStepper.h>

AccelStepper stepper; // Defaults to AccelStepper::FULL4WIRE (4 pins) on 2, 3, 4, 5


void setup()
{
  pinMode(inPin, INPUT);
  pinMode(outPin, OUTPUT);
  stepper.setMaxSpeed(1000);
  stepper.setSpeed(50);
}

void loop()
{
  reading = digitalRead(inPin);

  // if the input just went from LOW and HIGH and we've waited long enough
  // to ignore any noise on the circuit, toggle the output pin and remember
  // the time
  if (reading == HIGH && previous == LOW && millis() - time > debounce) {
    if (state == LOW)
      state = HIGH;   
      stepper.runSpeed();
      
  }  else {
      state = LOW;
      stepper.stop();
     
           
    time = millis(); 
    }
    digitalWrite(outPin, state);
    previous = reading; 
}