Rotary encoder pinout diagram or wire color code

I recently received a rotary encoder from a Chinese seller on ebay that looked professional OMRON-like device and has 400 ppr. Here are some photos:

The problem is that communicating with the seller in Hong Kong who buys from a manufacurer in China was a very bad experience, and the only document they sent me after a long give and take through emails was a this image in Chinese that probably describes the connections of the encoder: The seller told me that the manufacturer does not have a datasheet!!

The only reason that I bought it from there was that I couldn't find it anywhere else and the few lower quality encoders from well known companies here in the US were about 3 times the price (which wasn't cheap at all).

Now the encoder looks very nice and has 4 wires (Black, Red, Blue, & Yellow). I tried some test code that is known to be working while the connection was: Red to +Vcc Black was to GND and the other two (figured out were signal) through 1K resistors to interrupt pins on an arduino board.

I didn't receive anything on the serial monitor.

Tried checking the pins with a multimeter to try to know the pinout (which is which) and found out that the black with each of the yellow and blue give me something around 1.85 (diode drop reading).

I am still tackling the puzzle but if there is any standard color code out there for 4-wire encoders that will be great.

BTW, The +Vcc I supplied the encoder with was Vin from the arduino board which was about 7 volts and here is the code I tried:

volatile boolean fired;
volatile boolean up;

#define PINA 20
#define PINB 21
#define INTERRUPT 3  // that is, pin 20

// Interrupt Service Routine for a change to encoder pin A
void isr ()
{
  if (digitalRead (PINA))
    up = digitalRead (PINB);
  else
    up = !digitalRead (PINB);
  fired = true;
}  // end of isr


void setup ()
{
  digitalWrite (PINA, HIGH);     // enable pull-ups
  digitalWrite (PINB, HIGH); 
  attachInterrupt (INTERRUPT, isr, CHANGE);   // interrupt 0 is pin 2, interrupt 1 is pin 3

  Serial.begin (9600);
}  // end of setup

void loop ()
{
static long rotaryCount = 0;
  if (fired)
    {
    if (up)
      rotaryCount++;
    else
      rotaryCount--;
    fired = false;
        
    Serial.print ("Count = ");  
    Serial.println (rotaryCount);
  
    }  // end if fired

}  // end of loop

Borrowed from an older post by Nick Gammon

It worked!! There was a little contact problem and It's working great with the code and connection above. I don't know how to delete this thread or if it should stay in the archive of this forum

Thanks i just received the same encoder and needed some hints to wire it. I am thinking your should leave the thread up.

Hi, glad to see you got the problem solved. Most encoders have open collector outputs, this one is no different. The Chinese spec shows that a collector or pullup resistor is required. 1.5K if using a 12V supply, however in turning the pullup resistors ON in the arduino you have provided the current path required.

Good to see when the enquirer has been able to solve the problem themselves, you learn a lot.

Tom

Hi Everybody!

Sorry for my bad English! :blush:

I have received the same encoder, and this post was very useful to me. But it gives inaccurate results. Did you get accurate results with this Encoder?

In one revolution it should give 400 counts but it gives less. If I give one rotation in anti - clockwise direction, it is not giving the same result as previous case.

What should I do?

thanks!

Hi, can you post a picture of your project and a CAD or picture of a hand drawn circuit diagram, including how you are supplying power to the aduino and encoder.

Hope to help.

Tom........... :)

In one revolution it should give 400 counts but it gives less. If I give one rotation in anti - clockwise direction, it is not giving the same result as previous case.

Are you using interrupts?. Are you using Serial.print to monitorize?

Regards

Hi

First thanks for your prompt reply!

Here’s my drawing

Are you using interrupts?. Are you using Serial.print to monitorize?

yes, firstly I used your code , without accuracy.

But I found this code in Arduino’s web (it’s working better):

//PIN’s definition
#define encoder0PinA 2
#define encoder0PinB 3

volatile int encoder0Pos = 0;
volatile boolean PastA = 0;
volatile boolean PastB = 0;

