I've recovered from a PS/2 Mose some optical encoders that i intend to use on a continuous servo to get the position
The servo maxim speed is 375deg/s @ 6V and the encoder wheel has 34 slots in it.
In my case the direction of the movement is known (commanded by arduino) i need to know the position (by counting the slots in the encoder wheel) and if it is moving or not.
How can i improve the accuracy (lets say 1deg) by using the interrupts on both pins?
How can i know if is moving or not ?
I suppose that in my case i have to get also the direction of movement in order to compensate HoldPosition and to improve accuracy
Any advice? Thank you
Here is the code i got so far
// Read a optical rotary encoder from a PS/2 mouse with interrupts
// Encoder Sensor hooked up with common to 5V,
// myPinA to pin 2, myPinB to pin 3
// uses Arduino pullups on A & B channel outputs
// turning on the pullups saves having to hook up resistors
// to the A & B channel outputs
// each channel has a 0.1nF to the ground
//Maximum servo speed is 375deg/s
//Encoder wheel has 34 slots (cuts) in it
#define myPinA 2 //Channel A on interrupt 0
#define myPinB 3 //Channel B on interrupt 1
#define myPinP 4 //Power to the sensor
volatile int Pos = 0;
void setup()
{
//in this case myPinX is the same as Bit
DDRD &= ~(1 << myPinA);//Set pin 2 as input
DDRD &= ~(1 << myPinB);//Set pin 3 as input
DDRD |= (1 << myPinP);//Set pin 4 as output
PORTD |= B00011100;//Turn On 20KOhm resistors on 2,3,4 (HIGH)
attachInterrupt(0, Update, CHANGE);// encoder pin on interrupt 0 - pin 2
Serial.begin (115200);
Serial.println("start");
}
void loop(){
Serial.println(Pos, DEC);// debug - remember to comment out
}
void Update()
{
//if (bitRead(PINB, myPinA) && bitRead(PINB, myPinB))
if (!(bitRead(PINB, myPinA) ^ bitRead(PINB, myPinB)))
Pos++;
else
Pos--;
//I know command the direction
// if (bitRead(PINB, myPinA))// found a low-to-high on channel A
// {
// if (!bitRead(PINB, myPinB))// check channel B to see which way
// Pos = Pos - 1; // CCW
// else
// Pos = Pos + 1; // CW
// }
// else// found a high-to-low on channel A
// {
// if (!bitRead(PINB, myPinB))// check channel B to see which way
// Pos = Pos + 1;// CW
// else
// Pos = Pos - 1;// CCW
// }
}
I just realize that the servo is connected to a worm gear 1:40 so a resolution of 5 deg will be just fine so i need to double it by using interrupts on both channels but i don't know how.
I forgot to mention that i need this kind of measuring for two servos ( X and Y direction) an it is preferable to do it from soft.
I assume you aren't wanting to use the PS2 library, which requires 2 digital inputs from the PS2 mouse and returns x,y encoder rotation (CW and CCW) data as well as button clicks... I have just used this with great success!
I did try something similar (it returns X,Y,Z from -127 to 127 speed + three buttons) but i only need the count
Here is a bit modified code that i will test it tonight to see if is working.
I also want to test witch of the following statements are faster
if (!(bitRead(PINB, myPinA1) ^ bitRead(PINB, myPinB1)))
or
if (!((PIND & 0b00000100) ^ (PIND & 0b00010000)))
// Read a optical rotary encoder from a PS/2 mouse with interrupts
// Encoder Sensor hooked up with common to 5V,
// myPinA to pin 2, myPinB to pin 3
// uses Arduino pullups on A & B channel outputs
// turning on the pullups saves having to hook up resistors
// to the A & B channel outputs
// each channel has a 0.1nF to the ground
//Maximum servo speed is 375deg/s
//Encoder wheel has 34 slots (cuts) in it
#define myPinA1 2 //Channel A1 on interrupt 0
#define myPinA2 3 //Channel A2 on interrupt 1
#define myPinB1 4 //Channel B1
#define myPinB2 5 //Channel B2
#define myPinP 6 //Power to the sensor
volatile int PosA = 0;
volatile int PosB = 0;
void setup()
{
//in this case myPinX is the same as Bit
DDRD &= ~(1 << myPinA1);//Set pin 2 as input
DDRD &= ~(1 << myPinA2);//Set pin 3 as input
DDRD &= ~(1 << myPinB1);//Set pin 4 as input
DDRD &= ~(1 << myPinB2);//Set pin 5 as input
DDRD |= (1 << myPinP);//Set pin 6 as output
PORTD |= B01111100;//Turn On 20KOhm resistors on 2,3,4,5,6 (HIGH)
attachInterrupt(0, UpdateA, CHANGE);// encoder pin on interrupt 0 - pin 2
attachInterrupt(1, UpdateB, CHANGE);// encoder pin on interrupt 1 - pin 3
Serial.begin (115200);
Serial.println("start");
}
void loop()
{
Serial.println(PosA, DEC);// debug - remember to comment out
Serial.println(PosB, DEC);// debug - remember to comment out
}
void UpdateA()
{
//if (!(bitRead(PINB, myPinA1) ^ bitRead(PINB, myPinB1)))
if (!((PIND & 0b00000100) ^ (PIND & 0b00010000)))
PosA++;
else
PosA--;
}
void UpdateB()
{
//if (!(bitRead(PINB, myPinA2) ^ bitRead(PINB, myPinB2)))
if (!((PIND & 0b00001000) ^ (PIND & 0b00100000)))
PosB++;
else
PosB--;
}