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:
The trimmer potentiometer is used to vary the current through the IRED LEDs, in order to balance out the two output signals.
main.cpp@0:c71cc517659b, 2016-09-05 (annotated)
- Committer:
- elijahorr
- Date:
- Mon Sep 05 13:17:15 2016 +0000
- Revision:
- 0:c71cc517659b
- Child:
- 1:83e238178956
rev 1.0
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
elijahorr | 0:c71cc517659b | 1 | #include "mbed.h" |
elijahorr | 0:c71cc517659b | 2 | #include "SevenSegmentDisplay.h" |
elijahorr | 0:c71cc517659b | 3 | |
elijahorr | 0:c71cc517659b | 4 | // 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 | 0:c71cc517659b | 5 | #define SIGNAL_LOW 0.56 |
elijahorr | 0:c71cc517659b | 6 | #define SIGNAL_HIGH 0.60 |
elijahorr | 0:c71cc517659b | 7 | |
elijahorr | 0:c71cc517659b | 8 | class Encoder{ |
elijahorr | 0:c71cc517659b | 9 | public: |
elijahorr | 0:c71cc517659b | 10 | |
elijahorr | 0:c71cc517659b | 11 | /**************************************************************************************************************** |
elijahorr | 0:c71cc517659b | 12 | * Encoder - class constructor, used to declare an instant of the Encoder class. * |
elijahorr | 0:c71cc517659b | 13 | * * |
elijahorr | 0:c71cc517659b | 14 | * Parameters: PinA - analog channel A, PinB - analog channel B, OutputA - digital output for channel A, * |
elijahorr | 0:c71cc517659b | 15 | * OutputB - digital output for channel B, InputA - input for the feedback of digital channel A, * |
elijahorr | 0:c71cc517659b | 16 | * InputB - input for the feedback of digital channel B * |
elijahorr | 0:c71cc517659b | 17 | * * |
elijahorr | 0:c71cc517659b | 18 | * Returns: none * |
elijahorr | 0:c71cc517659b | 19 | ****************************************************************************************************************/ |
elijahorr | 0:c71cc517659b | 20 | Encoder(PinName pinA, PinName pinB, PinName OutputA, PinName OutputB, PinName InputA, PinName InputB) : |
elijahorr | 0:c71cc517659b | 21 | SignalA(pinA), SignalB(pinB), SquaredA(OutputA), SquaredB(OutputB), SquaredA_in(InputA), SquaredB_in(InputB){ |
elijahorr | 0:c71cc517659b | 22 | |
elijahorr | 0:c71cc517659b | 23 | //attach ADC function to ticker, will be called every 75 microseconds (pretty much as often as possible) |
elijahorr | 0:c71cc517659b | 24 | ProcessCycle.attach_us(this, &Encoder::ConvertSignals, 75); |
elijahorr | 0:c71cc517659b | 25 | //attach rising_A function to rising edge interrupt on the feedback signal for digital channel A |
elijahorr | 0:c71cc517659b | 26 | SquaredA_in.rise(this, &Encoder::rising_A); |
elijahorr | 0:c71cc517659b | 27 | //attach falling_A function to falling edge interrupt on the feedback signal for digital channel B |
elijahorr | 0:c71cc517659b | 28 | SquaredA_in.fall(this, &Encoder::falling_A); |
elijahorr | 0:c71cc517659b | 29 | } |
elijahorr | 0:c71cc517659b | 30 | |
elijahorr | 0:c71cc517659b | 31 | /******************************************************************************* |
elijahorr | 0:c71cc517659b | 32 | * get_count - returns the current encoder counter value |
elijahorr | 0:c71cc517659b | 33 | * |
elijahorr | 0:c71cc517659b | 34 | * Parameters: none |
elijahorr | 0:c71cc517659b | 35 | * |
elijahorr | 0:c71cc517659b | 36 | * Returns: int - current counter value |
elijahorr | 0:c71cc517659b | 37 | *******************************************************************************/ |
elijahorr | 0:c71cc517659b | 38 | int get_count(void){ |
elijahorr | 0:c71cc517659b | 39 | return count; |
elijahorr | 0:c71cc517659b | 40 | } |
elijahorr | 0:c71cc517659b | 41 | |
elijahorr | 0:c71cc517659b | 42 | private: |
elijahorr | 0:c71cc517659b | 43 | AnalogIn SignalA; //analog input for signal A |
elijahorr | 0:c71cc517659b | 44 | AnalogIn SignalB; //analog input for signal B |
elijahorr | 0:c71cc517659b | 45 | DigitalOut SquaredA; //digital output for the digital translation of channel A |
elijahorr | 0:c71cc517659b | 46 | DigitalOut SquaredB; //digital output for the digital translation of channel B |
elijahorr | 0:c71cc517659b | 47 | InterruptIn SquaredA_in; //interrupt for the feedback of digital channel A signal |
elijahorr | 0:c71cc517659b | 48 | InterruptIn SquaredB_in; //interrupt for the feedback of digital channel B signal |
elijahorr | 0:c71cc517659b | 49 | Ticker ProcessCycle; //ticker to attach signal converter function to |
elijahorr | 0:c71cc517659b | 50 | |
elijahorr | 0:c71cc517659b | 51 | int count; //variable to store counter value |
elijahorr | 0:c71cc517659b | 52 | |
elijahorr | 0:c71cc517659b | 53 | /******************************************************************************* |
elijahorr | 0:c71cc517659b | 54 | * ConvertSignals - converts the analog signals from the encoder into digital |
elijahorr | 0:c71cc517659b | 55 | * quadrature signals. |
elijahorr | 0:c71cc517659b | 56 | * |
elijahorr | 0:c71cc517659b | 57 | * Parameters: none |
elijahorr | 0:c71cc517659b | 58 | * |
elijahorr | 0:c71cc517659b | 59 | * Returns: none |
elijahorr | 0:c71cc517659b | 60 | *******************************************************************************/ |
elijahorr | 0:c71cc517659b | 61 | void ConvertSignals(void){ |
elijahorr | 0:c71cc517659b | 62 | |
elijahorr | 0:c71cc517659b | 63 | //take readings from the ADC |
elijahorr | 0:c71cc517659b | 64 | float A_reading = SignalA; |
elijahorr | 0:c71cc517659b | 65 | float B_reading = SignalB; |
elijahorr | 0:c71cc517659b | 66 | |
elijahorr | 0:c71cc517659b | 67 | //decision algorithm to decide when to set the digital signals high/low, |
elijahorr | 0:c71cc517659b | 68 | //SIGNAL_LOW and SIGNAL_HIGH are user defined high and low for the analog signals |
elijahorr | 0:c71cc517659b | 69 | if(A_reading < SIGNAL_LOW){ |
elijahorr | 0:c71cc517659b | 70 | SquaredA = 0; |
elijahorr | 0:c71cc517659b | 71 | } |
elijahorr | 0:c71cc517659b | 72 | else if(A_reading > SIGNAL_HIGH){ |
elijahorr | 0:c71cc517659b | 73 | SquaredA = 1; |
elijahorr | 0:c71cc517659b | 74 | } |
elijahorr | 0:c71cc517659b | 75 | |
elijahorr | 0:c71cc517659b | 76 | if(B_reading < SIGNAL_LOW){ |
elijahorr | 0:c71cc517659b | 77 | SquaredB = 0; |
elijahorr | 0:c71cc517659b | 78 | } |
elijahorr | 0:c71cc517659b | 79 | else if(B_reading > SIGNAL_HIGH){ |
elijahorr | 0:c71cc517659b | 80 | SquaredB = 1; |
elijahorr | 0:c71cc517659b | 81 | } |
elijahorr | 0:c71cc517659b | 82 | } |
elijahorr | 0:c71cc517659b | 83 | |
elijahorr | 0:c71cc517659b | 84 | /******************************************************************************* |
elijahorr | 0:c71cc517659b | 85 | * rising_A - interrupt function for rising edges on channel A, decides when |
elijahorr | 0:c71cc517659b | 86 | * the count should be decremented. |
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 | |
elijahorr | 0:c71cc517659b | 93 | void rising_A(void){ |
elijahorr | 0:c71cc517659b | 94 | if(SquaredB.read() == 0){ |
elijahorr | 0:c71cc517659b | 95 | count--; |
elijahorr | 0:c71cc517659b | 96 | } |
elijahorr | 0:c71cc517659b | 97 | } |
elijahorr | 0:c71cc517659b | 98 | |
elijahorr | 0:c71cc517659b | 99 | /******************************************************************************* |
elijahorr | 0:c71cc517659b | 100 | * falling_A - interrupt function for rising edges on channel A, decides when |
elijahorr | 0:c71cc517659b | 101 | * the count should be incremented. |
elijahorr | 0:c71cc517659b | 102 | * |
elijahorr | 0:c71cc517659b | 103 | * Parameters: none |
elijahorr | 0:c71cc517659b | 104 | * |
elijahorr | 0:c71cc517659b | 105 | * Returns: none |
elijahorr | 0:c71cc517659b | 106 | *******************************************************************************/ |
elijahorr | 0:c71cc517659b | 107 | |
elijahorr | 0:c71cc517659b | 108 | void falling_A(void){ |
elijahorr | 0:c71cc517659b | 109 | if(SquaredB.read() == 0){ |
elijahorr | 0:c71cc517659b | 110 | count++; |
elijahorr | 0:c71cc517659b | 111 | } |
elijahorr | 0:c71cc517659b | 112 | } |
elijahorr | 0:c71cc517659b | 113 | |
elijahorr | 0:c71cc517659b | 114 | }; |
elijahorr | 0:c71cc517659b | 115 | |
elijahorr | 0:c71cc517659b | 116 | /* Create an instance of the class Encoder, which will be called lollipop (because of the lolly stick height control). |
elijahorr | 0:c71cc517659b | 117 | * Pins must be given in the order specified in the constructor, and analog inputs must be ADC pins */ |
elijahorr | 0:c71cc517659b | 118 | Encoder lollipop(P0_15, P0_22, P0_17, P0_7, P1_14, P0_1); |
elijahorr | 0:c71cc517659b | 119 | SevenSegmentDisplay display(INSTANT); //create instance of SevenSegmentDisplay to drive the 7 segs |
elijahorr | 0:c71cc517659b | 120 | |
elijahorr | 0:c71cc517659b | 121 | /******************************************************************************* |
elijahorr | 0:c71cc517659b | 122 | * main - this is the main program routine. The encoder class is working in the |
elijahorr | 0:c71cc517659b | 123 | * background, as the constructor was called above. |
elijahorr | 0:c71cc517659b | 124 | * |
elijahorr | 0:c71cc517659b | 125 | * Parameters: none |
elijahorr | 0:c71cc517659b | 126 | * |
elijahorr | 0:c71cc517659b | 127 | * Returns: none |
elijahorr | 0:c71cc517659b | 128 | *******************************************************************************/ |
elijahorr | 0:c71cc517659b | 129 | int main(){ |
elijahorr | 0:c71cc517659b | 130 | //a while loop with the parameter 1 will always execute, and repeat forever |
elijahorr | 0:c71cc517659b | 131 | while(1){ |
elijahorr | 0:c71cc517659b | 132 | int counter = lollipop.get_count(); //get the current encoder count value |
elijahorr | 0:c71cc517659b | 133 | |
elijahorr | 0:c71cc517659b | 134 | // if the counter value is positive, seperate into individual digits and drive displays |
elijahorr | 0:c71cc517659b | 135 | if(counter >= 0){ |
elijahorr | 0:c71cc517659b | 136 | display.FadeMode(INSTANT); |
elijahorr | 0:c71cc517659b | 137 | int first_digit = counter/10; |
elijahorr | 0:c71cc517659b | 138 | int second_digit = counter%10; |
elijahorr | 0:c71cc517659b | 139 | display.DisplayDigits(first_digit, second_digit); |
elijahorr | 0:c71cc517659b | 140 | } |
elijahorr | 0:c71cc517659b | 141 | //if the counter value is negative, make the display flash while displaying value |
elijahorr | 0:c71cc517659b | 142 | else if(counter < 0){ |
elijahorr | 0:c71cc517659b | 143 | display.FadeMode(FLASH); |
elijahorr | 0:c71cc517659b | 144 | display.FlashRate(500); |
elijahorr | 0:c71cc517659b | 145 | counter = counter*-1; |
elijahorr | 0:c71cc517659b | 146 | int first_digit = counter/10; |
elijahorr | 0:c71cc517659b | 147 | int second_digit = counter%10; |
elijahorr | 0:c71cc517659b | 148 | display.DisplayDigits(first_digit, second_digit); |
elijahorr | 0:c71cc517659b | 149 | } |
elijahorr | 0:c71cc517659b | 150 | wait(0.2); |
elijahorr | 0:c71cc517659b | 151 | } |
elijahorr | 0:c71cc517659b | 152 | } |
elijahorr | 0:c71cc517659b | 153 |