Encoder not reading While other inputs are active

i have and encoder as a limit switch to control a motor that lifts up and down. if it is at the limit i have it where i can hold the stop and the up or down button to travel past the limits and when you let off of one or both it stops. when it is within the limits the motor stays on until the limit is reached or the stop button is pressed. i am having problems with the encoder not counting when one of the other inputs are active (up, down,stop) it is an incremental encoder.

here is the code i have

#include <RotaryEncoder.h>

RotaryEncoder encoder(A4, A5);

const int encoderPin = (A4, A5);
boolean toggle = true;
int buttonPin0 = 4;
int buttonPin1 = 5;
int buttonPin2 = 6;
int mtrUp = 12;
int mtrDown = 11;
int buttonStatus1 = LOW;
int buttonStatus2 = LOW;
int buttonStatus0 = LOW;


int encoderMin = -10;  // minimum sensor value
int encoderMax = 20;   //maximum sensor value
int encoderValue = 0;
int press = 0;
int mtrdelay = 100;   //delay between motor direction change


void setup()
{
  Serial.begin(57600);
  Serial.println("ENCODER POSITION");
  pinMode(mtrUp, OUTPUT);
  digitalWrite(mtrUp, HIGH);
  pinMode(mtrDown, OUTPUT);
  digitalWrite(mtrDown, HIGH);
  pinMode(buttonPin0, INPUT_PULLUP);
  pinMode(buttonPin1, INPUT_PULLUP);
  pinMode(buttonPin2, INPUT_PULLUP);

}

void loop()
{
  static int pos = 0;
  encoder.tick();

  int newPos = encoder.getPosition();

  if (pos != newPos)
  {
    Serial.print(newPos);
    Serial.println();
    pos = newPos;
  }

  if (newPos <= encoderMin)
  {
    digitalWrite(mtrDown, HIGH);

  }

  if (newPos >= encoderMax)
  {
    digitalWrite(mtrUp, HIGH);

  }
  {

    buttonStatus1 = digitalRead(buttonPin1);
    buttonStatus2 = digitalRead(buttonPin2);
    buttonStatus0 = digitalRead(buttonPin0);
   
    if (buttonStatus1 == LOW)
    {
      digitalWrite(mtrDown, HIGH);
      delay(mtrdelay);
      digitalWrite(mtrUp, LOW);


    }
    if (buttonStatus2 == LOW)
    {
      digitalWrite(mtrUp, HIGH);
      delay(mtrdelay);
      digitalWrite(mtrDown, LOW);

    }
    if (buttonStatus0 == LOW)
    {
      digitalWrite(mtrUp, HIGH);
      digitalWrite(mtrDown, HIGH);
    }
    
    if (buttonStatus1 == LOW && buttonStatus0 == LOW)
    {
      digitalWrite(mtrDown, HIGH);
      digitalWrite(mtrUp, LOW);


    }
    if (buttonStatus2 == LOW && buttonStatus0 == LOW)
    {
      digitalWrite(mtrUp, HIGH);
      digitalWrite(mtrDown, LOW);
    }


  }
}
delay(mtrdelay);

That's 100 milliseconds ignoring your encoder and missing any counts.

If you have an encoder, and you want to be able to accurately read it, then there is no room for delay in your code.

i had the delay so the motor does not instantly switch direction if the up button is pressed and then the down is pressed. i was going to increase it after i got it working.

Andrew530:
i had the delay so the motor does not instantly switch direction if the up button is pressed and then the down is pressed. i was going to increase it after i got it working.

You can have the effect of the delay. You can wait for a while. But you can't use the delay function to do it. You have to use the Blink Without Delay method to handle that timing.

You're using Matthias Hertel's library? That seems more appropriate for an encoder knob turned by a person, not for a motor-position sensor.

Paul Stoffregen's encoder library will user interrupts when available, so it can continue to count during a delay(). It's available in the Arduino library manager.

But delays are still bad. To get rid of them for this example, I suggest you switch to a state machine structure. You will have a lot of states: stopped, running-up, stopped-waiting-to-go-down...

You have to use the Blink Without Delay method to handle that timing.

