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

Dependencies:   BufferedSerial mbed

Revision:
0:545775417e0d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Mar 22 16:17:12 2016 +0000
@@ -0,0 +1,93 @@
+#include "mbed.h"
+#include "BufferedSerial.h"
+
+//  Interface to Rotary Encoder type IOSC3806-003G-1024BZ1-5L
+InterruptIn rcA     (PB_6);     //  Coder provides A and B quadrature outputs and a once-per-rev index position pulse (signal Z)
+InterruptIn rcB     (PA_6);     //  These three signals wired to inputs configured to cause CPU interrupt on every level transition
+InterruptIn rcZ     (PA_7);
+DigitalOut  led_grn     (LED1); //  green led on ST Nucleo board set to flash to prove system alive
+BufferedSerial pc(USBTX, USBRX);    //  serial port via usb used to display output on pc using TTY terminal e.g. PuTTY
+                    
+volatile    bool    trigger_200ms = false;
+
+Ticker  toggleTick;         //  turns led on / off @ 1Hz, provides visual check of cpu running
+
+int     seconds = 0;
+
+void ledToggler(void) { //  Interrupt handler - led on half sec, off half sec, repeat
+    led_grn = !led_grn;
+    if  (led_grn)
+        seconds++;  //  counts up once per second
+}
+
+void    twohundredms_handler    ()  {
+    trigger_200ms = true;
+}
+
+signed long angle = 0, turns = 0;
+
+void    rcArise_handler ()  {   //  Handler of 'A' rising edge interrupts
+    if  (rcB)   angle++;
+    else        angle--;
+}
+
+void    rcAfall_handler ()  {   //  Handler of 'A' falling edge interrupts
+    if  (rcB)   angle--;
+    else        angle++;
+}
+
+void    rcBrise_handler ()  {   //  Handler of 'B' rising edge interrupts   
+    if  (rcA)   angle--;
+    else        angle++;
+}
+
+void    rcBfall_handler ()  {   //  Handler of 'B' falling edge interrupts
+    if  (rcA)   angle++;
+    else        angle--;
+}
+
+void    rcZrise_handler ()  {   //  Index pulse interrupt handler,
+    if   (rcA)   {              //  keeps count of whole turns of the shaft
+        turns--;
+    }
+    else    {
+        turns++;
+    }
+    angle = 0;
+}
+void    rcZfall_handler ()  {   }
+
+
+int main()
+{
+    int     c_5 = 0;
+    toggleTick.attach(&ledToggler, 0.5f);   //  set interrupt handler to toggle led
+    Ticker  tick200ms;
+    tick200ms.attach_us(&twohundredms_handler, 200000); //  cause timer interrupts at 5Hz
+
+    rcA.mode  (PullUp);     //  Attach pullup resistors to the 3 coder outputs
+    rcB.mode  (PullUp);
+    rcZ.mode  (PullUp);
+    rcA.rise  (&rcArise_handler);   //  Identify interrupt handlers for each of rise and fall
+    rcA.fall  (&rcAfall_handler);   //  events on all three input lines
+    rcB.rise  (&rcBrise_handler);
+    rcB.fall  (&rcBfall_handler);
+    rcZ.rise  (&rcZrise_handler);
+    rcZ.fall  (&rcZfall_handler);
+
+    pc.baud (115200);
+    pc.printf   ("Jon's rotary encoder test sytem starting up\r\n");
+
+    //  Main loop
+    while(1) {  //  loop forever
+        pc.printf   ("Turns %+d\t%+.1f degree\r\n", turns, (double)angle * 360.0 / 2048.0);
+
+        c_5++;
+        if(c_5 > 4)
+        {               //  Can do stuff once per second here
+            c_5 = 0;
+        }
+        while   (!trigger_200ms)    ;//  NEARLY ALL CPU TIME WASTED HERE waiting for interrupt handler to set trigger_200 true
+        trigger_200ms = false;      //  Hence main loop is cycled every 200ms
+    }
+}