Set IN and OUT Stepper travel points using tact switches

//Set IN and OUT Stepper travel points using tact switches
TUTORIAL


Set IN and OUT Stepper motor travel points using tact switches

OVERVIEW

Welcome to the final part of this tutorial on how to use a Rotary Encoder to control a stepper motor.

To conclude this tutorial, we will add some switches to set IN and OUT points and then we will be able to make the motor move to those positions.

In the code we will see how to detect long press and short press of the switches to enable us to use the switches to do two things.

We will also add a buzzer to confirm the settings of the IN and OUT points.

CONNECTIONS

The IN switch is connected to A0

OUT switch is connected to A1

The 2 switches are both connected to GND

The Buzzer is connected to A2 and GND

We are using 5 pins to connect to the Easy Driver and 3 pins for the rotary encoder module.

Pin 8 is connected to DIR
Pin 9 to STEPS
Pin 10 to MS1
Pin 11 to MS2
and Pin 12 to SLEEP

The Voltage and GND of the Easy Driver are connected to a 12V 1A power supply.
The NEMA 17 motor we are using has a max amperage draw of around 0.45A.

The 4 leads of the NEMA stepper (2 per coils), are connected directly to the Easy Driver A and B.

A quick way to identify which wires are part of the same coil is to connect two wires together and if you feel resistance when trying to turn the stepper motor shaft, that means that those 2 wires are part of the same coil.

Pin 2(CLK), 3(DT) and 4(SW) are receiving information from the rotary encoder.

The encoder is also connected to 3.3V and Ground of the UNO.

DIN of the WS2812 RGB stick is connected to Pin 5 and Voltage and Ground is connected to the 5V and GND of the UNO.

We also connect the UNO Ground to the Easy Driver to serve as a reference.

THE CODE

To detect a long press or short press of the switches we will use the MILLIS function to detect the amount of time we hold down the switch.

A long press will SET the IN or OUT point and a short press will make the motor move to those points.

Also since we will use an Active Buzzer, all we need to do to make a sound when we set an IN or OUT point is to apply power to the buzzer for a short period of time to make a sound.

We invite you to watch all the tutorials in this series to get explanation on all the code that we are using.

And as always for more information about the tutorial and explanation of the code please watch our tutorial video.

/*Start of Code */

#include "FastLED.h" // FastLED library

// EasyDriver connections
#define dir_pin 8 // Pin 8 connected to Direction pin
#define step_pin 9 // Pin 9 connected to Steps pin on EasyDriver
#define MS1 10 // Pin 10 connected to MS1 pin
#define MS2 11 // Pin 11 connected to MS2 pin
#define SLEEP 12 // Pin 12 connected to SLEEP pin

// WS2812 RGB Stick connection
#define led_pin 5 // Pin 5 connected to DIN of RGB Stick

// IN and OUT switches connections
#define SWITCH_PIN_IN A0 // Pin A0 connected to IN point switch
#define SWITCH_PIN_OUT A1 // Pin A1 connected to OUT point switch

// Rotary Encoder Module connections
const int PinCLK=2; // Generating interrupts using CLK signal
const int PinSW=4; // Reading Push Button switch
const int PinDT=6; // Reading DT signal

#define NUM_LEDS 8 // # of WS2812 LEDs on stick
CRGB leds[NUM_LEDS]; // FastLED Library Init

// Buzzer connections
#define BUZZ_PIN A2 // Pin A2 connected to + of Buzzer

volatile boolean TurnDetected; // to detect rotation of Rotary Encoder
volatile boolean rotationdirection; // CW or CCW rotation
volatile boolean rswitch=0; // Variable to store rotary encoder switch state
volatile boolean led_speed_change; // to detect change of speed
volatile int StepsToTake=2; // Controls the speed of the Stepper per Rotary click

int direction; // Variable to set Rotation (CW-CCW) of stepper
int StepperPosition=0; // To store Stepper Motor Position
int IN_Position=0; // To store IN point Position
int OUT_Position=0; // To store OUT point Position

int time; // to detect long switch press duration