void setup()
{
Serial.begin (9600);
pinMode(encoder0PinA, INPUT);
//turn on pullup resistor
//digitalWrite(encoder0PinA, HIGH); //ONLY FOR SOME ENCODER(MAGNETIC)!!!
pinMode(encoder0PinB, INPUT);
//turn on pullup resistor
//digitalWrite(encoder0PinB, HIGH); //ONLY FOR SOME ENCODER(MAGNETIC)!!!
PastA = (boolean)digitalRead(encoder0PinA); //initial value of channel A;
PastB = (boolean)digitalRead(encoder0PinB); //and channel B

//To speed up even more, you may define manually the ISRs
// encoder A channel on interrupt 0 (arduino’s pin 2)
attachInterrupt(0, doEncoderA, RISING);
// encoder B channel pin on interrupt 1 (arduino’s pin 3)
attachInterrupt(1, doEncoderB, CHANGE);

}

void loop()
{
Serial.print ("Count = ");
Serial.println ( encoder0Pos);
delay(10);
}

//you may easily modify the code get quadrature…
//…but be sure this whouldn’t let Arduino back!
void doEncoderA()
{
PastB ? encoder0Pos–: encoder0Pos++;

}

void doEncoderB()
{
PastB = !PastB;
}

thanks

best regards

Ivan Barquero

Hi,

I’m still testing my code (for a speed servo DC hobby motor). I could say it works, but I do prefere testing it deeply before posting it.

I’ve had to struggle with serial.Print: it takes a long time to execute and, depending on the algorithm you are using to control the speed, it can influence the results. Since I realized that I’m using the DAC’s (arduino due) to check speed and/or errors, corrections, and so on . . . (by that means, you can use alternatively an oscilloscope or a normal multimeter . . .).

Suerte. (¿ hablas español?)

Hi, vffgaston, what is your serial speed? Set it to maximum, 115200, this will speed the sketch up.

Tom.......... :)

vffgaston: I've had to struggle with serial.Print: it takes a long time to execute and, depending on the algorithm you are using to control the speed, it can influence the results. eans, you can use alternatively an oscilloscope or a normal multimeter . . .).

Serial.print() has a buffer and is interrupt driven, it should only stall if the transmit buffer fills up.

Unfortunately there's no function to check for space in the transmit buffer. You just have to print less often....

Hi Everybody

Hi, vffgaston, what is your serial speed? Set it to maximum, 115200, this will speed the sketch up.

This is true, if I change serial speed to 115200 in this code, it will speed up, and get a little more acurracy, but it's no working well:

volatile boolean fired;
volatile boolean up;

#define PINA 20
#define PINB 21
#define INTERRUPT 3  // that is, pin 20

// Interrupt Service Routine for a change to encoder pin A
void isr ()
{
  if (digitalRead (PINA))
    up = digitalRead (PINB);
  else
    up = !digitalRead (PINB);
  fired = true;
}  // end of isr


void setup ()
{
  digitalWrite (PINA, HIGH);     // enable pull-ups
  digitalWrite (PINB, HIGH); 
  attachInterrupt (INTERRUPT, isr, CHANGE);   // interrupt 0 is pin 2, interrupt 1 is pin 3

  Serial.begin (9600);
}  // end of setup

void loop ()
{
static long rotaryCount = 0;
  if (fired)
    {
    if (up)
      rotaryCount++;
    else
      rotaryCount--;
    fired = false;
        
    Serial.print ("Count = ");  
    Serial.println (rotaryCount);
  
    }  // end if fired

}  // end of loop

So its better to set up serial speed to 115200 in all sketch up?? :astonished:

I've tested this code and works very well for me, has anybody tested it?

//PIN's definition
#define encoder0PinA  2
#define encoder0PinB  3

volatile int encoder0Pos = 0;
volatile boolean PastA = 0;
volatile boolean PastB = 0;

