3 steppers with 3 rotary encoders, 1 Mega, 1 noob

Greetings,
I just dove into the world of Arduino a few days ago. I ordered a couple of kits that included an Uno and Mega along with a sack full of accessories.
I am not a programmer so I can't speak the language right now.

I am a ham radio operator and enjoy building stuff for my hobby. I saw a video using a stepper and an Arduino and came up with an idea of a remotely controlled antenna tuner where I would turn the rotary encoder which would turn the stepper and ultimately turn 3 separate knobs on an antenna tuner that I would locate at the base of my antenna tower. I had looked at playing with Ardurinos some time ago but never got around to it until now.

I am using my Mega for this project along with 3 NEMA 17 steppers, 3 rotary encoders and 3 easy driver boards.

I have successfully connected 1 stepper setup thanks to the guys at Brainy bits following this tutorial:

My next step is to connect a 2nd stepper. This is where I am needing help.

In the process of trying to figure it all out, I learned about the attachInterrupt assignment. So, I assigned Pin 20 for the 2nd encoder which you can see in the following code.

I have also defined the easy driver connections for the 2nd driver board.

Am I going in the right direction with this? If so, other than pin definitions for the driver board and rotary controller and the attachInterrupt for the 2nd encoder, I do not know where to go from here. Everything I try does not work. About the best I get is the 2nd stepper only moves one direction.

Thanks for the help.
Kevin

// EasyDriver connections
#define step_pin 9  // Pin 9 connected to Steps pin on EasyDriver
#define dir_pin 8   // Pin 8 connected to Direction pin
#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

// EasyDriver2 connections
#define step_pin2 43  // Pin 43 connected to Steps pin on EasyDriver2
#define dir_pin2 45   // Pin 45 connected to Direction pin
#define MS1_2 41       // Pin 41 connected to MS1 pin
#define MS2_2 39      // Pin 39 connected to MS2 pin
#define SLEEP2 37     // Pin 37 connected to SLEEP pin
                   
volatile boolean TurnDetected;  // need volatile for Interrupts
volatile boolean rotationdirection;  // CW or CCW rotation

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

// Rotary Encoder2 Module connections
const int PinCLK2=20;   // Generating interrupts using CLK signal
const int PinDT2=33;    // Reading DT signal
const int PinSW2=31;    // Reading Push Button switch

int StepperPosition=0;    // To store Stepper Motor Position
int StepsToTake=4;      // Controls the speed of the Stepper per Rotary click

int direction;   // Variable to set Rotation (CW-CCW) of stepper


// Interrupt routine runs if CLK goes from HIGH to LOW
void rotarydetect ()  {
delay(4);  // delay for Debouncing
if (digitalRead(PinCLK))
rotationdirection= digitalRead(PinDT);
else
rotationdirection= !digitalRead(PinDT);
TurnDetected = true;
}


void setup ()  {

  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 Pin to Input
 pinMode(PinDT,INPUT);  
 pinMode(PinSW,INPUT);
 digitalWrite(PinSW, HIGH); // Pull-Up resistor for switch
 attachInterrupt (2,rotarydetect,FALLING); // interrupt 2 always connected to pin 21 on Arduino UNO
 attachInterrupt (3,rotarydetect,FALLING); // interrupt 3 always connected to pin 20 on Arduino UNO
}


void loop ()  {

 if (!(digitalRead(PinSW))) {   // check if button is pressed
 if (StepperPosition == 0) {  // check if button was already pressed
 } else {
     if (StepperPosition > 0) {  // Stepper was moved CW
       while (StepperPosition != 0){  //  Do until Motor position is back to ZERO
         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;
       }
     }
     else {
       while (StepperPosition != 0){ 
         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;
       }
     }
     StepperPosition=0; // Reset position to ZERO after moving motor back
   }
 }

// 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;
       }
 }
}

Please edit your post, select the code, and put it between [code] ... [/code] tags.

You can do that by hitting the "Code" icon above the posting area. It is the first icon, with the symbol: </>

How to use this forum

Done! Thank you.
Kevin

There are 2 problem here I believe

attachInterrupt (2,rotarydetect,FALLING); // interrupt 2 always connected to pin 21 on Arduino UNO
 attachInterrupt (3,rotarydetect,FALLING); // interrupt 3 always connected to pin 20 on Arduino UNO

An Uno does not have interrupts 2 or 3 or pins 20 or 21.

I don't know if interrupt 2 on a Mega is on pin 21 or whether interrupt 3 is on pin 20

Using the style attachInterrupt(digitalPinToInterrupt(pin), ISR, mode); would be safer.

The second problem is that you are trying to link two different interrupts to the same ISR function. Each interrupt needs its own ISR - for example rotaryDetect1 and rotaryDetect2

The way you have it the first line of code is replaced by the second line as there is only one ISR function. It is the same as this

myValue = 10;
myValue = 23;

...R

