Interface the RenBed with a simple optical linear encoder, using X1 encoding.

Dependencies:   SevenSegmentDisplay mbed

This is an example of a copper strip-board design for an optical linear encoder (IRED), and how it is wired up to the Renbed on a breadboard:

/media/uploads/elijahorr/encoderwiring.png

The trimmer potentiometer is used to vary the current through the IRED LEDs, in order to balance out the two output signals.

main.cpp

Committer:
elijahorr
Date:
2016-09-05
Revision:
0:c71cc517659b
Child:
1:83e238178956

File content as of revision 0:c71cc517659b:

#include "mbed.h"
#include "SevenSegmentDisplay.h"

// define values for high and low analog signals, used to compare to ADC values. 0.56 indicates that the low level is set to 56% of 3.3V.
#define SIGNAL_LOW 0.56
#define SIGNAL_HIGH 0.60

class Encoder{
public:
    
/****************************************************************************************************************
*   Encoder - class constructor, used to declare an instant of the Encoder class.                               *
*                                                                                                               *
*   Parameters: PinA - analog channel A, PinB - analog channel B, OutputA - digital output for channel A,       *
*               OutputB - digital output for channel B, InputA - input for the feedback of digital channel A,   *
*               InputB - input for the feedback of digital channel B                                            *
*                                                                                                               *
*   Returns: none                                                                                               *
****************************************************************************************************************/      
    Encoder(PinName pinA, PinName pinB, PinName OutputA, PinName OutputB, PinName InputA, PinName InputB) : 
        SignalA(pinA), SignalB(pinB), SquaredA(OutputA), SquaredB(OutputB), SquaredA_in(InputA), SquaredB_in(InputB){
        
        //attach ADC function to ticker, will be called every 75 microseconds (pretty much as often as possible)
        ProcessCycle.attach_us(this, &Encoder::ConvertSignals, 75);
        //attach rising_A function to rising edge interrupt on the feedback signal for digital channel A
        SquaredA_in.rise(this, &Encoder::rising_A);
        //attach falling_A function to falling edge interrupt on the feedback signal for digital channel B 
        SquaredA_in.fall(this, &Encoder::falling_A);
    }
    
/*******************************************************************************
*   get_count - returns the current encoder counter value
*
*   Parameters: none
*
*   Returns: int - current counter value
*******************************************************************************/    
    int get_count(void){
        return count;
    }
        
private:
    AnalogIn SignalA;           //analog input for signal A
    AnalogIn SignalB;           //analog input for signal B
    DigitalOut SquaredA;        //digital output for the digital translation of channel A
    DigitalOut SquaredB;        //digital output for the digital translation of channel B
    InterruptIn SquaredA_in;    //interrupt for the feedback of digital channel A signal 
    InterruptIn SquaredB_in;    //interrupt for the feedback of digital channel B signal
    Ticker ProcessCycle;        //ticker to attach signal converter function to
    
    int count;                  //variable to store counter value
    
/*******************************************************************************
*   ConvertSignals - converts the analog signals from the encoder into digital
*                    quadrature signals.
*
*   Parameters: none
*
*   Returns: none
*******************************************************************************/    
    void ConvertSignals(void){
        
        //take readings from the ADC
        float A_reading = SignalA;
        float B_reading = SignalB;
        
        //decision algorithm to decide when to set the digital signals high/low, 
        //SIGNAL_LOW and SIGNAL_HIGH are user defined high and low for the analog signals
        if(A_reading < SIGNAL_LOW){
            SquaredA = 0;
        }
        else if(A_reading > SIGNAL_HIGH){
            SquaredA = 1;
        }
        
        if(B_reading < SIGNAL_LOW){
            SquaredB = 0;
        }
        else if(B_reading > SIGNAL_HIGH){
            SquaredB = 1;
        }
    }
    
/*******************************************************************************
*   rising_A - interrupt function for rising edges on channel A, decides when 
*              the count should be decremented.
*
*   Parameters: none
*
*   Returns: none
*******************************************************************************/    
    
    void rising_A(void){
        if(SquaredB.read() == 0){
            count--;
        }
    }

/*******************************************************************************
*   falling_A - interrupt function for rising edges on channel A, decides when 
*              the count should be incremented.
*
*   Parameters: none
*
*   Returns: none
*******************************************************************************/
    
    void falling_A(void){
        if(SquaredB.read() == 0){
            count++;
        }
    }
        
};     

/* Create an instance of the class Encoder, which will be called lollipop (because of the lolly stick height control). 
* Pins must be given in the order specified in the constructor, and analog inputs must be ADC pins */        
Encoder lollipop(P0_15, P0_22, P0_17, P0_7, P1_14, P0_1);
SevenSegmentDisplay display(INSTANT);                       //create instance of SevenSegmentDisplay to drive the 7 segs

/*******************************************************************************
*   main - this is the main program routine. The encoder class is working in the 
*   background, as the constructor was called above.
*
*   Parameters: none
*
*   Returns: none
*******************************************************************************/    
int main(){
    //a while loop with the parameter 1 will always execute, and repeat forever 
    while(1){
        int counter = lollipop.get_count(); //get the current encoder count value
        
        // if the counter value is positive, seperate into individual digits and drive displays
        if(counter >= 0){
            display.FadeMode(INSTANT);
            int first_digit = counter/10;
            int second_digit = counter%10;
            display.DisplayDigits(first_digit, second_digit);
        }
        //if the counter value is negative, make the display flash while displaying value
        else if(counter < 0){
            display.FadeMode(FLASH);
            display.FlashRate(500);
            counter = counter*-1;
            int first_digit = counter/10;
            int second_digit = counter%10;
            display.DisplayDigits(first_digit, second_digit);
        }
        wait(0.2);
    }
}