How to read encoder speed through an interrupt with an Arduino based PLC’s

# How to read encoder speed through an interrupt with an Arduino based PLC’s

In this post it is showed how to read the speed of an encoder with an Arduino based PLC’s.

The requirements for this example are:

• Encoder
• One of our PLC’s
• 2 resistors of 4k7

In this example we have used an E6B2-C OMRON encoder and an M-Duino 21 I/O’s How to connect the devices?

The power supply of the E6B2-C OMRON encoder is between 5V to 24V, we used the 7V from the M-Duino to power supply the encoder. The two resistors are connected, as a Pull-up configuration, between the two phases to the 7V of the M-Duino. And the two phases are connected to I0.4 (phase B) and I0.5 (phase A). And all the GND are connected to the M-Duino GND.

Once all is connected we can proceed to programming the M-Duino. Remember that the encoder convert revolutions to pulses.

How to read these pulses? How to know the rotate direction?

On this example we use an external interrupt to know when the encoder is rotating. The phase A is connected to the interrupt 0 (I0.5). The interrupt will be configured to active when it appears a rising edge on I0.5. Every rising edge on the phase A will indicate us that the encoder is rotating (one pulse). But to know rotate direction we have to read if value of the phase B is low or high. If the rotate direction is forward (CW; phase B = LOW) and if the rotate direction is going backward (CCW; phase B = HIGH). Next it is showed a signal to get a better understanding of that. Counting pulses through an external interrupt is the best option, because you get sure that you do not lose any pulse while the microcontroller is executing other code.

With every interrupt we add pulses (pulses++) if the encoder is rotating forward and we subtract pulses if the encoder is rotating backward. Once we have the pulses counting on the right way we just need to know the time to be able to convert these pulses to a speed value. To know the time while we are getting  pulses we will use two variables, one for initial time (time0) and other to final time (timeF). Using the function micros() (also you can use millis() function) we will set the two values to implement our equation.

The E6B2-C OMRON encoder that is used on this example has a resolution of 500 pulses for revolution. So, our equation will be:

Speed = (pulses/500)   /   ( (timeF-timeO)/60000000 )   rev/min

In this example we display the speed of the encoder on serial monitor. To display it you have to introduce a “p” of print through the serial monitor.

IMPORTANT: remember, the interrupt has to be as fast as possible, if not you can get some Aliasing!

To add more information of the functions that are used on this code take a look on the Arduino Reference: millis(), micros(), attachInterrupt(), detachInterrupt()

Next it is showed how to convert this to code on Arduino IDE:

```const int phaseB = I0_4;
const int phaseA = I0_5;
int valuePhaseB = 0;
volatile long pulses = 0;
unsigned long timeO = 0;
unsigned long timeF = 0;
float encoderSpeed = 0;

void setup() {
Serial.begin(9600);
pinMode(phaseA, INPUT);   // configure the I.0 as a INPUTS
pinMode(phaseB, INPUT);
attachInterrupt(digitalPinToInterrupt(phaseA), detectPulses, RISING);    // enable external interrupt with a rising edge of PhaseA
timeO = micros();   // Initialize initial time
}

void loop() {
if (Serial.available() && Serial.read() == 'p') {
timeF = micros();     // Geting the final time to get the speed
encoderSpeed = ((float)pulses/500.0) / ((float)(timeF - timeO) / (60000000.0));
Serial.print("Speed: ");
Serial.print(encoderSpeed);     // Printing speed value
Serial.println(" rev/min");
pulses = 0;    // Initialize pulses to count again
timeO = micros();    // Initialize initial time again
}
}

void detectPulses() {
if (digitalRead(phaseB) == LOW) { //Confirm if we are turning on CW direction.
}
else { //Confirm if we are turning on CCW direction.
pulses--;    // Substraing pulses
}
}

```