Help with Incremental Optical Encoder

Hi, I'm quite new to electronics I got my basic knowledge from disassembling toys when I was like 5. And now I'm 15 so I haven't learned a lot about electronics.

I've been trying to get an rotary encoder to work (E6B2-CWZ6C 2000P/R 2M | OMRON Industrial Automation) and I've managed to do just that it works just fine, but I'm facing a issue on finding the angular direction the shaft is rotating on. to my knowledge I think the encoder's direction is determined by if the APulse is Greater than the BPulse it's rotating Clockwise and the opposite for CCW. But everytime I try the result becomes all random sometimes its cw and sometimes ccw I have to rotate the shaft fast suddenly for it to be registered as cw or ccw, but then also it gets mixed up. I'm using an Arduino leonardo for this, A is connected to D3 and B is to D2 (I've also connected Z to D0 but that's working fine since its only one pulse pr)
I currently cannot provide the code as of now since I'm away from my computer but I can send it in a reply if you want. The code isn't much though I just attached interrupt to 2 functions which just adds value B and A, and to determine the direction I checked if A is Greater than B and so on. I'm currently assuming its something to be related with mechanical bouncing and such but I'm not sure.

Any help will be much appreciated,
Thanks lots!

PS: as you can probably tell I'm very new to this forum so, sorry if I did any mistakes.

Edit: For anyone in the future I found the solution. I feel so stupid now knowing that it took me a whole day to find out it was this simple to do, Here's the code. (digitalWriteFast is a library package thingy it's not essential). Thanks to anyone that helped me with this!

#include <digitalWriteFast.h>

int counter = 0;

void setup() {
  Serial.begin(9600);

  pinMode(3, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);
  pinMode(0, INPUT_PULLUP);

  attachInterrupt(0, ai0, RISING);
  attachInterrupt(1, ai1, RISING);
  attachInterrupt(2, ai2, RISING);
}

void loop() {
  Serial.println(counter);
}

void ai0() {
  if (digitalReadFast(2) == LOW) {
    counter--;
  }
}

void ai1() {
  if (digitalReadFast(3) == LOW) {
    counter++;
  }
}

void ai2() {
  counter = 0;
}

I use this code to work with a similar encoder:
(readB == A) ? count++ : count--; // Count Forware or Count backwards
this gives the direction when the pulse occurs.

Full extremely fast Example:

#define ClockPin 2 // Must be pin 2 
#define DataPin 3 // Must be pin 3
#define readA bitRead(PIND,2)//faster than digitalRead()  (((value) >> (bit)) & 0x01)
#define readB bitRead(PIND,3)//faster than digitalRead()  (((value) >> (bit)) & 0x01)
volatile long count = 0;
long lastCtr;
unsigned long SpareCycles;

void Encoder(bool A) {
  (readB == A)  ? count++ : count--;
}

void setup() {
  Serial.begin(115200); //115200
  pinMode(ClockPin, INPUT);
  pinMode(DataPin, INPUT);
  /* 1 Step */
  attachInterrupt(digitalPinToInterrupt(ClockPin), [] {Encoder( true);}, RISING);
  /**/

  /*  2 step count
  attachInterrupt(digitalPinToInterrupt(ClockPin), [] {Encoder( readB);}, CHANGE);
  */
  
  /* Full 4 Step Count
  attachInterrupt(digitalPinToInterrupt(ClockPin), [] {Encoder( readB);}, CHANGE);
  attachInterrupt(digitalPinToInterrupt(DataPin ), [] {Encoder( !readA);}, CHANGE);
  */
}

void loop() {
  long Counter;
  SpareCycles++;
  noInterrupts ();
  Counter = count; //get the value without interrupts affecting it.
  interrupts ();
  if ((lastCtr != Counter) & (SpareCycles > 10)) {
    Serial.println(Counter);
    SpareCycles = 0;
  }
  lastCtr = Counter;
}

Notes:
[] {Encoder( true);}
found in:

  /* 1 Step */
  attachInterrupt(digitalPinToInterrupt(ClockPin), [] {Encoder( true);}, RISING);
  /**/

This is called a Lambda or anonymous function.
Lambda functions are called "anonymous" because they do not have a name that you can use to call them directly. Instead, they are typically used as part of another expression or statement.
I use the Lambda function to allow me to pass a value to the Encoder() function which normally couldn't happen when using the attachInterrupt() function.

Z

Please follow the forum rules (see the "How to get the best out of this forum" post). Post the code, using code tags, and a photo of a hand-drawn wiring diagram, with pins and connections clearly labeled.

In the serial monitor, it seems to add values if A is connected to D3, B is connected to D2 and subtract if B is connected to D3, A is connected to D2. I'm so confused :confused:

Sorry will do next time

This is expected behaviour given the nature of the quadrature output from the encoder. You need to make the connects so that you increment or decrement in the desired rotation direction for your application.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.