Hey Guys,
I have been using some optical encoders to gather data from some motors. I was having trouble however, because the encoder count seemed to be gaining and losing value randomly throughout a motor move. I would rotate the motor shaft from 0-90 degrees, and the encoder count (on a 1200 PPR encoder) would be between roughly -6 - 6 at zero degrees, and 286-315 at 90 degrees (where as the actual values are 0, and 300. These are just example ranges of what I was getting, it was always +/- no more than 10ish from the real value.
I have done multiple experiments on my motors (Steppers) and have verified beyond any doubt that they are moving precisely where I ask them to.
I was very frustrated for a long time and even bought quadrature decoder chips (which didn't work out) and thought maybe my signal wires needed debounced. By chance one day I thought maybe it is a problem with my code (which I thought was very unlikely because of how simple the code is) but I copied and pasted an encoder reading program from the internet, and lo and behold it worked. The encoder count was going from 0-300 just as it should.
I get bothered when I don't know why something doesn't work so I was hoping someone would be able to look at the code I was using to tell me why it was randomly gaining/losing encoder counts. I will also include the code that -worked- if it is needed. The encoders have two open collector signal wires, and I was using an arduino due on the native port.
My code:
int PinA = 2;
int PinB = 3;
int counter_2 = 0;
volatile int counter = 0;
char in_char;
unsigned long my_time;
String send, info, tab = "\t";
unsigned long start, stop, elapsed;
int pin_a = 2, pin_b = 3;
void setup()
{
SerialUSB.begin(9600);
pinMode(2, INPUT);
pinMode(3, INPUT);
start = millis();
attachInterrupt(digitalPinToInterrupt(pin_a), Achange, RISING);
attachInterrupt(digitalPinToInterrupt(pin_b), Bchange, RISING);
}
void loop()
{
if (counter != counter_2)
{
noInterrupts();
info = (String)counter;
counter_2 = counter;
interrupts();
stop = millis();
my_time = stop - start;
send = my_time + tab + info;
SerialUSB.println(send);
}
}
void Achange()
{
if (digitalRead(pin_b) == HIGH)
{
counter = counter - 1;
}
else
{
counter = counter + 1;
}
}
void Bchange()
{
if (digitalRead(pin_a) == LOW)
{
counter = counter - 1;
}
else
{
counter = counter + 1;
}
}
Internet code that worked:
double val=0;
byte PinA=6;
byte PinB=7;
int ASet;
int BSet;
void setup()
{
SerialUSB.begin(9600);
pinMode(PinA, INPUT);
pinMode(PinB, INPUT);
ASet = digitalRead(PinA);
BSet = digitalRead(PinB); // read the input pin
attachInterrupt(PinA, INCRE, CHANGE);
attachInterrupt(PinB, DECRE, CHANGE);
}
void loop()
{
int time=millis()/1000;
if(time % 1==0)
{
SerialUSB.print(time);
SerialUSB.print(" \t ");
SerialUSB.println(val);
//val=0;
delay(1000);
}
}
void INCRE()
{
ASet = digitalRead(PinA) == HIGH;
val += (ASet != BSet) ? +1 : -1;
}
void DECRE()
{
BSet = digitalRead(PinB) == HIGH;
val += (ASet == BSet) ? +1 : -1;
}