Example of interrupt driven Rotary Encoder interface using ISC3806-003G-1024BZ1-5L Rotary Encoder

Dependencies:   BufferedSerial mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include "BufferedSerial.h"
00003 
00004 //  Interface to Rotary Encoder type IOSC3806-003G-1024BZ1-5L
00005 InterruptIn rcA     (PB_6);     //  Coder provides A and B quadrature outputs and a once-per-rev index position pulse (signal Z)
00006 InterruptIn rcB     (PA_6);     //  These three signals wired to inputs configured to cause CPU interrupt on every level transition
00007 InterruptIn rcZ     (PA_7);
00008 DigitalOut  led_grn     (LED1); //  green led on ST Nucleo board set to flash to prove system alive
00009 BufferedSerial pc(USBTX, USBRX);    //  serial port via usb used to display output on pc using TTY terminal e.g. PuTTY
00010                     
00011 volatile    bool    trigger_200ms = false;
00012 
00013 Ticker  toggleTick;         //  turns led on / off @ 1Hz, provides visual check of cpu running
00014 
00015 int     seconds = 0;
00016 
00017 void ledToggler(void) { //  Interrupt handler - led on half sec, off half sec, repeat
00018     led_grn = !led_grn;
00019     if  (led_grn)
00020         seconds++;  //  counts up once per second
00021 }
00022 
00023 void    twohundredms_handler    ()  {
00024     trigger_200ms = true;
00025 }
00026 
00027 signed long angle = 0, turns = 0;
00028 
00029 void    rcArise_handler ()  {   //  Handler of 'A' rising edge interrupts
00030     if  (rcB)   angle++;
00031     else        angle--;
00032 }
00033 
00034 void    rcAfall_handler ()  {   //  Handler of 'A' falling edge interrupts
00035     if  (rcB)   angle--;
00036     else        angle++;
00037 }
00038 
00039 void    rcBrise_handler ()  {   //  Handler of 'B' rising edge interrupts   
00040     if  (rcA)   angle--;
00041     else        angle++;
00042 }
00043 
00044 void    rcBfall_handler ()  {   //  Handler of 'B' falling edge interrupts
00045     if  (rcA)   angle++;
00046     else        angle--;
00047 }
00048 
00049 void    rcZrise_handler ()  {   //  Index pulse interrupt handler,
00050     if   (rcA)   {              //  keeps count of whole turns of the shaft
00051         turns--;
00052     }
00053     else    {
00054         turns++;
00055     }
00056     angle = 0;
00057 }
00058 void    rcZfall_handler ()  {   }
00059 
00060 
00061 int main()
00062 {
00063     int     c_5 = 0;
00064     toggleTick.attach(&ledToggler, 0.5f);   //  set interrupt handler to toggle led
00065     Ticker  tick200ms;
00066     tick200ms.attach_us(&twohundredms_handler, 200000); //  cause timer interrupts at 5Hz
00067 
00068     rcA.mode  (PullUp);     //  Attach pullup resistors to the 3 coder outputs
00069     rcB.mode  (PullUp);
00070     rcZ.mode  (PullUp);
00071     rcA.rise  (&rcArise_handler);   //  Identify interrupt handlers for each of rise and fall
00072     rcA.fall  (&rcAfall_handler);   //  events on all three input lines
00073     rcB.rise  (&rcBrise_handler);
00074     rcB.fall  (&rcBfall_handler);
00075     rcZ.rise  (&rcZrise_handler);
00076     rcZ.fall  (&rcZfall_handler);
00077 
00078     pc.baud (115200);
00079     pc.printf   ("Jon's rotary encoder test sytem starting up\r\n");
00080 
00081     //  Main loop
00082     while(1) {  //  loop forever
00083         pc.printf   ("Turns %+d\t%+.1f degree\r\n", turns, (double)angle * 360.0 / 2048.0);
00084 
00085         c_5++;
00086         if(c_5 > 4)
00087         {               //  Can do stuff once per second here
00088             c_5 = 0;
00089         }
00090         while   (!trigger_200ms)    ;//  NEARLY ALL CPU TIME WASTED HERE waiting for interrupt handler to set trigger_200 true
00091         trigger_200ms = false;      //  Hence main loop is cycled every 200ms
00092     }
00093 }