Thanks Robin. I am using the Mega 2560 which has several more interrupt pins available over the UNO.
I made the changes you recommended. I have not done any loop code for the 2nd stepper yet. What I would like to do is get the 2nd rotary encoder properly installed.

In my final build I want to have 3 steppers controlled by 3 rotary encoders independendly of each other. I figure that if I can get the 2nd stepper added successfully that it will be simple to add the 3rd one.

As of right now, the 2nd encoder works just like the 1st encoder which moves the 1st stepper both directions. But, I do not want the 2nd encoder to move the 1st stepper - it needs to only move the 2nd stepper.

I need some help on getting setup so that the only encoder that moves the stepper is the 1st encoder.
I also will need assistance on how to code the loop so that the 2nd stepper moves properly. I do not know what the best solution will be for coding the loop.

The attached code shows the changes I made and where I currently am with the build.

Thanks for helping the noob :slight_smile:

Kevin

// EasyDriver connections
#define step_pin 9  // Pin 9 connected to Steps pin on EasyDriver
#define dir_pin 8   // Pin 8 connected to Direction pin
#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

// EasyDriver2 connections
#define step_pin2 43  // Pin 43 connected to Steps pin on EasyDriver2
#define dir_pin2 45   // Pin 45 connected to Direction pin
#define MS1_2 41       // Pin 41 connected to MS1 pin
#define MS2_2 39      // Pin 39 connected to MS2 pin
#define SLEEP2 37     // Pin 37 connected to SLEEP pin
                    
volatile boolean TurnDetected;  // need volatile for Interrupts
volatile boolean rotationdirection;  // CW or CCW rotation
 
// Rotary Encoder Module connections
const int PinCLK=21;   // Generating interrupts using CLK signal
const int PinDT=4;    // Reading DT signal
const int PinSW=5;    // Reading Push Button switch
// Rotary Encoder2 Module connections
const int PinCLK2=20;   // Generating interrupts using CLK signal
const int PinDT2=33;    // Reading DT signal
const int PinSW2=31;    // Reading Push Button switch
 
int StepperPosition=0;    // To store Stepper Motor Position
int StepsToTake=4;      // Controls the speed of the Stepper per Rotary click
 
int direction;   // Variable to set Rotation (CW-CCW) of stepper
 
 
// Interrupt routine runs if CLK goes from HIGH to LOW
void rotarydetect ()  {
delay(4);  // delay for Debouncing
if (digitalRead(PinCLK))
rotationdirection= digitalRead(PinDT);
else
rotationdirection= !digitalRead(PinDT);
TurnDetected = true;
}
void rotarydetect2 ()  {
delay(4);  // delay for Debouncing
if (digitalRead(PinCLK2))
rotationdirection= digitalRead(PinDT2);
else
rotationdirection= !digitalRead(PinDT2);
TurnDetected = true;
}
 
 
void setup ()  {
 
   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
   //2nd stepper
   pinMode(MS1_2, OUTPUT);
   pinMode(MS2_2, OUTPUT);
   pinMode(dir_pin2, OUTPUT);
   pinMode(step_pin2, OUTPUT);
   pinMode(SLEEP2, OUTPUT);   
   digitalWrite(SLEEP2, 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
   
   //2nd stepper driver
   digitalWrite(MS1_2, LOW);      // Configures to Full Steps
   digitalWrite(MS2_2, LOW);    // Configures to Full Steps
   
  pinMode(PinCLK,INPUT);  // Set Pin to Input
  pinMode(PinDT,INPUT);  
  pinMode(PinSW,INPUT);
  digitalWrite(PinSW, HIGH); // Pull-Up resistor for switch
  
  //for 2nd stepper rotary control
  pinMode(PinCLK2,INPUT);  // Set Pin to Input
  pinMode(PinDT2,INPUT);  
  pinMode(PinSW2,INPUT);
  digitalWrite(PinSW2, HIGH); // Pull-Up resistor for switch
  
  attachInterrupt (digitalPinToInterrupt(21),rotarydetect,FALLING); // interrupt 2 always connected to pin 21 on Arduino MEGA
  attachInterrupt (digitalPinToInterrupt(20),rotarydetect2,FALLING); // interrupt 3 always connected to pin 20 on Arduino MEGA
}
 
 //All the following code is the original code for just 1 stepper motor. 
 
void loop ()  {
 
  if (!(digitalRead(PinSW))) {   // check if button is pressed
  if (StepperPosition == 0) {  // check if button was already pressed
  } else {
      if (StepperPosition > 0) {  // Stepper was moved CW
        while (StepperPosition != 0){  //  Do until Motor position is back to ZERO
          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;
        }
      }
      else {
        while (StepperPosition != 0){ 
          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;
        }
      }
      StepperPosition=0; // Reset position to ZERO after moving motor back
    }
  }
 
// 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;
        }
  }
}
[code]

