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

Dependencies:   BufferedSerial mbed

main.cpp

Committer:
JonFreeman
Date:
2016-03-22
Revision:
0:545775417e0d

File content as of revision 0:545775417e0d:

#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
    }
}