Hello. I have written a simple sketch using 2 rotary encoders with a switch.
const byte numEnc = 2;
const byte ck[numEnc] = {22, 24};
const byte dt[numEnc] = {23, 25};
const byte sw[numEnc] = {26, 27};
volatile boolean count[numEnc];
volatile boolean lastCount[numEnc];
volatile boolean dir[numEnc];
volatile boolean lastDir[numEnc];
volatile boolean encButt[numEnc];
volatile int ticks[numEnc];
volatile int encPos[numEnc];
void setup()
{
Serial.begin(9600);
DDRA = B00000000; // Set port A to input.
}
void loop()
{
handleEncoder();
}
void handleEncoder()
{
for (int i = 0; i < numEnc; i++)
{
encButt[i] = digitalRead(sw[i]);
count[i] = digitalRead(ck[i]);
dir[i] = digitalRead(dt[i]);
// If encoder switch is pressed. Do high x4 resolution for encoder cycle.
// If encoder switch is not pressed. Do low resolution x1 for encoder cycle.
if(encButt[i] != true)
{
ticks[i] += lowResEnc();
}
else
{
ticks[i] += highResEnc();
}
lastCount[i] = count[i];
lastDir[i] = dir[i];
}
}
// Low reolution....
int lowResEnc()
{
for (int i = 0; i < numEnc; i++)
{
if (count[i] != lastCount[i])
{
if ((count[i] == LOW) && (dir[i] == LOW))
{
encPos[i]++;
Serial.print("encPos ");
Serial.print(encPos[i]);
Serial.print(" ");
Serial.print("count up ");
Serial.println(i);
}
else if ((count[i] == LOW) && (dir[i] == HIGH))
{
encPos[i]--;
Serial.print("encPos ");
Serial.print(encPos[i]);
Serial.print(" ");
Serial.print("count Down ");
Serial.println(i);
}
}
}
}
// High resolution
int highResEnc()
{
for (int i = 0; i < numEnc; i++)
{
if (count[i] != lastCount[i])
{
if ((count[i] == LOW) && (dir[i] == LOW))
{
encPos[i]++;
Serial.print("encPos ");
Serial.print(encPos[i]);
Serial.print(" ");
Serial.print("count up ");
Serial.println(i);
}
else if ((count[i] == LOW) && (dir[i] == HIGH))
{
encPos[i]--;
Serial.print("encPos ");
Serial.print(encPos[i]);
Serial.print(" ");
Serial.print("count Down ");
Serial.println(i);
}
else if ((count[i] == HIGH) && (dir[i] == HIGH))
{
encPos[i]++;
Serial.print("encPos ");
Serial.print(encPos[i]);
Serial.print(" ");
Serial.print("count Up ");
Serial.println(i);
}
else if ((count[i] == HIGH) && (dir[i] == LOW))
{
encPos[i]--;
Serial.print("encPos ");
Serial.print(encPos[i]);
Serial.print(" ");
Serial.print("count Down ");
Serial.println(i);
}
}
}
for (int i = 0; i < numEnc; i++)
{
if (dir[i] != lastDir[i])
{
if ((count[i] == LOW) && (dir[i] == LOW))
{
encPos[i]--;
Serial.print("encPos ");
Serial.print(encPos[i]);
Serial.print(" ");
Serial.print("count Down ");
Serial.println(i);
}
else if ((count[i] == LOW) && (dir[i] == HIGH))
{
encPos[i]++;
Serial.print("encPos ");
Serial.print(encPos[i]);
Serial.print(" ");
Serial.print("count Up ");
Serial.println(i);
}
else if ((count[i] == HIGH) && (dir[i] == HIGH))
{
encPos[i]--;
Serial.print("encPos ");
Serial.print(encPos[i]);
Serial.print(" ");
Serial.print("count Down ");
Serial.println(i);
}
else if ((count[i] == HIGH) && (dir[i] == LOW))
{
encPos[i]++;
Serial.print("encPos ");
Serial.print(encPos[i]);
Serial.print(" ");
Serial.print("count Up ");
Serial.println(i);
}
}
}
}
This works s expected. I turn the encoders without the button pressed they move by one increment each rotary step. If I turn them while the switch is pressed they move by 4 increments per rotary step. I get very sporadic miss reads when I turn the encoders fast so I got rid of the digital reads just to test and wrote this.
const byte numEnc = 2;
const byte ck[numEnc] = {22, 24};
const byte dt[numEnc] = {23, 25};
const byte sw[numEnc] = {26, 27};
volatile boolean count[numEnc];
volatile boolean lastCount[numEnc];
volatile boolean dir[numEnc];
volatile boolean lastDir[numEnc];
volatile boolean encButt[numEnc];
volatile int ticks[numEnc];
volatile int encPos[numEnc];
void setup()
{
Serial.begin(9600);
DDRA = B00000000; // Set port A to input.
}
void loop()
{
handleEncoder();
}
void handleEncoder()
{
int _ReadPort = PINA; // digital read port A.
for (int i = 0; i < numEnc; i++)
{
encButt[0] = _ReadPort & B00010000; // read encoder1 switch (pin 26)
encButt[1] = _ReadPort & B00100000; // read encoder2 switch (pin 27)
count[0] = _ReadPort & B00000001; // read encoder1 ck (pin 22)
count[1] = _ReadPort & B00000100;// read encoder2 ck (pin 24)
dir[0] = _ReadPort & B00000010; // read encoder 1 dt (pin 23)
dir[1] = _ReadPort & B00001000; // read encoder 2 dt (pin25)
// If encoder switch is pressed. Do high x4 resolution for encoder cycle.
// If encoder switch is not pressed. Do low resolution x1 for encoder cycle.
if(encButt[i] != true)
{
ticks[i] += lowResEnc();
}
else
{
ticks[i] += highResEnc();
}
lastCount[i] = count[i];
lastDir[i] = dir[i];
}
}
int lowResEnc()
{
for (int i = 0; i < numEnc; i++)
{
if (count[i] != lastCount[i])
{
if ((count[i] == LOW) && (dir[i] == LOW))
{
encPos[i]++;
Serial.print("encPos ");
Serial.print(encPos[i]);
Serial.print(" ");
Serial.print("count up ");
Serial.println(i);
}
else if ((count[i] == LOW) && (dir[i] == HIGH))
{
encPos[i]--;
Serial.print("encPos ");
Serial.print(encPos[i]);
Serial.print(" ");
Serial.print("count Down ");
Serial.println(i);
}
}
}
}
int highResEnc()
{
for (int i = 0; i < numEnc; i++)
{
if (count[i] != lastCount[i])
{
if ((count[i] == LOW) && (dir[i] == LOW))
{
encPos[i]++;
Serial.print("encPos ");
Serial.print(encPos[i]);
Serial.print(" ");
Serial.print("count up ");
Serial.println(i);
}
else if ((count[i] == LOW) && (dir[i] == HIGH))
{
encPos[i]--;
Serial.print("encPos ");
Serial.print(encPos[i]);
Serial.print(" ");
Serial.print("count Down ");
Serial.println(i);
}
else if ((count[i] == HIGH) && (dir[i] == HIGH))
{
encPos[i]++;
Serial.print("encPos ");
Serial.print(encPos[i]);
Serial.print(" ");
Serial.print("count Up ");
Serial.println(i);
}
else if ((count[i] == HIGH) && (dir[i] == LOW))
{
encPos[i]--;
Serial.print("encPos ");
Serial.print(encPos[i]);
Serial.print(" ");
Serial.print("count Down ");
Serial.println(i);
}
}
}
for (int i = 0; i < numEnc; i++)
{
if (dir[i] != lastDir[i])
{
if ((count[i] == LOW) && (dir[i] == LOW))
{
encPos[i]--;
Serial.print("encPos ");
Serial.print(encPos[i]);
Serial.print(" ");
Serial.print("count Down ");
Serial.println(i);
}
else if ((count[i] == LOW) && (dir[i] == HIGH))
{
encPos[i]++;
Serial.print("encPos ");
Serial.print(encPos[i]);
Serial.print(" ");
Serial.print("count Up ");
Serial.println(i);
}
else if ((count[i] == HIGH) && (dir[i] == HIGH))
{
encPos[i]--;
Serial.print("encPos ");
Serial.print(encPos[i]);
Serial.print(" ");
Serial.print("count Down ");
Serial.println(i);
}
else if ((count[i] == HIGH) && (dir[i] == LOW))
{
encPos[i]++;
Serial.print("encPos ");
Serial.print(encPos[i]);
Serial.print(" ");
Serial.print("count Up ");
Serial.println(i);
}
}
}
}
Now when I turn the 2nd encoder without pressing button it increments by 2 and not 1. The rest works as expected. Why is it doing this? Can somebody help me understand and possibly make this whole thing better.
Thank you in advance.