could you give me an example of what my code should look like or that.

thanks

Arduino IDE: File --> Examples --> 02.Digital --> BlinkWithoutDelay

Andrew530:
could you give me an example of what my code should look like or that.

thanks

The Blink Without Delay example is there in the examples in the IDE. There are literally thousands of web pages, tutorials, and forum posts explaining how it works. Why don't you put just a little bit of effort in yourself? Google is your friend.

is this what you were talking about. i can't seem to get it to work.

#include <RotaryEncoder.h>

RotaryEncoder encoder(A4, A5);

const int encoderPin = (A4, A5);
boolean toggle = true;
int buttonPin0 = 4;
int buttonPin1 = 5;
int buttonPin2 = 6;
int mtrUp = 12;
int mtrDown = 11;
int buttonStatus1 = LOW;
int buttonStatus2 = LOW;
int buttonStatus0 = LOW;



int encoderMin = -10;  // minimum sensor value
int encoderMax = 20;   //maximum sensor value
int encoderValue = 0;
int press = 0;

int period = 1000;
unsigned long time_now = 0;


void setup()
{
  Serial.begin(57600);
  Serial.println("ENCODER POSITION");
  pinMode(mtrUp, OUTPUT);
  digitalWrite(mtrUp, HIGH);
  pinMode(mtrDown, OUTPUT);
  digitalWrite(mtrDown, HIGH);
  pinMode(buttonPin0, INPUT_PULLUP);
  pinMode(buttonPin1, INPUT_PULLUP);
  pinMode(buttonPin2, INPUT_PULLUP);


}

void loop()
{
  static int pos = 0;
  encoder.tick();

  int newPos = encoder.getPosition();

  if (pos != newPos)
  {
    Serial.print(newPos);
    Serial.println();
    pos = newPos;
  }

  if (newPos <= encoderMin)
  {
    digitalWrite(mtrDown, HIGH);

  }

  if (newPos >= encoderMax)
  {
    digitalWrite(mtrUp, HIGH);

  }
  {

    buttonStatus1 = digitalRead(buttonPin1);
    buttonStatus2 = digitalRead(buttonPin2);
    buttonStatus0 = digitalRead(buttonPin0);
   
    if (buttonStatus1 == LOW)
    {
      digitalWrite(mtrDown, HIGH);
      while(millis() < time_now + period)
      digitalWrite(mtrUp, LOW);


    }
    if (buttonStatus2 == LOW)
    {
      digitalWrite(mtrUp, HIGH);
      while(millis() < time_now + period)
      digitalWrite(mtrDown, LOW);

    }
    if (buttonStatus0 == LOW)
    {
      digitalWrite(mtrUp, HIGH);
      digitalWrite(mtrDown, HIGH);
    }
    
    if (buttonStatus1 == LOW && buttonStatus0 == LOW)
    {
      digitalWrite(mtrDown, HIGH);
      digitalWrite(mtrUp, LOW);


    }
    if (buttonStatus2 == LOW && buttonStatus0 == LOW)
    {
      digitalWrite(mtrUp, HIGH);
      digitalWrite(mtrDown, LOW);


  }
  }
}
const int encoderPin = (A4, A5);

Well that's obviously not going to work. An int holds ONE value. Not two. Did you want an array here or something?

while(millis() < time_now + period)

I would suggest you go do some more reading on Blink Without Delay. It's never done this way because that fails at rollover, always with subtraction.

And you're using a while loop. So you might as well be using delay there. It is still blocking all other execution. The whole point of BWoD is to never hold up execution. Don't wait for something to be finished, let the loop function keep running and on each pass through check ONCE to see if it is time to do something.

Just replacing delay with blocking code using millis doesn't accomplish anything. The whole point is about NOT stopping other things from happening and NOT trapping execution on one line.

Is it going to be a separate if statement or does it get added between switching motor directions

It is always an if statement. The thing you want to happen every so often goes inside. The stuff you don't want interrupted or blocked goes outside. Google "Blink Without Delay". Don't just look at the code. There are literally thousands of pages where different people explain the concept in different ways. There is more about that one concept than anything else in Arduino.