Rotary encoder output is delayed when connected to a motor

Hello,

I am making a circuit where a wheel spins with a rotary encoder on it and when the encoder’s value becomes a multiple of six, a motor spins. Right now, I’m testing, so I’m not using units of measurement. Anyways, when I hook up everything and test it out, everything works great except for the fact that when hitting a multiple of six, outputs from the encoder aren’t being made! To clarify, when I turn the encoder, on the serial monitor it shows how many steps I have made, but when the value hits a multiple of six, the motor goes off as planned but doesn’t get any input from the encoder, making it think the value is still at that multiple of six, even when I spin the encoder. It doesn’t detect for what seems like a random length of time each time I run the program, until finally the rotary encoder output is detected and the motor stops. Any ideas?

Thanks.

#include <Stepper.h>

Stepper stepper(100, 9, 10, 11, 12);

#define outputA 2
#define outputB 3
int counter = 0; 
int aState;
int aLastState;  
bool drop = false;
const int Radius = 5;

void setup(){
Serial.begin(9600); // Begins Serial monitor
pinMode (outputA ,INPUT);
pinMode (outputB ,INPUT);
stepper.setSpeed(100);
aLastState = digitalRead(outputA);    
}

void dropSeed(int rotations) {
  stepper.step(100);
  stepper.step(-100);
}

void loop(){
aState = digitalRead(outputA);
int distance = (2*pi*Radius)/StepsPerRotation;
if (drop == false) {
  if (aState != aLastState){     
     // If the outputB state is different to the outputA state, that means the encoder is rotating clockwise
     if (digitalRead(outputB) == 1) { 
       counter ++;
     } else {
       counter --;
     }
     Serial.print("Position: ");
     Serial.println(counter);
   } 
   drop = true;
}
if(drop == true) {
  if (counter % 6 == 0 && counter != 0) {
    dropSeed(30);
    drop = false;
    if (drop == false) {
      // nothing
    } else {
      Serial.println("dammit we got a problem");
    }
  } else {
    drop = false;
  }
  
} else {
  Serial.println("sjkhfgkjd");
}
 aLastState = aState;
}

More members will see your code if you post it in code tags.

How would I do that? Plus, don't you have anything to say about my problem?

Ah! Nevermind :slight_smile:

I don't have any explanation for the "random length of time", but your program will certainly cause the encoder to be ignored during the blocking calls to stepper.step() and delay(). While those functions are running, the rest of your code is not running so the outputA pin is not being polled. The solution is to change your code to be non-blocking. You can see a simple demonstration of that in this tutorial:

To make your stepper movements non-blocking, you will want to move one step at a time, comparing micros() to the timestamp of the last step to determine when it's time to make the next step, until the desired number of steps are reached.

Thanks, I'll try that out

This is the simplest way I know of how to use an encoder without interfering with your other code

volatile int counter = 0;  // volatile keyword is needed to keep the integer alive during interrupts.

// outputA must be pin 2 or 3 on an UNO
// in Setup add this function with the lamba Anonomous function as the function pointer for attachInterrupts
attachInterrupt(digitalPinToInterrupt(outputA),    []{digitalRead(outputB)? counter++ :counter--;},    RISING);
// How this works We know the pin outputA just changed to HIGH so we now check the outputB for High to ++ the counter or LOW to --  the counter
// the Test ? Ture : False is another way to do the if statement you had in your code
// the [] { code } is a funciton without a name (annonomous) that only providing a pointer to that nameless function which is all that attachInterrupts needs.

// int your loop:
// copy the value to another variable using noInterrupts to prevent glitches during later use
  int CounterValue;
  noInterrupts ();
  Counter = count;
  interrupts ();

See if that simplifies your code
Z

pert

How would I incorporate this? I'm having some trouble

Post your best attempt at incorporating it and a description of the problem you’re having and we’ll help you out.

#include <Stepper.h>

Stepper stepper(100, 9, 10, 11, 12);

#define outputA 2
#define outputB 3
volatile int counter = 0;
int aState;
int aLastState;  
bool drop = false;
const int Radius = 5;
int prev_time = 0;

void setup(){
Serial.begin(9600); // Begins Serial monitor
pinMode (outputA ,INPUT);
pinMode (outputB ,INPUT);
stepper.setSpeed(100);
aLastState = digitalRead(outputA);   
}

void dropSeed(int rotations, int counter) {
    if (counter % 6 >= 0 && counter != 0){
      stepper.step(rotations);
      stepper.step(-rotations);
    }
}

void loop(){
  unsigned long currentTime = millis();
  aState = digitalRead(outputA);
  if (aState != aLastState){    
     // If the outputB state is different to the outputA state, that means the encoder is rotating clockwise
     if (digitalRead(outputB) == 1) {
       counter ++;
     } else {
       counter --;
     }
     Serial.print("Position: ");
     Serial.println(counter);
   }
   
  if (counter % 6 == 0 && counter != 0) {
    if (currentTime - 1000 >= 0) {
      
    } else {
      dropSeed(100, counter);
    }
  } else {
  }

 aLastState = aState;
}

lwadde2007:

#include <Stepper.h>

Stepper stepper(100, 9, 10, 11, 12);

#define outputA 2
#define outputB 3
volatile int counter = 0;
int aState;
int aLastState;  
bool drop = false;
const int Radius = 5;
int prev_time = 0;

