Shaft encoders

Hi,
i am new to Arduino and i am using it [Arduino ATMega 1280] for my project. i have a problem regarding rotary AB shaft encoding. i am using the below code and i am sure that i am missing some counts from the encoder :L can some one help me to either make this code more efficient or help me in developing other code... the encoding part is done in "void doEncoderA()"... thanks in advance. GXerri.

#define encoderXPinA 19
#define LED 13
int stopm01x = 22,stopm02y = 23,stopm03z = 24,stopm04 = 25,lock = 50;
//outputs
int m1a = 40,m1b = 41,m2a = 42,m2b = 43,m3a = 44,m3b = 45,m4a = 46,m4b = 47,posbx = 30, posby = 31, posbz = 32, posbr = 33;
int m1=40,m2=42,m3=44,m4=46;
int check,check1,message = 0;
unsigned int ZPos = 0, ZPosB = 0, x = 0, y = 0, a=0,b=0;

void setup()
{
attachInterrupt(0, intt, HIGH); //pin 2
// encoder pin on interrupt 4 (pin 19)
attachInterrupt(4, doEncoderA, CHANGE);

//outputs
pinMode(m1a, OUTPUT); //output motor 1 bit A and B
pinMode(m1b, OUTPUT); //
pinMode(m2a, OUTPUT); //output motor 2 bit A and B
pinMode(m2b, OUTPUT); //
pinMode(m3a, OUTPUT); //output motor 3 bit A and B
pinMode(m3b, OUTPUT); //
pinMode(m4a, OUTPUT); //output motor 4 bit A and B
pinMode(m4b, OUTPUT); //
pinMode(lock,OUTPUT);
//inputs
pinMode(stopm01x, INPUT);
pinMode(stopm01x, INPUT);
pinMode(stopm02y, INPUT);
pinMode(stopm03z, INPUT);
pinMode(stopm04, INPUT);
pinMode(posby, INPUT);

Serial.begin(9600);
}

void loop()
{
free(m1),free(m2),free(m3),free(m4); // free all motors
do //home motor 3
{
digitalWrite(lock, HIGH);
rev(m3); //m3 goes reverse
check=digitalRead(stopm03z); //check sensor
}
while (check == HIGH); // to be used with present sensor
digitalWrite(lock, LOW);
free(m3); //free
delay(500);
ZPos=0;
for (int z=0; z<2; z++)
{
do
{
digitalWrite(lock, HIGH);
fwd(m3); //m3 goes forward
}
while (ZPos != 45);

digitalWrite(lock, LOW);
free(m3);//free
delay(1000);

do
{
digitalWrite(lock, HIGH);
rev(m3);
}
while (ZPos != 11);
digitalWrite(lock, LOW);
free(m3); //free
delay(3000);
}
}

void doEncoderA()
{
a++;
// look for a low-to-high on channel A
if (a==50)
{
if (digitalRead(encoderXPinA) == HIGH)
{
// check channel B to see which way encoder is turning
if (digitalRead(posbz) == LOW)
{ZPos = ZPos - 1;} // CCW
else {ZPos = ZPos + 1;} // CW
}
else // must be a high-to-low edge on channel A
{
// check channel B to see which way encoder is turning
if (digitalRead(posbz) == HIGH) {ZPos = ZPos - 1;} // CCW
else {ZPos = ZPos + 1;} // CW
}
Serial.print("ZPos= ");
Serial.println (ZPos, DEC);
// use for debugging - remember to comment out
a=0;
}
}

void intt()
{
digitalWrite(lock,LOW);
brk(m1),brk(m2),brk(m3),brk(m4); //break all motors
delay(500);
free(m1),free(m2),free(m3),free(m4); // free all motors
delay(100);

Serial.println("i"); // "i\r" in C#
delay(100);
do
{
digitalWrite(13,LOW); //show interrupt on led
delay(10000); //
digitalWrite(13,HIGH); //
delay(10000); //
check = digitalRead(3);
check1= digitalRead(2);
}
while((check1 == HIGH)||(check == LOW)); //block here
// while((check1 == HIGH));
digitalWrite(13,LOW);

Serial.println("r"); // "r\r" in C#
// message = 's'; //this iu used to stop homing when the doors are opened
digitalWrite(lock,HIGH);
delay(100);
}

void rev(int M)
{
digitalWrite(M,HIGH); //M rev
digitalWrite(M+1,LOW); //
}
void fwd(int M)
{
digitalWrite(M,LOW); //M forward
digitalWrite(M+1,HIGH); //
}
void brk(int M)
{
digitalWrite(M,LOW); //break
digitalWrite(M+1,LOW); //
}
void free(int M)
{
digitalWrite(M,HIGH); //free
digitalWrite(M+1,HIGH); //
}

[ don't forget to use the code tags (# button) ]

Your code doesn't make sense - you increment a until it reaches 50 - this deliberately misses transistions. You have to record the step direction on every transition - the shaft can backstep at any time (even if the motor is turning one way, the encoder can have jitter/noise/vibration, only the combined state of A and B can disambiguate this from real steps)

first of all thanks for your reply :smiley:
secondly i am incrementing a up to 50 and then resets it back to 0
i am using this sort of dividing [sampling] the number of pulses the encoder is giving me cos it is giving me loads of pulses...
but even without that variable 'a' i am missing counts...

any idea how i can improve my code?? :L

Thanks.
GScerri.

Ah, you have calls to Serial.print in an interrupt handler? That's definitely not going to help. you might be in the handler for many milliseconds.

yes i am using that Serial.print for debugging (to know the position of the shaft at a moment), and i think it is the problem :L
ill try it without the Serial.print and let you know the outcome...

Thanks:)