// Interrupt routine runs if CLK goes from HIGH to LOW
void rotarydetect () {
delay(10); // delay for Debouncing Rotary Encoder

if (rswitch == 1) {
if (digitalRead(PinCLK)) {
if (digitalRead(PinDT)) {
if (StepsToTake > 2){
StepsToTake=StepsToTake-1; }}
if (!digitalRead(PinDT)) {
if (StepsToTake < 9){
StepsToTake=StepsToTake+1; }}
led_speed_change = true;
}
}

else {
if (digitalRead(PinCLK))
rotationdirection= digitalRead(PinDT);
else
rotationdirection= !digitalRead(PinDT);
TurnDetected = true;
}
}

void setup () {

pinMode(BUZZ_PIN, OUTPUT);
digitalWrite(BUZZ_PIN,LOW);
pinMode(SWITCH_PIN_IN, INPUT);
pinMode(SWITCH_PIN_OUT, INPUT);
digitalWrite(SWITCH_PIN_IN,HIGH);
digitalWrite(SWITCH_PIN_OUT,HIGH);

FastLED.addLeds<NEOPIXEL,led_pin>(leds, NUM_LEDS); // Setup FastLED Library
FastLED.clear();

// Light up starting LED's
for(int x = 0; x != (StepsToTake - 1); x++) {
if (x < 2) leds[x] = CRGB::Red;
if (x > 1 & x < 5) leds[x] = CRGB::Orange;
if (x > 4) leds[x] = CRGB::Green;
}

FastLED.setBrightness(50);
FastLED.show();

pinMode(MS1, OUTPUT);
pinMode(MS2, OUTPUT);
pinMode(dir_pin, OUTPUT);
pinMode(step_pin, OUTPUT);
pinMode(SLEEP, OUTPUT); 
digitalWrite(SLEEP, HIGH); // Wake up EasyDriver
delay(5); // Wait for EasyDriver wake up

/* Configure type of Steps on EasyDriver:
// MS1 MS2
//
// LOW LOW = Full Step //
// HIGH LOW = Half Step //
// LOW HIGH = A quarter of Step //
// HIGH HIGH = An eighth of Step //
*/ 
digitalWrite(MS1, LOW); // Configures to Full Steps
digitalWrite(MS2, LOW); // Configures to Full Steps

pinMode(PinCLK,INPUT); // Set Pins to Input
pinMode(PinDT,INPUT); 
pinMode(PinSW,INPUT);
digitalWrite(PinSW,INPUT_PULLUP); // use internal resistor of UNO for Rotary Encoder switch
attachInterrupt (0,rotarydetect,FALLING); // interrupt 0 always connected to pin 2 on Arduino UNO
}


