ECE 381 Lab 3 –Interrupts and Optical Encoders Understanding Optical Encoders An optical encoder is a type of rotary encoder (also known as a shaft encoder) that converts the angular position of a shaft to a digital code. Rather than using electro-mechanical contacts to indicate the shaft position, it shines the light from an LED onto a slotted disk. On the opposite side of the disk is a photo sensor (usually a phototransistor) that turns on when the light from the LED is shining through one of the slots on the disk. The signal from the phototransistor is then conditioned into logic voltages suitable for the particular application. If only one optical sensor is used, the encoder is suitable as a tachometer or position sensors in applications where the shaft turns in only one direction. See Figure 1 for an illustration. Figure 1 – Optical tachometer [1] If an application requires sensing the rotation of the shaft in both the clockwise (CW) and counterclockwise (CCW) directions, at least two optical sensors are required. Encoders of this type are referred to as quadrature encoders since they give 2-bits (22 = 4 or quad) of information about the shaft position. These two optical channels produce digital signals that are phased 90-degrees apart. When looked at as bit pairs, they form a 2-bit Gray code, meaning that only one bit changes at a time (e.g. 00, 01, 11, 10, 00, 01, …). This is essential to prevent a race condition for the device interfaced to the optical sensor. For example, suppose the optical sensors changed from 11 to 00. Since both channels cannot simultaneously go low, the device interfaced to it could ambiguously read this as (11, 01, 00) or (11, 10, 00). Error! Reference source not found. shows the quadrature digital output signals of the Bourns optical encoder we will use in this lab. The signals are shown with the encoder shaft rotating in the clockwise direction. Optical Encoder Applications Because they provide information about the direction, position, and velocity of a rotating shaft, optical encoders are used in many applications requiring feedback about motor driven systems, with robotics being a prominent area. Another common application for optical encoders is in user interfaces. When given a knob and some push button, they allow a user to select among a list of options in a menu. Since they only report relative position and not absolute position (like a potentiometer), they allow an application to start from Figure 2: Quadrature signals [2] ECE 381 Lab 3 –Interrupts and Optical Encoders a reasonable set of defaults. Part 1 – Basic GPIO Interrupts Objective Configure the PSoC to interrupt on one of the GPIO pins and toggle an LED at each interrupt. Configuration Configure Port1[0] to be an output with STRONG drive mode that connects to LED1 on the evaluation board. Name the port “LED1”. Connect the PSoC Evaluation Board switch to Port1[4] as shown in the figure at the right . Configure Port1[4] as follows: o Name: SWITCH o Drive: HIGH Z o Interrupt: RisingEdge Software Figure 3: Simple interrupt testing schematic. After setting the configuration parameters from above, browse to your project folder in Windows Explorer. o If your project happens to be named “interrupt” then look for the file interrupt\interrupt\boot.tpl and open it in a text editor. This is the template that PSoC Designer uses to generate boot.asm. o Locate the address in the Interrupt Vector Table corresponding to GPIO interrupts. o Replace `@INTERRUPT_#` with ljmp _PSoC_GPIO_ISR_C. o Save, close and return to PSoC Designer. Edit main.c and add the code on the following page. Build the project and program the PSoC Test the project on the PSoC for proper operation. Each time the switch is pressed, the LED should toggle state. Something to look for: You will probably notice that the LED occasionally toggles erratically. Sometimes it will go on/off as expected and other times it will flicker on/off briefly or even a few times. This is NOT due to an error in the program. It is because the switch, as a mechanical device, does not make a clean on and off contact when it is pressed or released. When captured on an oscilloscope, multiple transitions can be seen. This phenomenon is called bouncing and is present with almost all mechanical switches. The solution is switch debouncing (to be discussed at a future date) ECE 381 Lab 3 –Interrupts and Optical Encoders //---------------------------------------------------------------------------// // Project: Simple GPIO Interrupt // // File: main.c // // Description: This PSoC project configures Port1[0] as an output to drive // an LED and configures Port1[4] as an input that generates an interrupt // on the rising edge. At each interrupt Port1[0] is toggled, thereby turning // the LED on/off with each switch press. // // Ports: // Port1[0]: Name=LED, Drive=Strong // Port1[4]: Name=SWITCH, Drive=High Z, Interrupt=RisingEdge // // Author: Dr. Brad Noble // Date: 1-Sep-2009 // // Edited: Matthew Clark // Date: 29-July-2010 // //---------------------------------------------------------------------------#include <m8c.h> #include "PSoCAPI.h" #include "PSoCGPIOINT.h" // part specific constants and macros // PSoC API definitions for all User Modules // We have to include this file manually for GPIO // A compiler directive that tells the C compiler to make PSoC_GPIO_ISR_C a // function that handles interrupts. This means it replaces ret at the end of // the function with reti. Refer to PSoC Technical Reference Manual for more // information. #pragma interrupt_handler PSoC_GPIO_ISR_C void main(void) { // Enable global interrupts (see m8c.h) M8C_EnableGInt; // Enable GPIO Interrupts (see m8c.h) M8C_EnableIntMask(INT_MSK0,INT_MSK0_GPIO); // Spin here forever while(1); } // The interrupt vector for GPIO interrupts is usually handled in assembly // by function PSoC_GPIO_ISR located in PSoCGPIOINT.asm. Since we changed the // corresponding line in boot.asm, this function is called instead. // Note: This C function is only called when a GPIO interrupt is received // and when this C-function is finished it will return-from-interrupt (reti). void PSoC_GPIO_ISR_C(void) { // Toggle LED1 LED1_Data_ADDR ^= LED1_MASK; } ECE 381 Lab 3 –Interrupts and Optical Encoders Part 2 – Interfacing with an Optical Encoder Objective: Interface the optical encoder available in the lab to the PSoC and have the PSoC keep track of the number of rotations CW or CCW on the LCD display. Configuration The LCD connector on the evaluation board is permanently connected to Port 2 of the PSoC, however only P2[0-6] are used by the LCD. This means that if you are using the LCD for a project, the only pin of Port 2 that will be available for you to use is P2[7]. Place an LCD module in the chip-level view in PSoC Designer, located in Misc Digital of the User Modules window. Edit the LCD modules properties in the Properties window. Edit the LCDPort property to connect to Port_2 and Disable the BarGraph. Configure Port1[4] as follows: o Name: OpEncA o Drive: HIGH Z o Interrupt: ChangeFromRead Configure Port1[5] as follows: o Name: OpEncB o Drive: HIGH Z o Interrupt: ChangeFromRead Connect the optical encoder output A to P1[4] and output B to P1[5] according to the schematic on the optical encoder’s datasheet for 5V operation. Power for the encoder can be supplied by VCC and GND on the PSoC Evaluation Board. Software Write a program that will display a count with a range from 0 to 100 on the LCD and have it initialized to 50 on power-up. Each CW turn of the encoder should increment the count up to, but not exceed, 100. Each CCW turn of the encoder should decrement the count down to, but not below, 0. The concept is that the encoder selects a percentage from 0 to 100 with initial value of 50. References [1] Encoder Products Company products brochure http://www.encoder.com/literature/optical-encoder-guide.pdf [2] Bourns Series EM14 optical encoder datasheet http://www.bourns.com/data/global/pdfs/em14.pdf