Irregular reading from encoder with attachInterrupt() and Wemos D1

I need to read an encoder using the interrupt function by the wemos d1 mini board. However, plotting the readings results in an irregular waveform.

So I tested doing the reading without the interrupt function, just with digitalRead, and when plotting, the waveform was as expected.

In my project I can't just use digitalRead because I can lose readings while executing other functions. Any solution to this problem?

Below I attached the waveforms that I obtained in each of the tests, through the Serial Plotter. Also, I attached the circuit.

As you can see, I used a MOC70T3 optical sensor in my circuit, which was connected as recommended by the datashet. At the end of the gearbox shaft, a disc with 30 divisions was used.

Frequency of the waveform is 40hz.

Below is a simplified code that I used to do just these reading tests:

#define motor 4
#define rotary_encoder 14

boolean signal_encoder = 0;

ICACHE_RAM_ATTR void waveForm() {
  signal_encoder = !signal_encoder;
}

void setup() {
  Serial.begin(115200);
  pinMode(rotary_encoder, INPUT_PULLUP);
  pinMode(motor, OUTPUT);
 
 //the line below was uncommented in the firt test
 // attachInterrupt(digitalPinToInterrupt(rotary_encoder), waveForm, CHANGE);
}

void loop() {
  digitalWrite(motor, 1);
 
  //the two lines below were commented while testing interrupt readings
  if(digitalRead(rotary_encoder))signal_encoder=1;
  else signal_encoder = 0;
  
  Serial.println(signal_encoder);
  delay(1);
}

Hi @ctnalves1
You commented out the interrupt line.

Hi alves,

welcome to the arduino-user-forum.

interrupts do what their name says:

interrupting the "normal" code-execution regardless which line of code it will be
executing the interrupt and return to the "normal" code-exection at exact that place the interruption occured.

This means interrupts work "in the backround" in parallel to your code.
If the encoder is connected to the interrupt-pin the change of the signal-level from LOW-to_HIGH or HIGH-to_LOW is enough to start executing the interrupt-code.

Does yur encoder just have a single output or does the encoder have two outputs (the typical A/B-channel quadrature rotary-encoder)

For A/B-channel quadrature rotary-encoder I recommend using the NewEnocder-library. This library works very reliable even with the most bouncy-mechancial rotary-encoders.

Your schematic does not show a rotary-encoder. What is the rotary-enocder used for?
Do you want to have feedback about the motor?
or do you want to use the rotary encoder for user-input?

best regards Stefan

make it volatile

1 Like

also what pins have you connected the encoder to? please post link to the board and connection diagram

In the first test this line was uncommented and the lines with if else were commented out

I used a MOC70T3 optical sensor as encoder (a led in front of a phototransistor, encapsulated). The diagram is in the right part of the image I attached. In the middle of the MOC70T3 was a rotating a disc with 30 divisions. The second wave form I got with digitalRead shows the result as expected.

The question is: why I got regular reading as I showed in the second wave form, but i don't had the same result using attachInterrupt(), as showed in the first wave form, if I used the same pin and the same circuit?

I tried usgin int instead boolean, but the restult was the same irregular reading with attachInterrupt.

The encoder is actualy a MOC70T3 series wired as showed in the right part of the image I attached. The pulses produced for the internal phototransistor is read by the pin 14.

alves,

which kind of code will make it work regular to read all pulses depends on what your application is.

So I have the explicit question:
shall the rotary-encoder detect the rotations of the motor? Yes or no?

What is the maximum rpm that the motor will have?
answer with a number

best regards Stefan

Hi Stefan.

Yes, the rotary encoder detects rotations of the motor.

maximum velocity is 80RPM

According to the data sheet it is called opto interrupter, and it is very different from rotary encoder.

does it create one pulse LOW-HIGH-LOW per rotation of the motor?

No .

@ctnalves1
tips how to improve your posting style

@killzone_kid advised you to make that variable volatile.

Have you?

 volatile boolean signal_encoder;

Google it

volatile variables in C++

It keeps the compiler from making changes that it thinks won't matter, but you know better that they wou,d.

a7