Problems with incremental rotary encoder ABZ. Broken Microcontroller?

Im currently testing an incremental rotary encoder the GHH60. Goal is to tell the absolute position of the shaft. At first everything seems to work fine but after a bit of time my values are getting super weird.

The setup:
-Arduino DUE
-GHH60-10G1024BMP526 (PNP+NPN Output) run with 5V and the the ouputs are brought down to 3.3V by voltage dividers (i know not optimal but currently dont have Schmitttriggers around me)

and here the code:

constexpr uint8_t PIN_A = 53;
constexpr uint8_t PIN_B = 51;
constexpr uint8_t PIN_Z = 49;

#define ZERO_ON_Z_RISING   1
#define PLOT_INTERVAL_MS   5
#define BAUDRATE           115200
#define Z_LOCKOUT_US 1000   


volatile long encoderPos = 0;    
volatile uint8_t lastA = 0;
volatile int8_t lastDir = 0;     
volatile long z_counter = 0;     
volatile unsigned long lastZMicros = 0;


unsigned long lastPlot = 0;


void isrA() {
  uint8_t a = (uint8_t)digitalRead(PIN_A);
  uint8_t b = (uint8_t)digitalRead(PIN_B);

  if (a != lastA) {
    if (a == b) {
      encoderPos--;
      lastDir = -1;
    } else {
      encoderPos++;
      lastDir = +1;
    }
    lastA = a;
  }
}


void isrZ() {
  
  unsigned long now = micros();
  if ((unsigned long)(now - lastZMicros) < (unsigned long)Z_LOCKOUT_US) {
    return;
  }
  lastZMicros = now;

#if ZERO_ON_Z_RISING
  encoderPos = 0;
#endif
  
  if (lastDir >= 0) {
    z_counter++;
  } else {
    z_counter--;
  }
}

void setup() {
  Serial.begin(BAUDRATE);
  while (!Serial) {;}  

  pinMode(PIN_A, INPUT_PULLUP);
  pinMode(PIN_B, INPUT_PULLUP);
  pinMode(PIN_Z, INPUT_PULLUP);

  lastA = (uint8_t)digitalRead(PIN_A);

  attachInterrupt(digitalPinToInterrupt(PIN_A), isrA, CHANGE);
  attachInterrupt(digitalPinToInterrupt(PIN_Z), isrZ, RISING);

}

void loop() {
  unsigned long now = millis();
  if (now - lastPlot >= PLOT_INTERVAL_MS) {
    lastPlot = now;

    int a = digitalRead(PIN_A);
    int b = digitalRead(PIN_B);
    int z = digitalRead(PIN_Z);

    long pos;
    long zc;
    noInterrupts();
    pos = encoderPos;
    zc  = z_counter;
    interrupts();

    Serial.print(a);   Serial.print('\t');
    Serial.print(b);   Serial.print('\t');
    Serial.print(z);   Serial.print('\t');
    Serial.print(pos); Serial.print('\t');
    Serial.println(zc);
  }
}

Behaviour:
-at first everything works wonderful. Position and the Z_counter changing as expected even if rotated fast
-after a bit of time things get buggy:
-> big jumps in the z_counter (even with the software debounce)
-> position variable changes only between [-1, 0, 1]
-> z_counter behaves like position variable: increments on every AB signal but doesn't reset
-> i also witnessed that sometimes the values jumped back and everything from then on seemed to work again as expected
-> i noticed also that if the encoder kept moving there was a lower tendency for the unexpected behaviour above. If the encoder did not move at all the buggy behavior showed up quite fast.

Any thoughts? After hours of debugging im stuck;(
Thanks in regards

Please post schematics of the build.

Edit:

-tomorrow i will try a different arduino to see if thats the problem
-to speak in numbers: sometimes the z_counter jumps to 600 from 0 while before working correctly

Long, looping leads, which are decent antennas, combined with loose, unsoldered connections on a breadboard invite all sorts of havoc, ranging from wobbly, intermittent connections to pickup of electrical interference from overhead lighting and other household appliances.

With consequences exactly as you describe.

That could be as @jremington says. It can also be unproperly connecting/using the GHH60.

A link to its datasheet could help us.

here you go:)

did you fin answere?

i could solder everything but i thought for prototyping the setup is sufficient;(

It appears from the image the voltage dividers are not connected as you think - that is, not at all.

p.s. which means, I think, you're driving five volt signals directly to the processor.

HA! I should stop wiring after 10 pm lol. Thanks man. Lets see how it works xD

You don't need to enable the pin pullup resistors with that encoder/wiring.
LastA should be static and defined within isrA since it is not used outside isrA.

Is there a faster digitalRead() available on the Due ?
I don't think you need to suspend interrupts in the loop() when reading 32bit values.

So finally wired everything correctly and made the changes that 6v6gt suggested. Everything runs smoothely now. Thanks a lot!

:+1: :slightly_smiling_face: