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.

Revision:
0:c71cc517659b
Child:
1:83e238178956
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Sep 05 13:17:15 2016 +0000
@@ -0,0 +1,153 @@
+#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);
+    }
+}
+