Angular Velocity from Rotary Encoder

Hey Guys,

i'm pretty new to Arduino (i'm using an Arduino Mega2560) and want to get an Angular Velocity out of a Rotary Encoder (HEDL-5640#A13).
So far im Using this Code to get the Angle:

int outputA = 53;
int outputB = 49;
int counter = 0;
int angle;
int aState;
int aLastState;

void setup() {
pinMode (outputA,INPUT);
pinMode (outputB,INPUT);

Serial.begin (250000);
// Reads the initial state of the outputA
aLastState = digitalRead(outputA);
}

void loop() {
aState = digitalRead(outputA); // Reads the "current" state of the outputA
// If the previous and the current state of the outputA are different, that means a Pulse has occured
if (aState != aLastState){
// If the outputB state is different to the outputA state, that means the encoder is rotating clockwise
if (digitalRead(outputB) != aState) {
counter ++;
} else {
counter --;
}
if (counter >=1000 || counter <=-1000){
counter = 0;
}

Serial.print("Time: ");
Serial.print(millis());
Serial.print(" : ");
Serial.print("Position: ");
Serial.print(counter);
Serial.print(" / ");
angle = ((counter*360)/1000);
Serial.print("Angle: ");
Serial.println(angle);

}
aLastState = aState; // Updates the previous state of the outputA with the current state
}

I tried to grab the time with millis() each time the encoder changes the counter but it doesn't seem so work out. So i thought i maybe could use a fixed time window and go over the difference between the counters, but i have no idea how to do it or if it's even possible without slowing the rest of my code down (i also have a ultra sonic sensor, and some manual inputs via switches). My attempt currently looks like this:

int outputA = 53;
int outputB = 49;
int counter = 0;
long timeA;
long timeB;
int timeDiff;
int angle;
float angleV;
int aState;
int aLastState;

void setup() {
pinMode (outputA,INPUT);
pinMode (outputB,INPUT);

Serial.begin (250000);
// Reads the initial state of the outputA
aLastState = digitalRead(outputA);
}

void loop() {
aState = digitalRead(outputA); // Reads the "current" state of the outputA
// If the previous and the current state of the outputA are different, that means a Pulse has occured

if (aState != aLastState){
// If the outputB state is different to the outputA state, that means the encoder is rotating clockwise
if (digitalRead(outputB) != aState) {
counter ++;
timeB = millis();
} else {
counter --;
timeB = millis();
}
if (counter >=1000 || counter <=-1000){
counter = 0;
}

Serial.print("Time: ");
Serial.print(millis());
Serial.print(" : ");
Serial.print("Position: ");
Serial.print(counter);
Serial.print(" / ");
angle = ((counter*360)/1000);
Serial.print("Angle: ");
Serial.print(angle);
Serial.print(" / ");
Serial.print("Time A: ");
Serial.print(timeA);
Serial.print(" / ");
Serial.print("Time B: ");
Serial.print(timeB);
Serial.print(" / ");
Serial.print("Angle-Velocity: ");
timeDiff = (timeB - timeA);
angleV = 0.36/timeDiff;
Serial.println(angleV);

timeA = millis();

}
aLastState = aState; // Updates the previous state of the outputA with the current state
}

which results in a Serial monitor looking something like this:

...
Time: 76914 : Position: 65 / Angle: 23 / Time A: 76913 / Time B: 76914 / Angle-Velocity: 0.36
Time: 76917 : Position: 64 / Angle: 23 / Time A: 76916 / Time B: 76917 / Angle-Velocity: 0.36
Time: 76920 : Position: 63 / Angle: 22 / Time A: 76920 / Time B: 76920 / Angle-Velocity: inf
Time: 76924 : Position: 62 / Angle: 22 / Time A: 76924 / Time B: 76924 / Angle-Velocity: inf
Time: 76928 : Position: 61 / Angle: 21 / Time A: 76928 / Time B: 76928 / Angle-Velocity: inf
Time: 76932 : Position: 60 / Angle: 21 / Time A: 76932 / Time B: 76932 / Angle-Velocity: inf
Time: 76936 : Position: 59 / Angle: 21 / Time A: 76936 / Time B: 76936 / Angle-Velocity: inf
Time: 76940 : Position: 58 / Angle: 20 / Time A: 76939 / Time B: 76939 / Angle-Velocity: inf
Time: 76943 : Position: 57 / Angle: 20 / Time A: 76943 / Time B: 76943 / Angle-Velocity: inf
Time: 76947 : Position: 56 / Angle: 20 / Time A: 76947 / Time B: 76947 / Angle-Velocity: inf
Time: 76951 : Position: 55 / Angle: 19 / Time A: 76950 / Time B: 76950 / Angle-Velocity: inf
Time: 76954 : Position: 54 / Angle: 19 / Time A: 76954 / Time B: 76954 / Angle-Velocity: inf
Time: 76958 : Position: 53 / Angle: 19 / Time A: 76958 / Time B: 76958 / Angle-Velocity: inf
Time: 76962 : Position: 52 / Angle: 18 / Time A: 76961 / Time B: 76961 / Angle-Velocity: inf
Time: 76966 : Position: 51 / Angle: 18 / Time A: 76965 / Time B: 76965 / Angle-Velocity: inf
Time: 76971 : Position: 50 / Angle: 18 / Time A: 76969 / Time B: 76971 / Angle-Velocity: 0.18
Time: 76975 : Position: 49 / Angle: 17 / Time A: 76973 / Time B: 76975 / Angle-Velocity: 0.18
Time: 76979 : Position: 48 / Angle: 17 / Time A: 76977 / Time B: 76979 / Angle-Velocity: 0.18
Time: 76984 : Position: 47 / Angle: 16 / Time A: 76981 / Time B: 76984 / Angle-Velocity: 0.12
Time: 76988 : Position: 46 / Angle: 16 / Time A: 76986 / Time B: 76988 / Angle-Velocity: 0.18
Time: 76993 : Position: 45 / Angle: 16 / Time A: 76990 / Time B: 76993 / Angle-Velocity: 0.12
Time: 76998 : Position: 44 / Angle: 15 / Time A: 76995 / Time B: 76998 / Angle-Velocity: 0.12
Time: 77003 : Position: 43 / Angle: 15 / Time A: 77000 / Time B: 77003 / Angle-Velocity: 0.12
Time: 77008 : Position: 42 / Angle: 15 / Time A: 77005 / Time B: 77008 / Angle-Velocity: 0.12
Time: 77014 : Position: 41 / Angle: 14 / Time A: 77010 / Time B: 77014 / Angle-Velocity: 0.09
Time: 77020 : Position: 40 / Angle: 14 / Time A: 77017 / Time B: 77020 / Angle-Velocity: 0.12
...

I'm also open for a completely different approach - mine doesn't seem very efficient.

Kind regards,
Max

When measuring the time between encoder steps, try micros() (microseconds) instead of millis() (milliseconds). There is a much higher chance that more than one will pass between encoder steps.