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-08
Revision:
1:83e238178956
Parent:
0:c71cc517659b

File content as of revision 1:83e238178956:

/*******************************************************************************
* Program to interface RenBed to a simple optical linear encoder               *
* Copyright (c) 2016 Elijah Orr                                                *
*                                                                              *
* Permission is hereby granted, free of charge, to any person obtaining a copy *
* of this software and associated documentation files (the "Software"), to deal*
* in the Software without restriction, including without limitation the rights *
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell    *
* copies of the Software, and to permit persons to whom the Software is        *
* furnished to do so, subject to the following conditions:                     *
*                                                                              *
* The above copyright notice and this permission notice shall be included in   *
* all copies or substantial portions of the Software.                          *
*                                                                              *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR   *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,     *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  *
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER       *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,*
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN    *
* THE SOFTWARE.                                                                *
*                                                                              *
* Encoder                                                                      *
*                                                                              *
* V1.0 08/09/2016 First issue of code                      Elijah Orr          *
*******************************************************************************/

#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.
* you will likely need to change these values for your particular encoder */
#define SIGNAL_LOW 0.56
#define SIGNAL_HIGH 0.60

class Encoder{

//public functions and variables can be accessed from anywhere
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 functions and variables are only accessable from within the encoder class        
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);
    }
}