An example solution for the two switch - flashing LED problem
Fork of Task324Solution by
main.cpp@5:0e52b9b0b1f8, 2019-09-11 (annotated)
- Committer:
- noutram
- Date:
- Wed Sep 11 14:44:37 2019 +0000
- Revision:
- 5:0e52b9b0b1f8
- Parent:
- 3:ba009495c5ef
2019
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
noutram | 0:3590cc227050 | 1 | #include "mbed.h" |
noutram | 0:3590cc227050 | 2 | |
noutram | 1:e8e7c7c87028 | 3 | //Next state logic for switch debounce |
noutram | 1:e8e7c7c87028 | 4 | void updateSwitchState(int sw, int &swState, Timer &tmr, unsigned short &debouncedSwitchOutput); |
noutram | 1:e8e7c7c87028 | 5 | //Moore outputs for switch debounce |
noutram | 1:e8e7c7c87028 | 6 | void updateSwitchOutputs(int swState, unsigned short &debouncedSwitchOutput); |
noutram | 1:e8e7c7c87028 | 7 | //Mealy machine for timer interval |
noutram | 1:e8e7c7c87028 | 8 | static void updateFlashIntervalFSM(float &interval, unsigned short sw1, unsigned short sw2); |
noutram | 0:3590cc227050 | 9 | |
noutram | 0:3590cc227050 | 10 | DigitalOut red_led(D7); |
noutram | 0:3590cc227050 | 11 | DigitalOut green_led(D5); |
noutram | 0:3590cc227050 | 12 | DigitalIn SW1(D4); |
noutram | 0:3590cc227050 | 13 | DigitalIn SW2(D3); |
noutram | 0:3590cc227050 | 14 | //This is the solution based on the proposed flowchart. |
noutram | 0:3590cc227050 | 15 | //The precise delay required may need adjusting |
noutram | 0:3590cc227050 | 16 | |
noutram | 0:3590cc227050 | 17 | Timer tmr1; |
noutram | 0:3590cc227050 | 18 | Timer tmr2; |
noutram | 1:e8e7c7c87028 | 19 | Timer flashTimer; |
noutram | 0:3590cc227050 | 20 | |
noutram | 0:3590cc227050 | 21 | #define WAITING4PRESS 0 |
noutram | 0:3590cc227050 | 22 | #define WAITING4BOUNCE_RISING 1 |
noutram | 0:3590cc227050 | 23 | #define WAITING4RELEASE 2 |
noutram | 0:3590cc227050 | 24 | #define WAITING4BOUNCE_FALLING 4 |
noutram | 0:3590cc227050 | 25 | |
noutram | 1:e8e7c7c87028 | 26 | #define SWPRESSED 1 |
noutram | 1:e8e7c7c87028 | 27 | #define SWRELEASED 0 |
noutram | 1:e8e7c7c87028 | 28 | |
noutram | 1:e8e7c7c87028 | 29 | int main() |
noutram | 1:e8e7c7c87028 | 30 | { |
noutram | 0:3590cc227050 | 31 | //Initial logging message |
noutram | 0:3590cc227050 | 32 | puts("START"); |
noutram | 1:e8e7c7c87028 | 33 | |
noutram | 1:e8e7c7c87028 | 34 | //Power on check |
noutram | 1:e8e7c7c87028 | 35 | red_led = 1; //Set RED LED to OFF |
noutram | 1:e8e7c7c87028 | 36 | green_led = 1; |
noutram | 1:e8e7c7c87028 | 37 | wait(1.0); |
noutram | 0:3590cc227050 | 38 | |
noutram | 0:3590cc227050 | 39 | //Initial state |
noutram | 0:3590cc227050 | 40 | red_led = 0; //Set RED LED to OFF |
noutram | 0:3590cc227050 | 41 | green_led = 0; |
noutram | 1:e8e7c7c87028 | 42 | |
noutram | 0:3590cc227050 | 43 | //Switch state |
noutram | 0:3590cc227050 | 44 | int sw1State = 0; |
noutram | 0:3590cc227050 | 45 | int sw2State = 0; |
noutram | 1:e8e7c7c87028 | 46 | |
noutram | 0:3590cc227050 | 47 | //Timers |
noutram | 0:3590cc227050 | 48 | tmr1.stop(); |
noutram | 0:3590cc227050 | 49 | tmr1.reset(); |
noutram | 0:3590cc227050 | 50 | tmr2.stop(); |
noutram | 0:3590cc227050 | 51 | tmr2.reset(); |
noutram | 1:e8e7c7c87028 | 52 | flashTimer.stop(); |
noutram | 1:e8e7c7c87028 | 53 | flashTimer.reset(); |
noutram | 1:e8e7c7c87028 | 54 | flashTimer.start(); |
noutram | 0:3590cc227050 | 55 | |
noutram | 0:3590cc227050 | 56 | //Initial logging message |
noutram | 0:3590cc227050 | 57 | puts("Entering state WAITING4PRESS"); |
noutram | 0:3590cc227050 | 58 | |
noutram | 1:e8e7c7c87028 | 59 | //Debounced outputs |
noutram | 1:e8e7c7c87028 | 60 | unsigned short sw1_db = SWRELEASED; |
noutram | 1:e8e7c7c87028 | 61 | unsigned short sw2_db = SWRELEASED; |
noutram | 1:e8e7c7c87028 | 62 | |
noutram | 1:e8e7c7c87028 | 63 | //Timer delay |
noutram | 3:ba009495c5ef | 64 | float flashInterval = 1.0f; |
noutram | 1:e8e7c7c87028 | 65 | |
noutram | 0:3590cc227050 | 66 | //Main Polling Loop |
noutram | 0:3590cc227050 | 67 | while (true) { |
noutram | 1:e8e7c7c87028 | 68 | |
noutram | 0:3590cc227050 | 69 | //Poll inputs (without blocking) |
noutram | 0:3590cc227050 | 70 | int sw1 = SW1; |
noutram | 0:3590cc227050 | 71 | int sw2 = SW2; |
noutram | 1:e8e7c7c87028 | 72 | |
noutram | 1:e8e7c7c87028 | 73 | //SWITCH DEBOUNCE FSM |
noutram | 1:e8e7c7c87028 | 74 | updateSwitchState(sw1, sw1State, tmr1, sw1_db); |
noutram | 1:e8e7c7c87028 | 75 | updateSwitchState(sw2, sw2State, tmr2, sw2_db); |
noutram | 1:e8e7c7c87028 | 76 | |
noutram | 1:e8e7c7c87028 | 77 | //Update flashInterval |
noutram | 1:e8e7c7c87028 | 78 | updateFlashIntervalFSM(flashInterval, sw1_db, sw2_db); |
noutram | 1:e8e7c7c87028 | 79 | |
noutram | 1:e8e7c7c87028 | 80 | //LED TIMER DELAY FSM (trivial) |
noutram | 1:e8e7c7c87028 | 81 | if (flashTimer >= flashInterval) { |
noutram | 1:e8e7c7c87028 | 82 | green_led = !green_led; |
noutram | 1:e8e7c7c87028 | 83 | flashTimer.reset(); |
noutram | 1:e8e7c7c87028 | 84 | } |
noutram | 0:3590cc227050 | 85 | |
noutram | 1:e8e7c7c87028 | 86 | |
noutram | 0:3590cc227050 | 87 | } //end while |
noutram | 0:3590cc227050 | 88 | |
noutram | 0:3590cc227050 | 89 | } |
noutram | 0:3590cc227050 | 90 | |
noutram | 1:e8e7c7c87028 | 91 | //Here is an example of a self-contained finite state machine |
noutram | 1:e8e7c7c87028 | 92 | //sw1 and sw2 are debounced, so no need for timers |
noutram | 1:e8e7c7c87028 | 93 | //interval is a Mealy output (keeps the FSM small) |
noutram | 1:e8e7c7c87028 | 94 | static void updateFlashIntervalFSM(float &interval, unsigned short sw1, unsigned short sw2) |
noutram | 1:e8e7c7c87028 | 95 | { |
noutram | 1:e8e7c7c87028 | 96 | //This data type is private to this function |
noutram | 1:e8e7c7c87028 | 97 | enum FI_STATE {NOPRESS, PRESSED}; |
noutram | 1:e8e7c7c87028 | 98 | |
noutram | 1:e8e7c7c87028 | 99 | //This is a static local - it is initilaised ONCE and remembers it's value with each function call |
noutram | 1:e8e7c7c87028 | 100 | static FI_STATE state = NOPRESS; |
noutram | 1:e8e7c7c87028 | 101 | |
noutram | 1:e8e7c7c87028 | 102 | //Simple FSM to update the interval - reduced to 2 states |
noutram | 1:e8e7c7c87028 | 103 | switch (state) { |
noutram | 1:e8e7c7c87028 | 104 | case NOPRESS: |
noutram | 1:e8e7c7c87028 | 105 | if (sw1 && sw2) { |
noutram | 1:e8e7c7c87028 | 106 | state = PRESSED; |
noutram | 1:e8e7c7c87028 | 107 | interval = 1.0; //Mealy output |
noutram | 1:e8e7c7c87028 | 108 | } else if (sw1 & !sw2) { |
noutram | 1:e8e7c7c87028 | 109 | state = PRESSED; |
noutram | 2:5ebd8af9586e | 110 | interval += ((interval>0.2f) ? -0.1f : 0.0f); |
noutram | 1:e8e7c7c87028 | 111 | } else if (!sw1 & sw2) { |
noutram | 1:e8e7c7c87028 | 112 | state = PRESSED; |
noutram | 1:e8e7c7c87028 | 113 | interval += 0.1f; |
noutram | 1:e8e7c7c87028 | 114 | } |
noutram | 1:e8e7c7c87028 | 115 | break; |
noutram | 1:e8e7c7c87028 | 116 | case PRESSED: |
noutram | 1:e8e7c7c87028 | 117 | //All states lead back to NOPRESS when both are released |
noutram | 1:e8e7c7c87028 | 118 | if (!sw1 && !sw2) { |
noutram | 1:e8e7c7c87028 | 119 | state = NOPRESS; |
noutram | 1:e8e7c7c87028 | 120 | } |
noutram | 1:e8e7c7c87028 | 121 | //If at any time both are pressed, reset the interval |
noutram | 1:e8e7c7c87028 | 122 | else if (sw1 && sw2) { |
noutram | 1:e8e7c7c87028 | 123 | interval = 1.0; //Mealy output |
noutram | 1:e8e7c7c87028 | 124 | } |
noutram | 1:e8e7c7c87028 | 125 | break; |
noutram | 1:e8e7c7c87028 | 126 | default: |
noutram | 1:e8e7c7c87028 | 127 | printf("ERROR"); |
noutram | 1:e8e7c7c87028 | 128 | state = NOPRESS; |
noutram | 1:e8e7c7c87028 | 129 | interval = 1.0; |
noutram | 1:e8e7c7c87028 | 130 | } //End case |
noutram | 1:e8e7c7c87028 | 131 | } //End function |
noutram | 1:e8e7c7c87028 | 132 | |
noutram | 0:3590cc227050 | 133 | // Update the state for a given switch and LED pair |
noutram | 0:3590cc227050 | 134 | // Parameters: |
noutram | 0:3590cc227050 | 135 | // sw is the switch input, 0 for released and 1 for pressed, passed by value |
noutram | 0:3590cc227050 | 136 | // swState is an integer that keeps a record of state, passed by reference (updated by the function) |
noutram | 1:e8e7c7c87028 | 137 | // REMOVED led is of type DigitalOut, connected to a LED |
noutram | 0:3590cc227050 | 138 | // tmr is of type Timer, a reference to unique instance of a timer |
noutram | 0:3590cc227050 | 139 | // This function cannot be called by an ISR |
noutram | 1:e8e7c7c87028 | 140 | void updateSwitchState(int sw, int &swState, Timer &tmr, unsigned short &debouncedSwitchOutput) |
noutram | 0:3590cc227050 | 141 | { |
noutram | 1:e8e7c7c87028 | 142 | //LED |
noutram | 1:e8e7c7c87028 | 143 | switch (swState) { |
noutram | 1:e8e7c7c87028 | 144 | |
noutram | 1:e8e7c7c87028 | 145 | //Waiting for switch to be pressed |
noutram | 0:3590cc227050 | 146 | case WAITING4PRESS: |
noutram | 0:3590cc227050 | 147 | |
noutram | 0:3590cc227050 | 148 | if (sw == 1) { |
noutram | 0:3590cc227050 | 149 | //Output: start timer |
noutram | 0:3590cc227050 | 150 | tmr.reset(); |
noutram | 0:3590cc227050 | 151 | tmr.start(); |
noutram | 1:e8e7c7c87028 | 152 | |
noutram | 0:3590cc227050 | 153 | //Next state |
noutram | 1:e8e7c7c87028 | 154 | swState = WAITING4BOUNCE_RISING; |
noutram | 0:3590cc227050 | 155 | puts("Entering state: WAITING4BOUNCE_RISING"); |
noutram | 1:e8e7c7c87028 | 156 | } |
noutram | 0:3590cc227050 | 157 | break; |
noutram | 1:e8e7c7c87028 | 158 | |
noutram | 1:e8e7c7c87028 | 159 | //Waiting for 50ms to elapse |
noutram | 1:e8e7c7c87028 | 160 | case WAITING4BOUNCE_RISING: |
noutram | 0:3590cc227050 | 161 | if (tmr.read_ms() > 50) { |
noutram | 0:3590cc227050 | 162 | //Outputs: Stop timer |
noutram | 0:3590cc227050 | 163 | tmr.stop(); |
noutram | 0:3590cc227050 | 164 | //Next state |
noutram | 1:e8e7c7c87028 | 165 | swState = WAITING4RELEASE; |
noutram | 1:e8e7c7c87028 | 166 | puts("Entering state: WAITING4RELEASE"); |
noutram | 1:e8e7c7c87028 | 167 | } |
noutram | 0:3590cc227050 | 168 | break; |
noutram | 1:e8e7c7c87028 | 169 | |
noutram | 1:e8e7c7c87028 | 170 | //Waiting for switch to be released |
noutram | 0:3590cc227050 | 171 | case WAITING4RELEASE: |
noutram | 0:3590cc227050 | 172 | if (sw == 0) { |
noutram | 0:3590cc227050 | 173 | tmr.reset(); |
noutram | 1:e8e7c7c87028 | 174 | tmr.start(); |
noutram | 0:3590cc227050 | 175 | //Next state |
noutram | 1:e8e7c7c87028 | 176 | swState = WAITING4BOUNCE_FALLING; |
noutram | 1:e8e7c7c87028 | 177 | puts("Entering state: WAITING4BOUNCE_FALLING"); |
noutram | 1:e8e7c7c87028 | 178 | } |
noutram | 0:3590cc227050 | 179 | break; |
noutram | 1:e8e7c7c87028 | 180 | |
noutram | 1:e8e7c7c87028 | 181 | //Waiting 50ms for switch bounce |
noutram | 0:3590cc227050 | 182 | case WAITING4BOUNCE_FALLING: |
noutram | 0:3590cc227050 | 183 | if (tmr.read_ms() > 50) { |
noutram | 0:3590cc227050 | 184 | //Outputs: Reset timer 1 |
noutram | 0:3590cc227050 | 185 | tmr.stop(); |
noutram | 0:3590cc227050 | 186 | tmr.reset(); |
noutram | 1:e8e7c7c87028 | 187 | |
noutram | 0:3590cc227050 | 188 | //Next state: |
noutram | 0:3590cc227050 | 189 | swState = WAITING4PRESS; |
noutram | 1:e8e7c7c87028 | 190 | puts("Entering state: WAITING4PRESS"); |
noutram | 0:3590cc227050 | 191 | } |
noutram | 0:3590cc227050 | 192 | break; |
noutram | 1:e8e7c7c87028 | 193 | |
noutram | 0:3590cc227050 | 194 | default: |
noutram | 0:3590cc227050 | 195 | //Something has gone very wrong |
noutram | 0:3590cc227050 | 196 | tmr.stop(); |
noutram | 0:3590cc227050 | 197 | tmr.reset(); |
noutram | 0:3590cc227050 | 198 | swState = WAITING4PRESS; |
noutram | 0:3590cc227050 | 199 | puts("ERROR"); |
noutram | 0:3590cc227050 | 200 | break; |
noutram | 1:e8e7c7c87028 | 201 | |
noutram | 1:e8e7c7c87028 | 202 | } //end switch |
noutram | 1:e8e7c7c87028 | 203 | |
noutram | 1:e8e7c7c87028 | 204 | //Moore outputs |
noutram | 1:e8e7c7c87028 | 205 | updateSwitchOutputs(swState, debouncedSwitchOutput); |
noutram | 1:e8e7c7c87028 | 206 | |
noutram | 1:e8e7c7c87028 | 207 | } //end function |
noutram | 1:e8e7c7c87028 | 208 | |
noutram | 1:e8e7c7c87028 | 209 | |
noutram | 1:e8e7c7c87028 | 210 | //Moore Outputs - asserted with each pass. Could be convered easily to Mealy outputs |
noutram | 1:e8e7c7c87028 | 211 | // swState is the state of the switch debounce finite state machine |
noutram | 1:e8e7c7c87028 | 212 | // debouncedSwitchOutput is the Moore output for the state machine |
noutram | 1:e8e7c7c87028 | 213 | void updateSwitchOutputs(int swState, unsigned short &debouncedSwitchOutput) |
noutram | 1:e8e7c7c87028 | 214 | { |
noutram | 1:e8e7c7c87028 | 215 | switch (swState) { |
noutram | 1:e8e7c7c87028 | 216 | //Waiting for switch to be pressed |
noutram | 1:e8e7c7c87028 | 217 | case WAITING4PRESS: |
noutram | 1:e8e7c7c87028 | 218 | debouncedSwitchOutput = SWRELEASED; |
noutram | 1:e8e7c7c87028 | 219 | break; |
noutram | 1:e8e7c7c87028 | 220 | //Waiting for 50ms to elapse |
noutram | 1:e8e7c7c87028 | 221 | case WAITING4BOUNCE_RISING: |
noutram | 1:e8e7c7c87028 | 222 | debouncedSwitchOutput = SWRELEASED; |
noutram | 1:e8e7c7c87028 | 223 | break; |
noutram | 1:e8e7c7c87028 | 224 | //Waiting for switch to be released |
noutram | 1:e8e7c7c87028 | 225 | case WAITING4RELEASE: |
noutram | 1:e8e7c7c87028 | 226 | debouncedSwitchOutput = SWPRESSED; |
noutram | 1:e8e7c7c87028 | 227 | break; |
noutram | 1:e8e7c7c87028 | 228 | //Waiting 50ms for switch bounce |
noutram | 1:e8e7c7c87028 | 229 | case WAITING4BOUNCE_FALLING: |
noutram | 1:e8e7c7c87028 | 230 | debouncedSwitchOutput = SWRELEASED; |
noutram | 1:e8e7c7c87028 | 231 | break; |
noutram | 1:e8e7c7c87028 | 232 | default: |
noutram | 1:e8e7c7c87028 | 233 | //Something has gone very wrong |
noutram | 1:e8e7c7c87028 | 234 | debouncedSwitchOutput = SWRELEASED; |
noutram | 1:e8e7c7c87028 | 235 | printf("ERROR\n\r"); |
noutram | 1:e8e7c7c87028 | 236 | break; |
noutram | 1:e8e7c7c87028 | 237 | } //end switch |
noutram | 1:e8e7c7c87028 | 238 | } //end function |
noutram | 1:e8e7c7c87028 | 239 |