Components and supplies
Tactile Switch, Top Actuated
Breadboard (generic)
Arduino UNO
Jumper wires (generic)
Apps and platforms
Arduino IDE
Project description
Code
Reading Multiple Buttons by Polling
c_cpp
This sketch will reliably read any number of button switches by polling each of them in turn. Once a button switch is pressed the main code loop will switch to user provided code to handle the purpose of the button press. This is controlled via a switch control struct(ure) and associated switch-case code. The sketch layout is straight forward and process code for each button can be added where indicated within the main loop, under the switch-case section. As provided out of the box (OOTB), the main loop switch-case handling code simply prints to the serial monitor the button number activated.
1/* 2 Ron D Bentley, Stafford, UK 3 Feb 2021 4 5 Reading Multiple Button Switches, using simple polling 6 '''''''''''''''''''''''''''''''''''''''''''''''''''''' 7 8 This example and code is in the public domain and may be used without restriction and 9 without warranty. 10 11 This sketch will reliably read any number of button switches by polling each of 12 them in turn. Once a button switch is pressed the main code loop will switch 13 to user provided code to handle the purpose of the button press. This is controlled 14 via a switch control struct(ure) and associated main loop switch-case code. 15 16 Note that this sketch is only designed for processing multiple BUTTON switches. However, 17 the switch definition and control struct(ure) ('struct switch_control') is designed to 18 support of other types of switch also, eg toggle switches. For purposes of this example 19 sketch parts of this control struct(ure) are not used. These aspects will be picked up 20 in other sketch examples. 21 22 The sketch layout is straight forward and process code for each button can be added 23 where indicated within the main loop, under the respective switch-case section for a 24 button switch. 25 26 Configurability: 27 1. Number of button switches - the implementation is such that each button switch is 28 allocated to a digital pin. The sketch will therefore support as many button 29 switches as a microcontroller can provide digital inputs. 30 This example sketch is configured, 'out-of-the-box' (OOTB)for six button switches, 31 but more may be added by: 32 33 a. changing the macro definition '#define num_switches' to be the number of buttons 34 switches to be connected 35 b. for each button switch, deciding its circuit type and allocating it to a digital pin 36 c. in the 'Switch to Pin Macro Definition List' adding new button switch macro 37 definitions, one for each additional button switch, 38 for example: '#define button_switch_? <pin number>' 39 d. in the 'Switch Control Sruct(ure) Declaration' adding further preset data to the 40 'switches' data struct(ure), for example: '...,button_switch_?, circuit_?,...', etc. 41 42 For a fuller appreciation of button switch fundementals see the tutorial 'Understanding 43 and Using Button Switches': 44 https://create.arduino.cc/projecthub/ronbentley1/understanding-and-using-button-switches-2ffe6c?ref=platform&ref_id=424_trending___&offset=2 45*/ 46// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 47// These declarations are specifically for defining and controlling the attached switches 48// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 49 50#define circuit_C1 INPUT // switch circuit requires an external pull down 10k ohm resistor 51#define circuit_C2 INPUT_PULLUP // switch type reqires no other components beyond the button switch 52 53#define debounce 10 // number of millisecs to wait for a switch to settle once activated 54#define switched true // signifies switch has been pressed/switch cycle complete 55 56#define button_switch 1 // differentiates switch type 57#define toggle_switch 2 // toggle switches are NOT used in this example sketch - future use 58 59#define num_switches 6 // number of button switches connected 60 61// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 62// % Switch to Pin Macro Definition List % 63// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 64// associate button swithes each with a digital pin. 65// add further definitions here if adding more switches 66// note that digital pins allocated are arbitary, any 67// available pin will do, or remove any not required. 68#define button_switch_1 2 69#define button_switch_2 3 70#define button_switch_3 4 71#define button_switch_4 5 72#define button_switch_5 6 73#define button_switch_6 7 74 75// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 76// % Switch Control Sruct(ure) Declaration % 77// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 78// now set up the configuration data for each individual 79// switch to be used by the switch read function and to 80// generally define the nature of the switch. 81struct switch_control { 82 int switch_type; // type of switch connected.NOT used in this sketch example - future use 83 int switch_pin; // digital input pin assigned to the switch 84 int circuit_type; // the type of circuit wired to the switch 85 bool switch_on; // the value relating to what "on" means, set up in the setup() function 86 bool switch_pending; // records if switch in transition or not 87 long unsigned int elapse_timer; // records debounce timer count when associated switch is in transition 88 bool switch_status; // current state of switch.NOT used in this sketch example - future use 89} switches[num_switches] = { 90 button_switch, button_switch_1, circuit_C2, LOW, false, 0, !switched, 91 button_switch, button_switch_2, circuit_C2, LOW, false, 0, !switched, 92 button_switch, button_switch_3, circuit_C2, LOW, false, 0, !switched, 93 button_switch, button_switch_4, circuit_C2, LOW, false, 0, !switched, 94 button_switch, button_switch_5, circuit_C2, LOW, false, 0, !switched, 95 button_switch, button_switch_6, circuit_C2, LOW, false, 0, !switched 96}; 97// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 98 99void setup() { 100 // initialise digital input switch pins 101 for (int sw = 0; sw < num_switches; sw++) { 102 // define the switch circuit type - circuit_type is: 103 // circuit_C1 (INPUT) or circuit_C2 (INPUT_PULLUP) 104 pinMode(switches[sw].switch_pin, switches[sw].circuit_type); 105 // establish 'meaning' for switch on/off depending on circuit type 106 if (switches[sw].circuit_type == circuit_C2) { 107 // switch is NOT configured with a pull down switch resistor 108 switches[sw].switch_on = LOW; // switch pin goes LOW when switch pressed, ie on 109 } else { 110 // circuit_type_C1, so switch IS configured with a pull down switch resistor 111 switches[sw].switch_on = HIGH; // switch pin goes HIGH when switch pressed, ie on 112 } 113 } 114 Serial.begin(115200); // dont forget to set your serial monitor speed to whatever is set here 115} 116 117void loop() { 118 // poll each connected switch in turn and, if switched, process its associated purpose 119 for (int sw = 0; sw < num_switches; sw++) { 120 if (read_switch(sw) == switched) { 121 // this switch (sw) has been pressed, so process via a case switch 122 Serial.print("\ 123button switch "); 124 Serial.print(sw + 1); 125 Serial.print(" on digital pin "); 126 byte button_pin = switches[sw].switch_pin; 127 Serial.println(button_pin); 128 // move to switch's associated code section 129 switch (button_pin) 130 { 131 case button_switch_1: 132 Serial.println("case statement 1 entered"); 133 break; 134 case button_switch_2: 135 Serial.println("case statement 2 entered"); break; 136 case button_switch_3: 137 Serial.println("case statement 3 entered"); 138 break; 139 case button_switch_4: 140 Serial.println("case statement 4 entered"); 141 break; 142 case button_switch_5: 143 Serial.println("case statement 5 entered"); 144 break; 145 case button_switch_6: 146 Serial.println("case statement 6 entered"); 147 break; 148 default: 149 // spurious switch index! Should never arise as this is controlled 150 // by the for loop within defined upper bound 151 break; 152 } 153 Serial.flush(); // flush out the output buffer 154 } 155 } 156 // pollng of the switches now complete until next cycle, so do other things here as required... 157 158 159 160} 161 162// 163// generic button switch read function. 164// reading is controlled by: 165// a. the function parameter which indicates which switch 166// is to be polled, and 167// b. the switch control struct(ure), referenced by a). 168// 169// note that this function works in a nonexclusive way 170// and incorporates debounce code 171// 172bool read_switch(int sw) { 173 int switch_pin_reading; 174 switch_pin_reading = digitalRead(switches[sw].switch_pin); 175 if (switch_pin_reading == switches[sw].switch_on) { 176 // switch is pressed (ON), so start/restart debounce process 177 switches[sw].switch_pending = true; 178 switches[sw].elapse_timer = millis(); // start elapse timing 179 return !switched; // now waiting for debounce to conclude 180 } 181 if (switches[sw].switch_pending && switch_pin_reading == !switches[sw].switch_on) { 182 // switch was pressed, now released (OFF), so check if debounce time elapsed 183 if (millis() - switches[sw].elapse_timer > debounce) { 184 // dounce time elapsed, so switch press cycle complete 185 switches[sw].switch_pending = false; 186 return switched; 187 } 188 } 189 return !switched; 190} 191
Comments
Only logged in users can leave comments