N20 Motor Rotary Encoder Counting Problem

Hi everyone,
I have a N20 Gearbox DC Motor with Encoder,
While running the motor I know the direction with output values of pins. Than I decied to use One Signal pin of rotary encoder to count ++ or --
But I realized that one direction counts more than the other side.
I cannot understand how it is generating signals.
Should I use 2 pins of Encoder?

Please help me :frowning:
Thanks a lot

Please post your code and a circuit diagram. A photograph of a hand drawn circuit will suffice.

A link to the motor/gearbox/encoder would also be useful

You need to post a link to the datasheet for your encoder and also post the program you are using.

...R

PS ... please post your program using the code button </>

so it looks like this

. See How to use the Forum. It makes it much easier for people to help you

Motor Link : Motor Link

My code :

#include <EEPROM.h>
#include <IRremote.h>
//MOTOR CONSTANTS
#define encoder0PinA  2
#define motorPinA  3
#define motorPinB  4
#define STOP 0
#define FORWARD 1
#define REVERSE 2

#define RANGE_END 2000
#define RANGE_START 1500
#define RANGE_TOLERANCE 0
#define STEP_SIZE 50


//IR CONSTANTS
#define IR_CLOSE_CODE 28815
#define IR_OPEN_CODE 45135
#define IR_STEP_REVERSE_CODE 61455
unsigned int val = 0;
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;


volatile int encoderDirection = STOP;
volatile int motorDirection  = STOP;
volatile int encoderState, lastEncoderState;
volatile unsigned int counter = 0;
volatile boolean IsStepReverseActive = false;
volatile unsigned int targetCounter = RANGE_START;



void setup() {
  irrecv.enableIRIn();
  pinMode(encoder0PinA, INPUT);
  pinMode(motorPinA, OUTPUT);
  pinMode(motorPinB, OUTPUT);
  attachInterrupt(0, doEncoderA, CHANGE);
  encoderState = digitalRead(encoder0PinA);
  lastEncoderState = encoderState;

  Serial.begin (9600);

  Serial.print("Counter value from EEPROM : ");
  counter = EEPROMReadInt(0);
  Serial.println(counter, DEC);

  delay(100);
  motorForward();
}

void loop() {

  if (irrecv.decode(&results)) {
    val = results.value;
    
    if (val == IR_CLOSE_CODE) {
      Serial.println("IR CLOSE"); motorReverse();
    } else if (val == IR_OPEN_CODE) {
      Serial.println("IR OPEN"); motorForward();
    } else if (val == IR_STEP_REVERSE_CODE) {
      Serial.println("IR STEP REVERSE"); 
      if ((counter - STEP_SIZE) >= RANGE_START)
      {
        IsStepReverseActive = true;
        targetCounter = counter - STEP_SIZE;
        motorReverse();
      }
    }
    
    irrecv.resume(); // Receive the next value
  }

   
}

void doEncoderA() {
  encoderState = digitalRead(encoder0PinA);
  if (lastEncoderState != encoderState) {
    lastEncoderState = encoderState;

    //*****************************************************
    if (encoderDirection == FORWARD) {
      counter++;
    }
    else if (encoderDirection == REVERSE)
    {
      counter--;
    }
   //*****************************************************

    if (motorDirection == FORWARD && counter >= RANGE_END)
    {
      motorStop();
    }
    else if (motorDirection == REVERSE && counter <= RANGE_START)
    {
      motorStop();
    }
    else if(IsStepReverseActive && counter <= targetCounter)
    {
      motorStop();
    }
    else
    {
      EEPROMWriteInt(0, counter);
    }
    Serial.println(counter, DEC);
  }
}

void motorForward() {
  if (counter < RANGE_END)
  {
    digitalWrite(motorPinA, HIGH);
    digitalWrite(motorPinB, LOW);
    motorDirection = FORWARD;
    setEncoderDirection(FORWARD);
  }
}
void motorReverse() {
  if (counter > RANGE_START)
  {
    digitalWrite(motorPinA, LOW);
    digitalWrite(motorPinB, HIGH);
    motorDirection = REVERSE;
    setEncoderDirection(REVERSE);
  }
}
void motorStop() {
  if (motorDirection != STOP) {
    digitalWrite(motorPinA, LOW);
    digitalWrite(motorPinB, LOW);
    motorDirection = STOP;
    IsStepReverseActive = false;
    EEPROMWriteInt(0, counter);
  }
}

void EEPROMWriteInt(int p_address, int p_value)
{
  byte lowByte = ((p_value >> 0) & 0xFF);
  byte highByte = ((p_value >> 8) & 0xFF);

  EEPROM.write(p_address, lowByte);
  EEPROM.write(p_address + 1, highByte);
}

unsigned int EEPROMReadInt(int p_address)
{
  byte lowByte = EEPROM.read(p_address);
  byte highByte = EEPROM.read(p_address + 1);

  return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);
}

void setEncoderDirection(int d) {
  if (d == FORWARD) {
    encoderDirection = FORWARD;
  } else if (d == REVERSE) {
    encoderDirection = REVERSE;
  }
}

Info:
500RPM (N20 15000RPM, reduction ratio 30: 1)
210 pulses per revolution = Motor Tail Hall encoder (7CPR) * 30 (reduction ratio)

....

I want to move between 1500 - 2000 values, it does but position is not stable .. It always going more and more closer to one side slowly.

I suggest that you start with a program that only controls the motor (no EEPROM and no IR) to keep things as simple as possible until you figure out how to control the motor.

I don't understand why you would have a function called setEncoderDirection(). In my mind you GET data from an encoder.

...R

One part of the motor specification says

Continuous Current(A):60

Very amusing !

Later on it says

Current (mA): ≤170

More realistic but I hope that it is not being powered from an Arduino pin.

Circuit diagram awaited

I use a Motor Driver module

Robin2:
I suggest that you start with a program that only controls the motor (no EEPROM and no IR) to keep things as simple as possible until you figure out how to control the motor.

I don't understand why you would have a function called setEncoderDirection(). In my mind you GET data from an encoder.

...R

beacuse Although I stopped the motor, the rotary encoder generates signal for a second after set pinout values LOW. The recieved signals must be processed.
So I have to remember the last command before STOP

UKHeliBob:
Please post your code and a circuit diagram. A photograph of a hand drawn circuit will suffice.

Seems like a pretty straight forward and reasonable request.

I will do when I get back to home

Back to the basic question

Should I use 2 pins of Encoder?

You presumably know the motor direction so you just need to count pulses on one encoder pin and add/subtract to/from the count according to the motor direction.

If you use both encoder pins you can determine the direction, but if you are controlling the motor this should not be necessary and is only usually used to read an externally driven encoder.

boraciner:

I don't understand why you would have a function called setEncoderDirection(). In my mind you GET data from an encoder.

beacuse Although I stopped the motor, the rotary encoder generates signal for a second after set pinout values LOW. The recieved signals must be processed.
So I have to remember the last command before STOP

I'm not convinced.

I could understand saveEncoderDirection(), but not setEncoderDirection()

...R