(still) unable to read an encoder

Hi,

After thinking about a good code I "came up" with the following code:

#define encoder0PinA 2 

volatile int val = 0;
volatile int PinB = 3;

void setup()
{ 
  pinMode(encoder0PinA, INPUT);
  pinMode(PinB, INPUT); 
  attachInterrupt(0, doEncoderA, CHANGE);  // encoder pin on interrupt 0 (pin 2) 
  Serial.begin (9600);
  Serial.print("Encoderpositie = ");
  Serial.println(val);
} 

void loop()
{
//Do stuff here
} 

void doEncoderA()
{ 
  if ((encoder0PinA == HIGH) && (PinB == LOW))
    {
      val = val + 1;
    }
  else
    {
      if ((encoder0PinA == HIGH) && (PinB == HIGH))
        {
          val = val - 1;
        }
      else
        {
          if ((encoder0PinA == LOW) && (PinB == HIGH))
            {
              val = val + 1;
            }
          else
            {
              if ((encoder0PinA == LOW) && (PinB == LOW))
              {
              val = val -1;
              }
            }}}
Serial.print("Encoderpositie = ");            
Serial.println(val);          
}

I now think this isn't such a good code after all.

This is what happens:

After rotating for a short while the uC crashes and stalls.

This is the setup I use. I'm using a stock rotary encoder. The resistors are pull down resistors.

2 problems so far

  1. the code stalls
  2. as long/short as the code is working no adding or subtraction

In my mind the code should be ok?

What am I missing?

Leo

  if ((encoder0PinA == HIGH) && (PinB == LOW))

encoder0PinA and PinB are pin numbers, they don't represent the state of the pins; you need digitalRead.

Serial print commands shouldn't be in your interrupt routine - move them to loop.

Ok, thanks.

I have changed the code and the code doesn't stall anymore.
I also receive different numbers now instead of only zero's.

#define encoder0PinA 2 

volatile int val = 0;
volatile int PinB = 3;
volatile int valA;
volatile int valB;
int valold;

void setup()
{ 
  pinMode(encoder0PinA, INPUT);
  pinMode(PinB, INPUT);
  digitalWrite(encoder0PinA, HIGH);
  digitalWrite(PinB, HIGH); 
  attachInterrupt(0, doEncoderA, CHANGE);  // encoder pin on interrupt 0 (pin 2) 
  Serial.begin (9600);
  Serial.print("Encoderpositie = ");
  Serial.println(val);
  valold = val;
} 

void loop()
{
if (valold != val)
  {
    Serial.print("Encoderpositie = ");            
    Serial.println(val);
    valold = val;   
  } 
}

void doEncoderA()
{ 
valA = digitalRead(encoder0PinA);
valB = digitalRead(PinB);
  if ((valA == HIGH) && (valB == LOW))
    {
      val = val + 1;
    }
  else
    {
      if ((valA == HIGH) && (valB == HIGH))
        {
          val = val - 1;
        }
      else
        {
          if ((valA == LOW) && (valB == HIGH))
            {
              val = val + 1;
            }
          else
            {
              if ((valA == LOW) && (valB == LOW))
              {
              val = val -1;
              }
            }}}   
}

But the numbers are erratic. The trends seem to be ok (overall rising or falling numbers) but not every step gives the same difference. The differences can be really high (higher then some missed values by the serial monitor). Sometimes the trend can even shortly reverse while rotating in one direction???

Why is it so hard to read an encoder?

EDIT:
I have added two 0,1 uF capacitors between the A and B and ground and it seems to be a bit better now. (maybe it's only better in my mind but I have a feeling it really is a bit better now) Maybe the erratic behaviour is caused by bouncing?

For a phototransistor output encoder you have to provide the right
value of pull up resistor, the built-in pullups may be too high.

You might need schmidt-triggers to cleanup the signals too.

An oscilloscope would help a lot, but static readings with a mutimeter
may be useful too.

Post a schematic of your wiring with labels for the pins.

This is how the setup is made.

Have you tried reading this ?
http://playground.arduino.cc/Main/RotaryEncoders