Help on Project with Rotary Incremental Encoder

Hi!
I'm trying to make a 12v engine work along with it's controller and an incremental encoder, but the encoder seems to be responding wrongly to real interactions, so to isolate this component I created a specific diagram using Fritzing (first time using it, sorry if it's kind of messy), and an ChatGPT-generated arduino code.

SPECIFICATIONS:

  • Schmitt Trigger Cd40106 Dip Cd40106b Cd40106be
  • Arduino Uno
  • 2x 1kohm resistors
  • ROTARY ENCODER LPD3806-600BM-G5-24C

Code:

#define ENCODER_A 2
#define ENCODER_B 3

const int PULSES_PER_REVOLUTION = 600;  // Adjust this according to your encoder
volatile int pulseCounter = 0;

void setup() {
  // Configure the encoder pins as inputs (without internal pull-ups)
  pinMode(ENCODER_A, INPUT);
  pinMode(ENCODER_B, INPUT);

  // Start serial communication
  Serial.begin(9600);
  Serial.println("System started");

  // Configure the interrupts for the encoder pins
  attachInterrupt(digitalPinToInterrupt(ENCODER_A), onChangeA, CHANGE);
  attachInterrupt(digitalPinToInterrupt(ENCODER_B), onChangeB, CHANGE);
}

void loop() {
  // Calculate the current angular position in degrees
  float angle = (pulseCounter % PULSES_PER_REVOLUTION) * 360.0 / PULSES_PER_REVOLUTION;

  // Ensure the angle is within the range [0, 360)
  if (angle < 0) {
    angle += 360;
  }

  // Print the current angular position on the Serial Monitor
  Serial.print("Angular position: ");
  Serial.print(angle, 2);  // Print with two decimal places
  Serial.println(" degrees");

  delay(100);  // Wait 100 ms for faster readings
}

void onChangeA() {
  noInterrupts();  // Disable interrupts while executing this function

  int stateA = digitalRead(ENCODER_A);
  int stateB = digitalRead(ENCODER_B);

  // Increment or decrement the pulse counter depending on the rotation direction
  if (stateA == HIGH) {
    if (stateB == LOW) {
      pulseCounter++;
    } else {
      pulseCounter--;
    }
  } else {
    if (stateB == LOW) {
      pulseCounter--;
    } else {
      pulseCounter++;
    }
  }

  interrupts();  // Re-enable interrupts
}

void onChangeB() {
  noInterrupts();  // Disable interrupts while executing this function

  int stateA = digitalRead(ENCODER_A);
  int stateB = digitalRead(ENCODER_B);

  // Increment or decrement the pulse counter depending on the rotation direction
  if (stateA == HIGH) {
    if (stateB == LOW) {
      pulseCounter++;
    } else {
      pulseCounter--;
    }
  } else {
    if (stateB == LOW) {
      pulseCounter--;
    } else {
      pulseCounter++;
    }
  }

  interrupts();  // Re-enable interrupts
}


The results I'm getting when I manually rotate the axis of the encoder 360º are these (far from reality):

Angular position: 359.40 degrees
Angular position: 359.40 degrees
Angular position: 359.40 degrees
Angular position: 359.40 degrees
Angular position: 359.40 degrees
Angular position: 359.40 degrees
Angular position: 359.40 degrees
Angular position: 0.00 degrees
Angular position: 0.00 degrees
Angular position: 359.40 degrees
Angular position: 359.40 degrees
Angular position: 0.00 degrees
Angular position: 0.00 degrees
Angular position: 0.00 degrees
Angular position: 359.40 degrees
Angular position: 0.00 degrees
Angular position: 0.00 degrees
Angular position: 359.40 degrees
Angular position: 0.00 degrees
Angular position: 359.40 degrees
Angular position: 359.40 degrees
Angular position: 359.40 degrees
Angular position: 0.00 degrees
Angular position: 359.40 degrees
Angular position: 359.40 degrees
Angular position: 359.40 degrees
Angular position: 0.00 degrees
Angular position: 0.00 degrees
Angular position: 0.00 degrees
Angular position: 359.40 degrees
Angular position: 359.40 degrees

It never prints more than 20º in total, totally weird. And this is the reason why I'm using a Schmitt trigger for noise cancel (just in case. I read it may be helpful).

Any ideas? Did you ever use an incremental encoder for arduino?

Thank you very much!!!

Please post a conventional schematic diagram, Fritzings are generally useless.

You do not need an IC, just two pullup resistors on A and B. Since the encoder is specified as 600 PPR, you will need to properly scale the counts to have 0-360 degree readout. See LPA3806-600BM-G5-24C Rotary Encoder Output

The first thing to do, once the IC removed and the wiring has been corrected, is to verify that counts increment linearly for rotation in one direction and to determine the total counts per revolution for your choice of input edge detection.

2 Likes

How is powered this74ls14 ( it is a long time since last time I used an ls )
vcc is on pin 14 gnd on pin 7
the connection of A to pin 1 is incorrect
also this ic is unnecessary for testing the encoder.

P.S.
Sorry didn't read the chatgpt thing : - ( why not asking also...

1 Like

diagram is wrong. and this IC is useless

2 Likes

The machine does not seem to understand the use of interrupts and where and why to turn interrupts off and on.

1 Like
#define ENCODER_A 2
#define ENCODER_B 3

const int PULSOS_POR_REVOLUCION = 600;  // Ajusta esto según tu encoder
volatile long contadorPulsos = 0;

void setup() {
  // Configura los pines del encoder como entradas (sin pull-up internas)
  pinMode(ENCODER_A, INPUT);
  pinMode(ENCODER_B, INPUT);

  // Inicia la comunicación serie
  Serial.begin(115200);
  Serial.println("Sistema iniciado");

  // Configura las interrupciones para los pines del encoder
  attachInterrupt(digitalPinToInterrupt(ENCODER_A), cambioA, RISING);
}

void loop() {
  noInterrupts();
  long Pulses = contadorPulsos;
  interrupts();
  // Calcula la posición angular actual en grados
  float angulo = (Pulses % PULSOS_POR_REVOLUCION) * 360.0 / PULSOS_POR_REVOLUCION;

  // Asegúrate de que el ángulo esté en el rango [0, 360)
  if (angulo < 0) {
    angulo += 360;
  }

  // Imprime la posición angular actual en el Monitor Serie
  Serial.print("Posición angular: ");
  Serial.print(angulo, 2);  // Imprime con dos decimales
  Serial.println(" grados");

  delay(100);  // Espera 100 ms para una lectura más rápida
}

void cambioA() {
  if (digitalRead(ENCODER_B))contadorPulsos++;
  else contadorPulsos--;
}

If ChatGPT wrote the code, you will need to ask it to fix the code.

3 Likes

Sorry your picture is useless for troubleshooting, Post an annotated schematic. Although I will admit your fuzzy tells me you need to spend a little time with the Arduino Cookbook and some tutorials on rotary encoders and digital ICs.

  • Why have you decide interrupts a necessary ?
    :thinking:
1 Like