void setup(){
Serial.begin(9600); // Begins Serial monitor
pinMode (outputA ,INPUT);
pinMode (outputB ,INPUT);
stepper.setSpeed(100);
aLastState = digitalRead(outputA);  
}

void dropSeed(int rotations, int counter) {
   if (counter % 6 >= 0 && counter != 0){
     stepper.step(rotations);
     stepper.step(-rotations);
   }
}

void loop(){
 unsigned long currentTime = millis();
 aState = digitalRead(outputA);
 if (aState != aLastState){    
    // If the outputB state is different to the outputA state, that means the encoder is rotating clockwise
    if (digitalRead(outputB) == 1) {
      counter ++;
    } else {
      counter --;
    }
    Serial.print("Position: ");
    Serial.println(counter);
  }
 
 if (counter % 6 == 0 && counter != 0) {
   if (currentTime - 1000 >= 0) {
     
   } else {
     dropSeed(100, counter);
   }
 } else {
 }

aLastState = aState;
}

I’m not sure what your trying to do but here’s the code inserted somewhat I couldn’t test it as I don’t have your stepper library. I also removed the Lambda anonymous function and replaced it with a regular function as I see it may be too advanced.

#include <Stepper.h>

Stepper stepper(100, 9, 10, 11, 12);

#define outputA 2
#define outputB 3
volatile int counter = 0;
int aState;
int aLastState; 
bool drop = false;
const int Radius = 5;
int prev_time = 0;

void FunctionForAttachInterrupt(){
  digitalRead(outputB)? counter++ :counter--;
}

void setup(){
Serial.begin(9600); // Begins Serial monitor
pinMode (outputA ,INPUT);
pinMode (outputB ,INPUT);
stepper.setSpeed(100);
attachInterrupt(digitalPinToInterrupt(outputA),   FunctionForAttachInterrupt, RISING);

}

void dropSeed(int rotations, int counter) {
    if (counter % 6 >= 0 && counter != 0){
      stepper.step(rotations);
      stepper.step(-rotations);
    }
}

void loop(){
  unsigned long currentTime = millis();
  int CounterValue;
  noInterrupts ();
  CounterValue = count;
  interrupts ();
  
  Serial.print("Position: ");
  Serial.println(counter);

  if (counter % 6 == 0 && counter != 0) {
    if (currentTime - 1000 >= 0) {
     
    } else {
      dropSeed(100, counter);
    }
  } else {
  }
}

z

There are some problems. The stpper motor turns when getting to a multiple of six, but sometimes the counter increases by six when I turn it in the slightest. The value in which the counter increases by changes every time I turn the rotary encoder. Once, it went from 58 to 112 in one turn!

lwadde2007:
There are some problems. The stpper motor turns when getting to a multiple of six, but sometimes the counter increases by six when I turn it in the slightest. The value in which the counter increases by changes every time I turn the rotary encoder. Once, it went from 58 to 112 in one turn!

What part are you using for the encoder?
Link to a datasheet?
Sketch up a diagram of how you are connected.
Show us your code and the changes you made.
I need more information to help you if I can. Right now I’m guessing and could lead you in the wrong direction.
Z

The diagram is in my original post.
Here’s my new code:

#include <Stepper.h>

Stepper stepper(100, 9, 10, 11, 12);

#define outputA 2
#define outputB 3
volatile int counter = 0;
int aState;
int aLastState;
const long pi = 3.14159265358979;
bool drop = false;
const int Radius = 5;
int prev_time = 0;

void FunctionForAttachInterrupt(){
  digitalRead(outputB)? counter++ :counter--;
}

void setup(){
Serial.begin(9600); // Begins Serial monitor
pinMode (outputA ,INPUT);
pinMode (outputB ,INPUT);
stepper.setSpeed(100);
attachInterrupt(digitalPinToInterrupt(outputA),   FunctionForAttachInterrupt, RISING);

}

void dropSeed(int rotations) {
    stepper.step(rotations);
    stepper.step(-rotations);
}

void loop(){
  unsigned long currentTime = millis();
  int CounterValue;
  noInterrupts ();
  CounterValue = counter;
  interrupts ();
  Serial.print("Position: \n");
  Serial.print(counter);

  if (counter % 6 == 0 && counter != 0) {
      dropSeed(100);
  } else {
  }
}

This is the link to my encoder:

The type of encoder linked in the reply #14 requires pullup resistors* on the A and B lines. You can use the internal pullups.

Those encoders are nothing like the encoder shown on your (not real clear) Fritz diagram.

  • I suppose that you could use pull down resistors, but why?

I couldn't find my encoders on Fritzing.

lwadde2007:
This is the link to my encoder:
https://www.amazon.ca/Cylewet-Encoder-Digital-Potentiometer-Arduino/dp/B07G9Z5CG3/ref=sr_1_3?keywords=rotary+encoder&qid=1580065749&sr=8-3

I'm suggesting you add small capacitor to help denounce the switches.

Encoder.jpg
Z

Encoder.jpg

Where is the capacitor in that image? Also, where could I get one of those?

lwadde2007:
Where is the capacitor in that image? Also, where could I get one of those?

They as surface mount capacitors I soldered between the pins of the encoder. They are yellowish in color and they are small
https://www.amazon.com/dp/B07M631J1Q/ref=cm_sw_r_em_apa_i_k6JlEbAV5E3KG

Z