Hi. I've been playing with bits of code on this page
http://www.arduino.cc/playground/Main/RotaryEncoders to get my shiny new optical encoder working as a motor controller.
I started with this one
//PIN's definition
#define encoder0PinA 2
#define encoder0PinB 3
volatile int encoder0Pos = 0;
volatile boolean PastA = 0;
volatile boolean PastB = 0;
void setup()
{
pinMode(encoder0PinA, INPUT);
//turn on pullup resistor
//digitalWrite(encoder0PinA, HIGH); //ONLY FOR SOME ENCODER(MAGNETIC)!!!!
pinMode(encoder0PinB, INPUT);
//turn on pullup resistor
//digitalWrite(encoder0PinB, HIGH); //ONLY FOR SOME ENCODER(MAGNETIC)!!!!
PastA = (boolean)digitalRead(encoder0PinA); //initial value of channel A;
PastB = (boolean)digitalRead(encoder0PinB); //and channel B
//To speed up even more, you may define manually the ISRs
// encoder A channel on interrupt 0 (arduino's pin 2)
attachInterrupt(0, doEncoderA, RISING);
// encoder B channel pin on interrupt 1 (arduino's pin 3)
attachInterrupt(1, doEncoderB, CHANGE);
}
void loop()
{
//your staff....ENJOY! :D
}
//you may easily modify the code get quadrature..
//..but be sure this whouldn't let Arduino back!
void doEncoderA()
{
PastB ? encoder0Pos--: encoder0Pos++;
}
void doEncoderB()
{
PastB = !PastB;
}
which worked well apart from the fact that the direction differed every time I used it, and it seemed to depend on which direction it was turned to begin with. This was not acceptable for motor control!
So I'm now looking at this one -
enum PinAssignments {
encoderPinA = 2,
encoderPinB = 3,
clearButton = 8
};
volatile unsigned int encoderPos = 0;
unsigned int lastReportedPos = 1;
boolean A_set = false;
boolean B_set = false;
void setup() {
pinMode(encoderPinA, INPUT);
pinMode(encoderPinB, INPUT);
pinMode(clearButton, INPUT);
digitalWrite(encoderPinA, HIGH); // turn on pullup resistor
digitalWrite(encoderPinB, HIGH); // turn on pullup resistor
digitalWrite(clearButton, HIGH);
// encoder pin on interrupt 0 (pin 2)
attachInterrupt(0, doEncoderA, CHANGE);
// encoder pin on interrupt 1 (pin 3)
attachInterrupt(1, doEncoderB, CHANGE);
Serial.begin(9600);
}
void loop(){
if (lastReportedPos != encoderPos) {
Serial.print("Index:");
Serial.print(encoderPos, DEC);
Serial.println();
lastReportedPos = encoderPos;
}
if (digitalRead(clearButton) == LOW) {
encoderPos = 0;
}
}
// Interrupt on A changing state
void doEncoderA(){
// Test transition
A_set = digitalRead(encoderPinA) == HIGH;
// and adjust counter + if A leads B
encoderPos += (A_set != B_set) ? +1 : -1;
}
// Interrupt on B changing state
void doEncoderB(){
// Test transition
B_set = digitalRead(encoderPinB) == HIGH;
// and adjust counter + if B follows A
encoderPos += (A_set == B_set) ? +1 : -1;
}
Which works well but for one thing, when it counts below zero it goes to 65535 rather than -1 (which I need), and is the way the first example works. Is there a way I can either make the second example count decreasing values below zero as negative numbers, or make the first example count in the same direction every time?
Thanks guys