void setup() 
{
  Serial.begin (9600);
  pinMode(encoder0PinA, INPUT);
  //turn on pullup resistor
  //digitalWrite(encoder0PinA, HIGH); //ONLY FOR SOME ENCODER(MAGNETIC)!!!! 
  pinMode(encoder0PinB, INPUT); 
  //turn on pullup resistor
  //digitalWrite(encoder0PinB, HIGH); //ONLY FOR SOME ENCODER(MAGNETIC)!!!! 
  PastA = (boolean)digitalRead(encoder0PinA); //initial value of channel A;
  PastB = (boolean)digitalRead(encoder0PinB); //and channel B

//To speed up even more, you may define manually the ISRs
// encoder A channel on interrupt 0 (arduino's pin 2)
  attachInterrupt(0, doEncoderA, RISING);
// encoder B channel pin on interrupt 1 (arduino's pin 3)
  attachInterrupt(1, doEncoderB, CHANGE); 

}


void loop()
{  
  Serial.print ("Count = ");  
    Serial.println ( encoder0Pos);
    delay(10);
}

//you may easily modify the code  get quadrature..
//..but be sure this whouldn't let Arduino back! 
void doEncoderA()
{
     PastB ? encoder0Pos--:  encoder0Pos++;
    
}

void doEncoderB()
{
     PastB = !PastB; 
}

Best regards

Ivan Barquero

P.D. vffgaston, sí ,hablo español. Soy de Tudela, navarra, ( me habrás reconocido por mi cutre-ingles xd), no se si en la comunidad les molestará que escribamos en Castellano cuando este Post esta originalmente escrito en inglés, (pero desde luego me explicaría mejor)

El tema de la precision del Encoder, con el segundo código esta solucionado ( creando las ISR manualmente), aunque me gustaría que alguien más pudiera testear los codigos.

Otra cuestion es que he encontrado poca informacion sobre "Using pin change interrupts (PCINT)", ya que mi mega 2560 solo tiene 6 interrupts y me gustaría poder tener más. no se si alguien me podrá explicar ( igual debería postear en otro post relacionado con el tema,

Saludos!

Hi, vffgaston, what is your serial speed? Set it to maximum, 115200, this will speed the sketch up.

Hi, TomGeorge,

When I noticed the problem of the time it takes the Serial.print command (@ 9600 almost double the time between interrupts -encoder rising edges-) I discarded it to debug the code. Nevertheless, later I tried to change the baud rate to different speeds, but then the monitor started showing alien characters (it brings to me such an old memories . . .) even, of course, changing the speed in the "hardware managing" XP window: frankly, I am too lazy to change parities, stop bits and so on and check what happens.

Am I doing something wrong? (I mean, should it work changing JUST the baud rate both sides?)

Thanks (every case) ;)

Hi, did you change the speed in the monitor screen to the same as the speed you changed in the sketch?

Tom...... :)

Hi Tom,

That’s the way I do it.

Regards

BAUD_RATE.bmp (1.38 MB)

Hola Iván,

I will write the main part of the post in english (I think is a matter of politness), specially the technical parts of it. (Nevertheless, I think your english is quite good: sure everyboby understand it).

I’m developping a servo speed (software made) for the simplest hobby DC motor (the one that every kit mounts; see photo). I have it almost finished (in fact I’m testing how it performs with brand new batteries, medium wasted, an AC~DC converter and so on: for the first & second cases it is already working well). The encoder is a 10 teeth one made in plastic (and with the teeth slightly different, by the way).

What is your hardware?. If it matches with mine one I’ll test it in my hardware (even if I have to change pins numbers and things like that).

English readers! . . the spanish part begins (i swear that it contains just personal data and greetings . . . and some kind ethnic comments;). Pls excuse us).

Regards

Como habrás visto vivo en Logroño (ayer estuve en Castejón por cuestiones profesionales).

En general estos sajones son un poco polillas con cuestiones de protocolo, así que mejor que la parte técnica esté en inglés (seguro que hay gente que te puede ayudar aunque sólo hablen inglés . . pobres. Además así podemos tirarles alguna puya como esta 8).

Postea lo que te pido y miro a ver si puedo ayudarte (en cualquier caso especifícame cual es el proyecto final).

mgrwfRCxTv5t5e2xh9GtZPw.jpg