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.

Committer:
elijahorr
Date:
Thu Sep 08 07:15:57 2016 +0000
Revision:
1:83e238178956
Parent:
0:c71cc517659b
first issue

Who changed what in which revision?

UserRevisionLine numberNew contents of line
elijahorr 1:83e238178956 1 /*******************************************************************************
elijahorr 1:83e238178956 2 * Program to interface RenBed to a simple optical linear encoder *
elijahorr 1:83e238178956 3 * Copyright (c) 2016 Elijah Orr *
elijahorr 1:83e238178956 4 * *
elijahorr 1:83e238178956 5 * Permission is hereby granted, free of charge, to any person obtaining a copy *
elijahorr 1:83e238178956 6 * of this software and associated documentation files (the "Software"), to deal*
elijahorr 1:83e238178956 7 * in the Software without restriction, including without limitation the rights *
elijahorr 1:83e238178956 8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell *
elijahorr 1:83e238178956 9 * copies of the Software, and to permit persons to whom the Software is *
elijahorr 1:83e238178956 10 * furnished to do so, subject to the following conditions: *
elijahorr 1:83e238178956 11 * *
elijahorr 1:83e238178956 12 * The above copyright notice and this permission notice shall be included in *
elijahorr 1:83e238178956 13 * all copies or substantial portions of the Software. *
elijahorr 1:83e238178956 14 * *
elijahorr 1:83e238178956 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
elijahorr 1:83e238178956 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
elijahorr 1:83e238178956 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
elijahorr 1:83e238178956 18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
elijahorr 1:83e238178956 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,*
elijahorr 1:83e238178956 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN *
elijahorr 1:83e238178956 21 * THE SOFTWARE. *
elijahorr 1:83e238178956 22 * *
elijahorr 1:83e238178956 23 * Encoder *
elijahorr 1:83e238178956 24 * *
elijahorr 1:83e238178956 25 * V1.0 08/09/2016 First issue of code Elijah Orr *
elijahorr 1:83e238178956 26 *******************************************************************************/
elijahorr 1:83e238178956 27
elijahorr 0:c71cc517659b 28 #include "mbed.h"
elijahorr 0:c71cc517659b 29 #include "SevenSegmentDisplay.h"
elijahorr 0:c71cc517659b 30
elijahorr 1:83e238178956 31 /* 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.
elijahorr 1:83e238178956 32 * you will likely need to change these values for your particular encoder */
elijahorr 0:c71cc517659b 33 #define SIGNAL_LOW 0.56
elijahorr 0:c71cc517659b 34 #define SIGNAL_HIGH 0.60
elijahorr 0:c71cc517659b 35
elijahorr 0:c71cc517659b 36 class Encoder{
elijahorr 1:83e238178956 37
elijahorr 1:83e238178956 38 //public functions and variables can be accessed from anywhere
elijahorr 0:c71cc517659b 39 public:
elijahorr 0:c71cc517659b 40
elijahorr 0:c71cc517659b 41 /****************************************************************************************************************
elijahorr 0:c71cc517659b 42 * Encoder - class constructor, used to declare an instant of the Encoder class. *
elijahorr 0:c71cc517659b 43 * *
elijahorr 0:c71cc517659b 44 * Parameters: PinA - analog channel A, PinB - analog channel B, OutputA - digital output for channel A, *
elijahorr 0:c71cc517659b 45 * OutputB - digital output for channel B, InputA - input for the feedback of digital channel A, *
elijahorr 0:c71cc517659b 46 * InputB - input for the feedback of digital channel B *
elijahorr 0:c71cc517659b 47 * *
elijahorr 0:c71cc517659b 48 * Returns: none *
elijahorr 0:c71cc517659b 49 ****************************************************************************************************************/
elijahorr 0:c71cc517659b 50 Encoder(PinName pinA, PinName pinB, PinName OutputA, PinName OutputB, PinName InputA, PinName InputB) :
elijahorr 0:c71cc517659b 51 SignalA(pinA), SignalB(pinB), SquaredA(OutputA), SquaredB(OutputB), SquaredA_in(InputA), SquaredB_in(InputB){
elijahorr 0:c71cc517659b 52
elijahorr 0:c71cc517659b 53 //attach ADC function to ticker, will be called every 75 microseconds (pretty much as often as possible)
elijahorr 0:c71cc517659b 54 ProcessCycle.attach_us(this, &Encoder::ConvertSignals, 75);
elijahorr 0:c71cc517659b 55 //attach rising_A function to rising edge interrupt on the feedback signal for digital channel A
elijahorr 0:c71cc517659b 56 SquaredA_in.rise(this, &Encoder::rising_A);
elijahorr 0:c71cc517659b 57 //attach falling_A function to falling edge interrupt on the feedback signal for digital channel B
elijahorr 0:c71cc517659b 58 SquaredA_in.fall(this, &Encoder::falling_A);
elijahorr 0:c71cc517659b 59 }
elijahorr 0:c71cc517659b 60
elijahorr 0:c71cc517659b 61 /*******************************************************************************
elijahorr 0:c71cc517659b 62 * get_count - returns the current encoder counter value
elijahorr 0:c71cc517659b 63 *
elijahorr 0:c71cc517659b 64 * Parameters: none
elijahorr 0:c71cc517659b 65 *
elijahorr 0:c71cc517659b 66 * Returns: int - current counter value
elijahorr 0:c71cc517659b 67 *******************************************************************************/
elijahorr 0:c71cc517659b 68 int get_count(void){
elijahorr 0:c71cc517659b 69 return count;
elijahorr 0:c71cc517659b 70 }
elijahorr 1:83e238178956 71
elijahorr 1:83e238178956 72 //private functions and variables are only accessable from within the encoder class
elijahorr 0:c71cc517659b 73 private:
elijahorr 0:c71cc517659b 74 AnalogIn SignalA; //analog input for signal A
elijahorr 0:c71cc517659b 75 AnalogIn SignalB; //analog input for signal B
elijahorr 0:c71cc517659b 76 DigitalOut SquaredA; //digital output for the digital translation of channel A
elijahorr 0:c71cc517659b 77 DigitalOut SquaredB; //digital output for the digital translation of channel B
elijahorr 0:c71cc517659b 78 InterruptIn SquaredA_in; //interrupt for the feedback of digital channel A signal
elijahorr 0:c71cc517659b 79 InterruptIn SquaredB_in; //interrupt for the feedback of digital channel B signal
elijahorr 0:c71cc517659b 80 Ticker ProcessCycle; //ticker to attach signal converter function to
elijahorr 0:c71cc517659b 81
elijahorr 0:c71cc517659b 82 int count; //variable to store counter value
elijahorr 0:c71cc517659b 83
elijahorr 0:c71cc517659b 84 /*******************************************************************************
elijahorr 0:c71cc517659b 85 * ConvertSignals - converts the analog signals from the encoder into digital
elijahorr 0:c71cc517659b 86 * quadrature signals.
elijahorr 0:c71cc517659b 87 *
elijahorr 0:c71cc517659b 88 * Parameters: none
elijahorr 0:c71cc517659b 89 *
elijahorr 0:c71cc517659b 90 * Returns: none
elijahorr 0:c71cc517659b 91 *******************************************************************************/
elijahorr 0:c71cc517659b 92 void ConvertSignals(void){
elijahorr 0:c71cc517659b 93
elijahorr 0:c71cc517659b 94 //take readings from the ADC
elijahorr 0:c71cc517659b 95 float A_reading = SignalA;
elijahorr 0:c71cc517659b 96 float B_reading = SignalB;
elijahorr 0:c71cc517659b 97
elijahorr 0:c71cc517659b 98 //decision algorithm to decide when to set the digital signals high/low,
elijahorr 0:c71cc517659b 99 //SIGNAL_LOW and SIGNAL_HIGH are user defined high and low for the analog signals
elijahorr 0:c71cc517659b 100 if(A_reading < SIGNAL_LOW){
elijahorr 0:c71cc517659b 101 SquaredA = 0;
elijahorr 0:c71cc517659b 102 }
elijahorr 0:c71cc517659b 103 else if(A_reading > SIGNAL_HIGH){
elijahorr 0:c71cc517659b 104 SquaredA = 1;
elijahorr 0:c71cc517659b 105 }
elijahorr 0:c71cc517659b 106
elijahorr 0:c71cc517659b 107 if(B_reading < SIGNAL_LOW){
elijahorr 0:c71cc517659b 108 SquaredB = 0;
elijahorr 0:c71cc517659b 109 }
elijahorr 0:c71cc517659b 110 else if(B_reading > SIGNAL_HIGH){
elijahorr 0:c71cc517659b 111 SquaredB = 1;
elijahorr 0:c71cc517659b 112 }
elijahorr 0:c71cc517659b 113 }
elijahorr 0:c71cc517659b 114
elijahorr 0:c71cc517659b 115 /*******************************************************************************
elijahorr 0:c71cc517659b 116 * rising_A - interrupt function for rising edges on channel A, decides when
elijahorr 0:c71cc517659b 117 * the count should be decremented.
elijahorr 0:c71cc517659b 118 *
elijahorr 0:c71cc517659b 119 * Parameters: none
elijahorr 0:c71cc517659b 120 *
elijahorr 0:c71cc517659b 121 * Returns: none
elijahorr 0:c71cc517659b 122 *******************************************************************************/
elijahorr 0:c71cc517659b 123
elijahorr 0:c71cc517659b 124 void rising_A(void){
elijahorr 0:c71cc517659b 125 if(SquaredB.read() == 0){
elijahorr 0:c71cc517659b 126 count--;
elijahorr 0:c71cc517659b 127 }
elijahorr 0:c71cc517659b 128 }
elijahorr 0:c71cc517659b 129
elijahorr 0:c71cc517659b 130 /*******************************************************************************
elijahorr 0:c71cc517659b 131 * falling_A - interrupt function for rising edges on channel A, decides when
elijahorr 0:c71cc517659b 132 * the count should be incremented.
elijahorr 0:c71cc517659b 133 *
elijahorr 0:c71cc517659b 134 * Parameters: none
elijahorr 0:c71cc517659b 135 *
elijahorr 0:c71cc517659b 136 * Returns: none
elijahorr 0:c71cc517659b 137 *******************************************************************************/
elijahorr 0:c71cc517659b 138
elijahorr 0:c71cc517659b 139 void falling_A(void){
elijahorr 0:c71cc517659b 140 if(SquaredB.read() == 0){
elijahorr 0:c71cc517659b 141 count++;
elijahorr 0:c71cc517659b 142 }
elijahorr 0:c71cc517659b 143 }
elijahorr 0:c71cc517659b 144
elijahorr 0:c71cc517659b 145 };
elijahorr 0:c71cc517659b 146
elijahorr 0:c71cc517659b 147 /* Create an instance of the class Encoder, which will be called lollipop (because of the lolly stick height control).
elijahorr 0:c71cc517659b 148 * Pins must be given in the order specified in the constructor, and analog inputs must be ADC pins */
elijahorr 0:c71cc517659b 149 Encoder lollipop(P0_15, P0_22, P0_17, P0_7, P1_14, P0_1);
elijahorr 0:c71cc517659b 150 SevenSegmentDisplay display(INSTANT); //create instance of SevenSegmentDisplay to drive the 7 segs
elijahorr 0:c71cc517659b 151
elijahorr 0:c71cc517659b 152 /*******************************************************************************
elijahorr 0:c71cc517659b 153 * main - this is the main program routine. The encoder class is working in the
elijahorr 0:c71cc517659b 154 * background, as the constructor was called above.
elijahorr 0:c71cc517659b 155 *
elijahorr 0:c71cc517659b 156 * Parameters: none
elijahorr 0:c71cc517659b 157 *
elijahorr 0:c71cc517659b 158 * Returns: none
elijahorr 0:c71cc517659b 159 *******************************************************************************/
elijahorr 0:c71cc517659b 160 int main(){
elijahorr 0:c71cc517659b 161 //a while loop with the parameter 1 will always execute, and repeat forever
elijahorr 0:c71cc517659b 162 while(1){
elijahorr 0:c71cc517659b 163 int counter = lollipop.get_count(); //get the current encoder count value
elijahorr 0:c71cc517659b 164
elijahorr 0:c71cc517659b 165 // if the counter value is positive, seperate into individual digits and drive displays
elijahorr 0:c71cc517659b 166 if(counter >= 0){
elijahorr 0:c71cc517659b 167 display.FadeMode(INSTANT);
elijahorr 0:c71cc517659b 168 int first_digit = counter/10;
elijahorr 0:c71cc517659b 169 int second_digit = counter%10;
elijahorr 0:c71cc517659b 170 display.DisplayDigits(first_digit, second_digit);
elijahorr 0:c71cc517659b 171 }
elijahorr 0:c71cc517659b 172 //if the counter value is negative, make the display flash while displaying value
elijahorr 0:c71cc517659b 173 else if(counter < 0){
elijahorr 0:c71cc517659b 174 display.FadeMode(FLASH);
elijahorr 0:c71cc517659b 175 display.FlashRate(500);
elijahorr 0:c71cc517659b 176 counter = counter*-1;
elijahorr 0:c71cc517659b 177 int first_digit = counter/10;
elijahorr 0:c71cc517659b 178 int second_digit = counter%10;
elijahorr 0:c71cc517659b 179 display.DisplayDigits(first_digit, second_digit);
elijahorr 0:c71cc517659b 180 }
elijahorr 0:c71cc517659b 181 wait(0.2);
elijahorr 0:c71cc517659b 182 }
elijahorr 0:c71cc517659b 183 }
elijahorr 0:c71cc517659b 184