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