Explanation of Quadrature with Arduino

advertisement
Quadrature
Amanda Innis
For Dr. David Grow
March 19, 2013
New Mexico Technical Institute of Mining and Technology
The optical encoder used for the code development in this document contained Pin’s A and B as
well as an index pin. The A and B pins was used in this setting to indicate the direction the
rotation of a lever arm was occurring. The encoder has the B windows offset from the A
windows in order to achieve an indication of direction (Figure 1). The index pin is used in the
encoder to give relative position and has only one window in the device. In order to read the
position and direction quadrature code for the Arduino Board was developed.
Figure 1: The figure above shows the window offset for the optical encoder.
The start of the quadrature code development began with going to the Arduino website [1] in
order to find base code from which to build. The base code can be found in the appendix. This
code from the site had a setup for counter-clockwise and clockwise directions. However, the
initial code was not setup to increment in degrees for each counter-clockwise or clockwise
movement. The code also did not include index pin code to set a relative position.
The first issue addressed was to program the code to increment in degrees. On the encoder as
part of a string of digits a 3000 was seen and supposed as the counts per revolution (cpr). This
idea was confirmed by checking the data sheet of the model. Then, to calculate the degrees each
window represents, 360 degrees was divided by 3000 (the cpr). The result of this calculation was
0.12 degrees per window. The basic code was changes such that the count was no longer plus
1
one or minus one but rather plus 0.12 and minus 0.12. An example of this line of code is shown
below, where encoder0Pos is the current position of the lever arm.
encoder0Pos=encoder0Pos-0.12;
After this code was implemented, a new issue was discovered. As the lever for the optical
encoder was moved at a higher velocity, the degree position lost accuracy. After trial and error
this was fixed by increasing the baud rate in the code and on the serial monitor to 115200. It was
determined that this rate was suitable for the device application. If further accuracy is required in
the future, recording data to an SD card is will provide the necessary speed.
The next issue of relative position was addressed. A new pin for the index window was initiated
in the code as a new variable. The code was setup such that if the position pin read “High,”
which means the index window can be seen, then the position of the lever arm was set to zero.
The particular code for this setup is shown below.
if(digitalRead(encoder0PosPin) == HIGH){
encoder0Pos=0;
}
Initially after testing, the position did not reset to zero at any point along the trajectory and thus
was not hitting the index pin. For this project, the lever arm was only moving through
approximately 200 degrees of the encoder. The degree restriction and code error, in this case,
meant that the index window was in the other 160 degrees of the encoder. To fix this issue, the
set screws were loosened and the optical encoder sleeve was rotated with the code running. Once
the code indicated the position was reset to zero along the lever arm trajectory, the index window
was found and the set screws were re-tightened.
After some issues along the way the necessary code was created. The base code was found, and
the position was changed to degrees. In addition, the index pin was used to have the code output
a relative position instead of a generic position. With the combination of these two components a
complete quadrature code was developed for the optical encoder. The final code can be seen in
the appendix.
2
Reference
[1] Arduino Playground. Accessed March 19, 2013
http://playground.arduino.cc/Main/RotaryEncoders
3
Appendix
Original Base Code
int val;
int encoder0PinA = 3; //Encoder Pin A
int encoder0PinB = 4;
int encoder0Pos = 0;
int encoder0PinALast = LOW;
int n = LOW;
void setup() {
pinMode (encoder0PinA,INPUT);
pinMode (encoder0PinB,INPUT);
Serial.begin (9600);
}
//initialize corresponding pin on arduino
//capture rate for data
void loop() {
n = digitalRead(encoder0PinA);
if ((encoder0PinALast == LOW) && (n == HIGH)){
if (digitalRead(encoder0PinB) == LOW) {
encoder0Pos--;
} else {
encoder0Pos++;
}
Serial.print (encoder0Pos);
Serial.print ("/");
}
encoder0PinALast = n;
}
//HIGH=light shines through
// minus one to the position count
//Prints generic position
Modified Final Quadrature
int val;
int encoder0PinA = 13;
int encoder0PinB = 12;
int encoder0PosPin = 11;
float encoder0Pos = 0;
int encoder0PinALast = LOW;
int n = LOW;
void setup() {
pinMode (encoder0PinA,INPUT);
pinMode (encoder0PinB,INPUT);
pinMode (encoder0PosPin,INPUT);
Serial.begin (115200);
//pin A attached connected to pin 13 on Arduino
//holds position value
//initialize pin
//added position pin
//speed
4
}
void loop() {
n = digitalRead(encoder0PinA);
if(digitalRead(encoder0PosPin) == HIGH){
encoder0Pos=0;
}
//Relative Position
if ((encoder0PinALast == LOW) && (n == HIGH)) {
if (digitalRead(encoder0PinB) == LOW) {
encoder0Pos=encoder0Pos-0.12;
} else {
encoder0Pos=encoder0Pos+0.12;
}
Serial.print (encoder0Pos);
Serial.print ("/");
//subtracts from position in degrees per window
//if can't see A and can see B
//prints position
}
encoder0PinALast = n;
}
5
Download