void loop () {

if (digitalRead(SWITCH_PIN_IN) == LOW) // Do if IN switch is pressed
{
time = millis();
delay(500); //debounce

// check if the switch is pressed for longer than 1 second.
if(digitalRead(SWITCH_PIN_IN) == LOW && time - millis() >5000) 
{
digitalWrite(BUZZ_PIN,HIGH);
delay(100);
digitalWrite(BUZZ_PIN,LOW);
IN_Position=StepperPosition;
while (StepperPosition > IN_Position){ // Do until Motor position is back to IN point
digitalWrite(dir_pin, HIGH); // (HIGH = anti-clockwise / LOW = clockwise)
for (int x = 1; x < StepsToTake; x++) {
digitalWrite(step_pin, HIGH);
delay(1);
digitalWrite(step_pin, LOW);
delay(1); 
}
StepperPosition=StepperPosition-StepsToTake;
delay(100-(StepsToTake*11));
}
}
else {
while (StepperPosition < IN_Position){ 
digitalWrite(dir_pin, LOW); // (HIGH = anti-clockwise / LOW = clockwise)
for (int x = 1; x < StepsToTake; x++) { 
digitalWrite(step_pin, HIGH); 
delay(1); 
digitalWrite(step_pin, LOW); 
delay(1); 
} 
StepperPosition=StepperPosition+StepsToTake; 
delay(100-(StepsToTake*11)); 
} 
} 
} 

if (digitalRead(SWITCH_PIN_OUT) == LOW) // Do if OUT switch is pressed { time = millis(); delay(500); //debounce // check if the switch is pressed for longer than 1 second. if(digitalRead(SWITCH_PIN_OUT) == LOW && time - millis() >5000) 
{
digitalWrite(BUZZ_PIN,HIGH);
delay(100);
digitalWrite(BUZZ_PIN,LOW);
OUT_Position=StepperPosition;
while (StepperPosition > OUT_Position){ // Do until Motor position is back to OUT point
digitalWrite(dir_pin, HIGH); // (HIGH = anti-clockwise / LOW = clockwise)
for (int x = 1; x < StepsToTake; x++) {
digitalWrite(step_pin, HIGH);
delay(1);
digitalWrite(step_pin, LOW);
delay(1); 
}
StepperPosition=StepperPosition-StepsToTake;
delay(100-(StepsToTake*11));
}
}
else {
while (StepperPosition < OUT_Position){ 
digitalWrite(dir_pin, LOW); // (HIGH = anti-clockwise / LOW = clockwise)
for (int x = 1; x < StepsToTake; x++) {
digitalWrite(step_pin, HIGH);
delay(1);
digitalWrite(step_pin, LOW);
delay(1); 
}
StepperPosition=StepperPosition+StepsToTake;
delay(100-(StepsToTake*11));
}
}

if (!(digitalRead(PinSW))) { // Do if Rotary Encoder switch is pressed
delay(250); // debounce switch
if (rswitch == 0) {
rswitch = 1; }
else {
rswitch = 0;
}
}

// Runs if Rotary Encoder switch is pressed
if (led_speed_change) {
led_speed_change = false; // do Not repeat IF loop until new rotation detected

// Which LED's to light up
FastLED.clear();
for(int x = 0; x != (StepsToTake - 1); x++) {
if (x < 2) leds[x] = CRGB::Red;
if (x > 1 & x < 5) leds[x] = CRGB::Orange;
if (x > 4) leds[x] = CRGB::Green; 
}
FastLED.setBrightness(50);
FastLED.show();
}

// Runs if rotation was detected
if (TurnDetected) {
TurnDetected = false; // do NOT repeat IF loop until new rotation detected

// Which direction to move Stepper motor
if (rotationdirection) { // Move motor CCW
digitalWrite(dir_pin, HIGH); // (HIGH = anti-clockwise / LOW = clockwise)
for (int x = 1; x < StepsToTake; x++) {
digitalWrite(step_pin, HIGH);
delay(1);
digitalWrite(step_pin, LOW);
delay(1); 
}
StepperPosition=StepperPosition-StepsToTake;
}

if (!rotationdirection) { // Move motor CW
digitalWrite(dir_pin, LOW); // (HIGH = anti-clockwise / LOW = clockwise)
for (int x = 1; x < StepsToTake; x++) {
digitalWrite(step_pin, HIGH);
delay(1);
digitalWrite(step_pin, LOW); 
delay(1); 
}
StepperPosition=StepperPosition+StepsToTake;
}
}
}

/* End of Code */
TUTORIAL VIDEO
DOWNLOAD

Just copy the above Sketch code you want to use above in your Arduino IDE software to program your Arduino.

Used libraries:

You can download the FastLED library here

Once downloaded, just extract the content of the zip files inside your “arduino/libraries” folder.

By | 2018-02-23T17:11:14+00:00 September 30th, 2015|Tutorials|