I get the impression that you are not carefully studying your own code. If you want to control two different motors how can you expect to do so when the code in the two ISRs affects the same variables. You need different variables for each motor.

Also, the very last thing you want in an ISR is a delay(). An ISR should finish as quickly as possible. 100 microseconds for the whole thing would be very long.

What are the pins pinCLK and pinDT connected to? If the pinCLK has already triggered the ISR why do you need to read it again in the ISR?

Your code would be easier for you (and us) to follow if it was
attachInterrupt (digitalPinToInterrupt(pinCLK),rotarydetect,FALLING);

...R

Thanks, Robin.

I have corrected the attachInterrupt and removed the ISR delay for rotary detect and rotarydetect2.
I don't know how to go about adding the 2nd stepper in the loop part of the code.
Right now both encoders move the 1st stepper. I only need one encoder to control one stepper.

Thanks for your suggestions so far. I have learned a lot from it. Just looking for further direction if possible.

Kevin

// EasyDriver connections
#define step_pin 9  // Pin 9 connected to Steps pin on EasyDriver
#define dir_pin 8   // Pin 8 connected to Direction pin
#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

// EasyDriver2 connections
#define step_pin2 43  // Pin 43 connected to Steps pin on EasyDriver2
#define dir_pin2 45   // Pin 45 connected to Direction pin
#define MS1_2 41       // Pin 41 connected to MS1 pin
#define MS2_2 39      // Pin 39 connected to MS2 pin
#define SLEEP2 37     // Pin 37 connected to SLEEP pin
                    
volatile boolean TurnDetected;  // need volatile for Interrupts
volatile boolean rotationdirection;  // CW or CCW rotation
 
// Rotary Encoder Module connections
const int PinCLK=21;   // Generating interrupts using CLK signal
const int PinDT=4;    // Reading DT signal
const int PinSW=5;    // Reading Push Button switch
// Rotary Encoder2 Module connections
const int PinCLK2=20;   // Generating interrupts using CLK signal
const int PinDT2=33;    // Reading DT signal
const int PinSW2=31;    // Reading Push Button switch
 
int StepperPosition=0;    // To store Stepper Motor Position
int StepsToTake=4;      // Controls the speed of the Stepper per Rotary click
 
int direction;   // Variable to set Rotation (CW-CCW) of stepper
 
 
// Interrupt routine runs if CLK goes from HIGH to LOW
void rotarydetect ()  {
if (digitalRead(PinCLK))
rotationdirection= digitalRead(PinDT);
else
rotationdirection= !digitalRead(PinDT);
TurnDetected = true;
}
void rotarydetect2 ()  {
if (digitalRead(PinCLK2))
rotationdirection= digitalRead(PinDT2);
else
rotationdirection= !digitalRead(PinDT2);
TurnDetected = true;
}
 
 
void setup ()  {
 
   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
   Serial.begin(9600);
 /* 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 Pin to Input
  pinMode(PinDT,INPUT);  
  pinMode(PinSW,INPUT);
  digitalWrite(PinSW, HIGH); // Pull-Up resistor for switch
  
 attachInterrupt (digitalPinToInterrupt(PinCLK),rotarydetect,FALLING); // interrupt 2 always connected to pin 21 on Arduino MEGA
 attachInterrupt (digitalPinToInterrupt(PinCLK2),rotarydetect2,FALLING); // interrupt 3 always connected to pin 20 on Arduino MEGA
 
 }
 
 //All the following code is the original code for just 1 stepper motor. I am not sure what to attempt here for the 2nd stepper.
 
void loop ()  {
 
  if (!(digitalRead(PinSW))) {   // check if button is pressed
  if (StepperPosition == 0) {  // check if button was already pressed
  } else {
      if (StepperPosition > 0) {  // Stepper was moved CW
        while (StepperPosition != 0){  //  Do until Motor position is back to ZERO
          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;
        }
      }
      else {
        while (StepperPosition != 0){ 
          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;
        }
      }
      StepperPosition=0; // Reset position to ZERO after moving motor back
    }
  }
 
// 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;
        }
  }
}

Have a look at this

attachInterrupt (digitalPinToInterrupt(PinCLK),rotarydetect,FALLING);

and then this

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

Your ISR is triggered by a falling signal therefore the value when you read PinCLK can only be LOW. Why are you bothering to read it? Why are you bothering with an IF

Now think about this other ISR as well

void rotarydetect2 ()  {
   if (digitalRead(PinCLK2))
      rotationdirection= digitalRead(PinDT2);
   else
      rotationdirection= !digitalRead(PinDT2);
   TurnDetected = true;
}

This is a completely different piece of code based on what is happening on two different pins. So why are you updating the same variables as in the other ISR?

As I suggested earlier, you need to read through your code very very carefully and think about precisely what each item in it does.

As far as I can see all you need in the ISR is this

void rotarydetect ()  {
  rotationdirection= !digitalRead(PinDT);
  TurnDetected = true;
}

...R