An example solution for the two switch - flashing LED problem

Fork of Task324Solution by University of Plymouth - Stages 1, 2 and 3

Committer:
noutram
Date:
Wed Sep 11 14:44:37 2019 +0000
Revision:
5:0e52b9b0b1f8
Parent:
3:ba009495c5ef
2019

Who changed what in which revision?

UserRevisionLine numberNew 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