8 Comments

  1. jose luiz September 3, 2018 at 7:55 am - Reply

    Hello Brainy I loved this project and all of its publications.
    could you help me with a step motor circuit.
      I need to record the position of the step motor using a tick button and another to read. using a potentiometer. preferably with the driver l298 because I already have varios .. once again parabens for the projects and thank you very much

  2. john March 29, 2018 at 7:55 pm - Reply

    Hi Brainy Bits – Has anyone checked this code out? I have attempted twice now over the course of year to get it to work and nothing. Previous- Video 3 or V3 of the code(without the in outs) work with the same wiring setup on my bread board and the Stepper works as it should. But on this versions code, I am getting a Stepper Jam, 1 step forward, 1 step backwards. is all i get when rotating the encoder. I have swapped stepper etc. to test and the problem seems to be in the code. I have also noticed that the codes layout in the Video is different from what you have here on this page.Haven’t seen any successful builds any where of this so just wondering if this has been discovered yet?

  3. Kendall February 21, 2018 at 8:21 pm - Reply

    Hi,

    I’m trying to read and understand all the basics and I think I figured about 20 plus pins but I’m reading all types of ideas, like the LEDs “charlieplexing”?
    anyway I figured I needed to get a professional opinion. I’m planning to buy a kit plus anything else I may need for my specific needs to get started with.
    I think my biggest challenge will be with the eyepieces code (the 2nd set of 4 buttons.LEDs for the eyepieces) but if I can just make sure the MEGA is where I need to be, I think is a good start.

    Thanks for your time, I will also take a look at the link you provided to get more familiar with.

    Cheers,

    Kendall

    • brainy-bits February 21, 2018 at 8:29 pm - Reply

      No, problem! I would go with the MEGA for your project. When I had a telescope I did something similar for the focus knob, but it was just so I didn’t touch the telescope, it didn’t have positions memory like you want to do, good luck with your project, it’s a pretty cool idea! Btw if you’re having trouble with the code, I do offer coding services if you need help here: https://brainy-bits.com/custom-work/

      • Kendall February 22, 2018 at 7:55 am - Reply

        Thanks Ivan, I’m very excited about this project!

        I will start shopping for a MEGA. I saw that you offer coding and fab services, May need your help with coding down the road for sure! but I still what to learn as I go for other projects.

        But for the hardware, I will get the MAGA, stepper with driver, 8 pushbuttons OR can I set it up with 4 user buttons and (1) 4 position rotary switch for the eyepieces? 4LEDs for the users & 4 LEDs for the eyepieces to show which user/eyepiece is in play. OR some form of display that shows the eg; user #1 & eyepiece EYEPIECE=42MM, EYEPIECE=17MM, etc (I would always use those eyepieces in that order.)
        I’m asking because I want to make sure I’m on the right track with a good project foundation as I may get you involved with coding later on.

        Clear Skies,

        Kendall

      • Kendall March 20, 2018 at 5:57 pm - Reply

        Hi Ivan,

        I’m slowly learning and working on my project! :0P I’ve learned a little with the blinking LED and such to get familiar with the board.

        I’m using the MEGA 2560 and all parts you used in your project herein except the easy driver. Im using the ULN2003 driver and no LED strip. I made changes to your code to remove the LEDs and not 100% on my code for the 2003 driver. I think I want the stepper speed to be one speed only which would be fast. However, im getting an error at the “if digitalread sw pin in” when I verify!
        Can you please take a look and see if im on track?

        Best regards,

        Kendall
        Below is the code thus far:

        /*Start of Code */

        // Driver connections
        #define dir_pin 8 // Pin 8 connected to Direction pin
        #define step_pin 9 // Pin 9 connected to Steps pin on Driver
        #define MS1 10 // Pin 10 connected to MS1 pin
        #define MS2 11 // Pin 11 connected to MS2 pin
        #define SLEEP 12 // Pin 12 connected to SLEEP pin

        // IN and OUT switches connections
        #define SWITCH_PIN_IN A0 // Pin A0 connected to IN point switch
        #define SWITCH_PIN_OUT A1 // Pin A1 connected to OUT point switch

        // Rotary Encoder Module connections
        const int PinCLK=2; // Generating interrupts using CLK signal
        const int PinSW=4; // Reading Push Button switch
        const int PinDT=6; // Reading DT signal

        // Buzzer connections
        #define BUZZ_PIN A2 // Pin A2 connected to + of Buzzer

        volatile boolean TurnDetected; // to detect rotation of Rotary Encoder
        volatile boolean rotationdirection; // CW or CCW rotation

        int direction; // Variable to set Rotation (CW-CCW) of stepper
        int StepperPosition=0; // To store Stepper Motor Position
        int IN_Position=0; // To store IN point Position
        int OUT_Position=0; // To store OUT point Position

        int time; // to detect long switch press duration

        // Interrupt routine runs if CLK goes from HIGH to LOW
        void rotarydetect () {
        delay(10); // delay for Debouncing Rotary Encoder

        if (digitalRead(PinCLK)) {
        if (digitalRead(PinDT)) {

        if (!digitalRead(PinDT)) {

        }
        }

        else {
        if (digitalRead(PinCLK))
        rotationdirection= digitalRead(PinDT);
        else
        rotationdirection= !digitalRead(PinDT);
        TurnDetected = true;
        }
        }

        pinMode(BUZZ_PIN, OUTPUT);
        digitalWrite(BUZZ_PIN,LOW);
        pinMode(SWITCH_PIN_IN, INPUT);
        pinMode(SWITCH_PIN_OUT, INPUT);
        digitalWrite(SWITCH_PIN_IN,HIGH);
        digitalWrite(SWITCH_PIN_OUT,HIGH);

        pinMode(MS1, OUTPUT);
        pinMode(MS2, OUTPUT);
        pinMode(dir_pin, OUTPUT);
        pinMode(step_pin, OUTPUT);
        pinMode(SLEEP, OUTPUT);
        digitalWrite(SLEEP, HIGH); // Wake up EasyDriver
        delay(5); // Wait for EasyDriver wake up

        /* Configure type of Steps on EasyDriver:
        // MS1 MS2
        //
        // HIGH HIGH = An eighth of Step //
        */
        digitalWrite(MS1, LOW); // Configures to Full Steps
        digitalWrite(MS2, LOW); // Configures to Full Steps

        pinMode(PinCLK,INPUT); // Set Pins to Input
        pinMode(PinDT,INPUT);
        pinMode(PinSW,INPUT);
        digitalWrite(PinSW,INPUT_PULLUP); // use internal resistor of UNO for Rotary Encoder switch
        attachInterrupt (0,rotarydetect,FALLING); // interrupt 0 always connected to pin 2 on Arduino UNO
        }

        if (digitalRead(SWITCH_PIN_IN) == LOW) // Do if IN switch is pressed getting error: “expected unqualified-ID BEFORE IF”
        {
        time = millis();
        delay(500); //debounce

        // check if the switch is pressed for longer than 1 second.
        if(digitalRead(SWITCH_PIN_IN) == LOW && time – millis() >5000)
        {
        digitalWrite(BUZZ_PIN,HIGH);
        delay(100);
        digitalWrite(BUZZ_PIN,LOW);
        IN_Position=StepperPosition;
        while (StepperPosition > IN_Position){ // Do until Motor position is back to IN point
        digitalWrite(dir_pin, HIGH); // (HIGH = anti-clockwise / LOW = clockwise)
        for (int x = 1; x < StepsToTake; x++) {
        digitalWrite(step_pin, HIGH);
        delay(1);
        digitalWrite(step_pin, LOW);
        delay(1);
        }
        StepperPosition=StepperPosition-StepsToTake;
        delay(100-(StepsToTake*11));
        }
        }
        else {
        while (StepperPosition < IN_Position){
        digitalWrite(dir_pin, LOW); // (HIGH = anti-clockwise / LOW = clockwise)
        for (int x = 1; x 5000)
        {
        digitalWrite(BUZZ_PIN,HIGH);
        delay(100);
        digitalWrite(BUZZ_PIN,LOW);
        OUT_Position=StepperPosition;
        while (StepperPosition > OUT_Position){ // Do until Motor position is back to OUT point
        digitalWrite(dir_pin, HIGH); // (HIGH = anti-clockwise / LOW = clockwise)
        for (int x = 1; x < StepsToTake; x++) {
        digitalWrite(step_pin, HIGH);
        delay(1);
        digitalWrite(step_pin, LOW);
        delay(1);
        }
        StepperPosition=StepperPosition-StepsToTake;
        delay(100-(StepsToTake*11));
        }
        }
        else {
        while (StepperPosition < OUT_Position){
        digitalWrite(dir_pin, LOW); // (HIGH = anti-clockwise / LOW = clockwise)
        for (int x = 1; x < StepsToTake; x++) {
        digitalWrite(step_pin, HIGH);
        delay(1);
        digitalWrite(step_pin, LOW);
        delay(1);
        }
        StepperPosition=StepperPosition+StepsToTake;
        delay(100-(StepsToTake*11));
        }
        }

        // Runs if rotation was detected
        if (TurnDetected) {
        TurnDetected = false; // do NOT repeat IF loop until new rotation detected

        // Which direction to move Stepper motor
        if (rotationdirection) { // Move motor CCW
        digitalWrite(dir_pin, HIGH); // (HIGH = anti-clockwise / LOW = clockwise)
        for (int x = 1; x < StepsToTake; x++) {
        digitalWrite(step_pin, HIGH);
        delay(1);
        digitalWrite(step_pin, LOW);
        delay(1);
        }
        StepperPosition=StepperPosition-StepsToTake;
        }

        if (!rotationdirection) { // Move motor CW
        digitalWrite(dir_pin, LOW); // (HIGH = anti-clockwise / LOW = clockwise)
        for (int x = 1; x < StepsToTake; x++) {
        digitalWrite(step_pin, HIGH);
        delay(1);
        digitalWrite(step_pin, LOW);
        delay(1);
        }
        StepperPosition=StepperPosition+StepsToTake;
        }
        }
        }

        /* End of Code */

  4. Kendall February 20, 2018 at 3:54 pm - Reply

    Ivan,

    1st of all I would like to thank you for all of you wonderful tutorials here! I’m trying to get into this hobby. I do have a electronics back ground and want to learn Arundio coding to create some cool projects like yourself. I sent a couple messages you may have received or not received regarding my stepper driven telescope focuser. this circuit is almost what I need to get started. but Im no sure if I need the MEAGA or UNO. below is a brief overview.

    Im working on a telescope focuser driven by a stepper motor like the video link herein.
    I would like to have a self contained box (a hand box to hold when viewing to e scope) that has 4 buttons to represent 1 to 4 users and each user can set the position using the encoder knob and set the focuser/stepper to his or her eyesight. so when the telescope is on any object, the user presses there number button and the focuser is set to there eyesight without touching the scope.
    *an LED or something would be good to show which button number is in play.

    Above is based on using one eyepiece power but I normally used up to 4 different eyepieces for different magnifications, which requires refocus between each.

    I attached a rudimentary diagram of what I think would be the connectivity, or at least show my method of madness!
    in the attached schematic, I put in a 4 position switch to select the different eyepieces being used.

    So the way this would work.

    example: 2 users and 4 eyepieces being used, power up the scope, track on 1st object and insert eyepiece A into the focuser, looking at the object in the eyepiece I would activate the user #1 button and rotate the encoder knob to focus to my eye, press the/a button and Im set.
    The next user would press the #2 button and do the same, so when we are going back and forth looking at objects, we just press the #1 or #2 button to have out independent focus.
    Next we remove the eyepiece A and insert eyepiece B and have to refocus our user buttons for that eyepiece.
    Once the all the 4 eyepieces are setup then you can just select the eyepiece being used from the rotary switch and press the user # button and view.

    Again, im just making sure this could be a feasible project and if so, to figure out what major components I will need, example using the UNO or will I need the MEGA?
    There are a wide variety of modular components available like the 4 button keypad, the driver/stepper and a good amount of the code needed.

    If think you have a better solution, questions or concerns, PLEASE let me know.

    All the best,
    Kendall

    • brainy-bits February 21, 2018 at 1:35 pm - Reply

      Hi, if you start with figuring out the number of pins needed:

      – 4 Digital pins for the user select switches
      – 3 Digital pins for the Rotary Encoder (2 for rotation, 1 for the integrated switch)
      – 2 Digital pins for the Easy Driver board to drive the stepper
      – 4 Digital pins for the LED’s

      So that’s already 13 pins, and if you wanted to use a 7 segment display or another module you would exceed the native UNO pin capacity.

      Of course you could use a shift register to save some pins, like in this tutorial here: https://brainy-bits.com/get-more-inputs-on-your-arduino-by-using-a-shift-register/

      I would use a MEGA, that way you are sure to have enough pins and have many more available if you want to add capabilities in your project down the road.

      This seems like a very feasible project, the only thing you need to make sure is that before you power on the project, you set the focus knob of the telescope all the way in, kind of like homing at startup, that way the stepper knows how many steps to take to focus for a specific eyepiece and user since the focus of the telescope will always be the same when starting up.

      Hope that helps you get started!

Leave A Comment