I Have a problem with arduino and rotary encoder

Hello everyone, I hope you can help me.
I have a problem with an encoder and Arduino Mega. I have found several tutorials on the Internet on how to use the encoder on Arduino, but all the videos and forums I have seen use a 5V encoder. I currently have an Omron E6B2-CWZ5B rotary encoder with 360P/R resolution, it is 12 to 24 V. I have tried several codes, however, none of them work for me, I have tried another similar encoder because I thought it might be damaged, but it does not give me a real reading, with any code at the time I see the serial monitor it throws me too many random values ​​without even moving the encoder, I managed to make it "work" with a code, I get values ​​in the serial monitor, but here I have another problem, if I turn the encoder slowly, it gives me a reading, for example, from 0 to 250 in a range of 5 cm, but if I do that same range but quickly, the encoder gives me a reading from 0 to 20, it is an example, if I turn quickly I have a different value than when I turn slowly, I don't really know what the problem is, I am energizing the encoder at 24v with an external source, can someone help me?

Well - we could help more if you provided information

https://industrial.omron.co.uk/en/products/E6B2-CWZ5B-100P-R-0-5M

like - how you have it connected, what arduino you are using , your sketch, ...

Hey I'm using this code:

volatile unsigned int temp, counter = 0; //This variable will increase or decrease depending on the rotation of encoder
    
void setup() {
  Serial.begin (9600);

  pinMode(2, INPUT_PULLUP); // internal pullup input pin 2 
  
  pinMode(3, INPUT_PULLUP); // internalเป็น pullup input pin 3
//Setting up interrupt
  //A rising pulse from encodenren activated ai0(). AttachInterrupt 0 is DigitalPin nr 2 on moust Arduino.
  attachInterrupt(0, ai0, RISING);
   
  //B rising pulse from encodenren activated ai1(). AttachInterrupt 1 is DigitalPin nr 3 on moust Arduino.
  attachInterrupt(1, ai1, RISING);
  }
   
  void loop() {
  // Send the value of counter
  if( counter != temp ){
  Serial.println (counter);
  temp = counter;
  }
  }
   
  void ai0() {
  // ai0 is activated if DigitalPin nr 2 is going from LOW to HIGH
  // Check pin 3 to determine the direction
  if(digitalRead(3)==LOW) {
  counter++;
  }else{
  counter--;
  }
  }
   
  void ai1() {
  // ai0 is activated if DigitalPin nr 3 is going from LOW to HIGH
  // Check with pin 2 to determine the direction
  if(digitalRead(2)==LOW) {
  counter--;
  }else{
  counter++;
  }
  }

And this is the diagram:
https://drive.google.com/file/d/14GEU6vKW8fl02yoAfO_-iTOAeVKnHHY4/view?usp=sharing

Sorry, but it's the only diagram I have right now

Hi axvu,
Be careful, it is not sure that you can directly connect the BLK and WH wires on the D2 and D3 inputs, because your encoder is powered in 12 V or 24V (unless they are open collector transistors which drive these wires; but if in doubt, you should be careful, you should put a transistor or at least a resistor network on these inputs).
Do you want an example of a program already done, or to correct your own ?

Add a voltage divider

Z

Of course yes, I could use some help

Ok, I have seen the documentation given by johnerrington, you have open collectors on BLK et WH, with the 12/24V type. You can wire directly on D and D3. For safety reason, I would put a 1K resistor in series.

Look you can review this manual, I'm using E6B2-CWZ5B model. Manual is short, but it has Open-collector Output:
extension://efaidnbmnnnibpcajpcglclefindmkaj/https://www.ia.omron.com/data_pdf/cat/e6b2-c_ds_e_6_1_csm491.pdf?id=487

Ok, you can try this :wink:
(don't forget to put your serial monitor with 115200 bauds)

  // Arduino pro-mini 5V 16 M         *optical* encoder          A & B on pin 2 & 3 
  // if you want to use a mechanical encoder, signals A & B *MUST* be (electricaly) properly debounced !

  #define SignalA          B00000100                          // encoder signal pin 2 (port D)
  #define SignalB          B00001000                          // encoder signal pin 3 (port D)
  #define SignalAB         B00001100                          // both signals
  volatile int             encodPos;                          // encoder position
  volatile byte            LastPortD = SignalA;               // previous A/B state 
  int encodLastPos;                                           // ----- for this demo, previous position


void setup(void) {
  PORTD |= SignalAB;                                          // internal pullups on interrupt pins 2, 3
  Serial.begin(115200);                                       // fast fast fast !
  attachInterrupt(digitalPinToInterrupt(2), ExtInt, CHANGE);  // encoder pin 2 interrupt vector
  attachInterrupt(digitalPinToInterrupt(3), ExtInt, CHANGE);  // encoder pin 3 interrupt vector 
}


void ExtInt() {                                               // OPTICAL ENCODER ext. interrupt pin 2, 3
  byte PortD =      PIND  & SignalAB;                         // 
  if ((PortD ^ LastPortD) & SignalA)   encodPos++;            // Rotation ->    {encodPos++; Sense = 1;}
  if ((PortD ^ LastPortD) & SignalB)   encodPos--;            // Rotation <-    {encodPos--; Sense = 0;}
  if ((PortD) &&  (PortD != SignalAB)) PortD ^= SignalAB;     //                              (swap A-B)
   LastPortD  =    PortD;                                     //                  mieux vaut faire court
}


void loop(void) {                                             // MAIN LOOP

  noInterrupts();                                             //
    int encodPosition = encodPos;                             //
  interrupts();                                               //

  if (encodLastPos != encodPosition) {                        // when the encoder change,
    encodLastPos = encodPosition;                             //
    Serial.println(encodPosition);                            // print encoder position
  }                                                           //
}                                                             //


I have already done it like this, however, when I check the serial monitor, it starts throwing random values without even moving the encoder axis. I have tried several codes from this forum ( Arduino Playground - RotaryEncoders, however with all of them it throws me random values, that is the problem I have. And I foud another code that does give me values when I move the encoder axis. But it doesn't giev me "real" readings because if I move the axis slowly it gives me different values than when I move it fast

Let me try, wait a minute

it should work !

This is what it shows me, it doesn't give me values if I move the encoder axis

OK, this looks like an electrical problem

can you measure the voltage on D2 and D3, with a multimeter?
You must see 5V and 0V, or 0V and 5V

I'm using an Arduino Mega, and the D2 and D3 are in the PWM Section, however, the digital ones start at 22, does that affect anything? or doesn't matter?

one moment, I look at the mega pins...

I have tried with 2 different encoders and 2 different Arduino but I have the same problem in the photo, Idk what's the problem

it seems you are not on the goods pins; you must be on pin 2 and pin 3, is this it ?
( I am not used to mega)

NO NO NO !

pin 18 and 19, it seems

Readings?
You're up/down counting, no position. You're only getting x pulses per rotation and you're not resetting at zero. You have to count from zero, not take a long count. If you rapidly spin the encoder you can out run the electronics.
Your direction logic doesn't look right but i can't put my finger on it.
It is possible to tease this encoder by being on the hairy edge and vibration. Hand rotation is unreliable. These are designed to be smoothly spun. Ive used their absolute encoders and they're tops.