Potentiometers are the easiest way to get an analog value into the Arduino. Nice for e.g. volume control or setting the speed of a fan or the brightness of a lamp.
A more digital way is to use rotary encoder instead which return pulses or even absolute positions. I found one here and it works as expected. Without using interrupts I was able to decode it just fine, but this really should be done via interrupts, but I never used interrupts before, so I checked via Google and found this. Works well and does not need a polling loop. The rotary encoder even looks identical to the one I bought.
For reference here the short test program:
/** * A simple incremental Rotary Encoder decoder example * [email protected] * http://www.rocketnumbernine.com/2010/03/06/decoding-a-rotary-encoder/ * use freely */ #include <util/delay.h> volatile uint8_t pinValues[2] = {0,0}; volatile int position = 0; const int APin=2; const int BPin=3; void setup() { Serial.begin(38400); pinMode(APin, INPUT); // 2 Encoder pins as inputs pinMode(BPin, INPUT); digitalWrite(APin, HIGH); // use internal pull-ups digitalWrite(BPin, HIGH); // enable interrupts on those two pins: // Depends on APin=2 and BPin=3 PCICR |= (1 << PCIE2); PCMSK2 |= (1 << PCINT18) | (1 << PCINT19); sei(); } ISR(PCINT2_vect) { _delay_ms(1); int pin0 = digitalRead(APin); int pin1 = digitalRead(BPin); if (pin0 != pinValues[0]) { rotary_encoder_change(0, pin0); } else if (pin1 != pinValues[1]) { rotary_encoder_change(1, pin1); } } void rotary_encoder_change(uint8_t changedPin, uint8_t value) { pinValues[changedPin] = value; position += ((pinValues[0] == pinValues[1]) ^ changedPin) ? 1 : -1; } void loop() { Serial.println(position); delay(200); }
Small addition: Arduino Playground has some more info.