#define circuit_C2 INPUT_PULLUP // switch type reqires no other components beyond the button switch
#define debounce 10 // number of millisecs to wait for a switch to settle once activated
#define switched true // signifies switch has been pressed/switch cycle complete
#define button_switch 1 // differentiates switch type
#define num_switches 4 // number of button switches connected
int relay_1 = 4;
int relay_2 = 7;
int relay_3 = 8;
int relay_4 = 12;
int led_1 = 3;
int led_2 = 5;
int led_3 = 9;
int led_4 = 11;
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Switch to Pin Macro Definition List %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// associate button swithes each with a digital pin.
// add further definitions here if adding more switches
// note that digital pins allocated are arbitary, any
// available pin will do, or remove any not required.
#define button_switch_1 2
#define button_switch_2 6
#define button_switch_3 10
#define button_switch_4 13
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// % Switch Control Sruct(ure) Declaration %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// now set up the configuration data for each individual
// switch to be used by the switch read function and to
// generally define the nature of the switch.
struct switch_control {
// int switch_type; // type of switch connected.NOT used in this sketch example - future use
int switch_pin; // digital input pin assigned to the switch
int circuit_type; // the type of circuit wired to the switch
bool switch_on; // the value relating to what "on" means, set up in the setup() function
bool switch_pending; // records if switch in transition or not
long unsigned int elapse_timer; // records debounce timer count when associated switch is in transition
} switches[num_switches] = {
button_switch_1, circuit_C2, LOW, false, 0,
button_switch_2, circuit_C2, LOW, false, 0,
button_switch_3, circuit_C2, LOW, false, 0,
button_switch_4, circuit_C2, LOW, false, 0,
};
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void setup() {
pinMode(relay_1, OUTPUT);
pinMode(relay_2, OUTPUT);
pinMode(relay_3, OUTPUT);
pinMode(relay_4, OUTPUT);
pinMode(led_1, OUTPUT);
pinMode(led_2, OUTPUT);
pinMode(led_3, OUTPUT);
pinMode(led_4, OUTPUT);
for(int i=0; i<255; i++){
analogWrite(led_1, i);
analogWrite(led_2, i);
analogWrite(led_3, i);
analogWrite(led_4, i);
}
delay(500);
digitalWrite(led_1, LOW);
digitalWrite(led_2, LOW);
digitalWrite(led_3, LOW);
digitalWrite(led_4, LOW);
// initialise digital input switch pins
for (int sw = 0; sw < num_switches; sw++) {
// define the switch circuit type - circuit_type is:
pinMode(switches[sw].switch_pin, switches[sw].circuit_type);
// establish 'meaning' for switch on/off depending on circuit type
if (switches[sw].circuit_type == circuit_C2) {
// switch is NOT configured with a pull down switch resistor
switches[sw].switch_on = LOW; // switch pin goes LOW when switch pressed, ie on
}
}
//Serial.begin(115200); // dont forget to set your serial monitor speed to whatever is set here
}
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void loop() {
// poll each connected switch in turn and, if switched, process its associated purpose
for (int sw = 0; sw < num_switches; sw++) {
if (read_switch(sw) == switched) {
// this switch (sw) has been pressed, so process via a case switch
// Serial.print("\nbutton switch ");
// Serial.print(sw + 1);
// Serial.print(" on digital pin ");
byte button_pin = switches[sw].switch_pin;
// Serial.println(button_pin);
// move to switch's associated code section
switch (button_pin)
{
case button_switch_1:
if (digitalRead(relay_1)==LOW){
analogWrite(led_1, 100);
digitalWrite(relay_1, HIGH);}
else
if (digitalRead(relay_1)==HIGH){
digitalWrite(led_1, LOW);
digitalWrite(relay_1, LOW);}
// Serial.println("case statement 1 entered");
break;
case button_switch_2:
if (digitalRead(relay_2)==LOW){
digitalWrite(led_2, HIGH);
digitalWrite(relay_2, HIGH);}
else
if (digitalRead(relay_2)==HIGH){
digitalWrite(led_2, LOW);
digitalWrite(relay_2, LOW);}
// Serial.println("case statement 2 entered");
break;
case button_switch_3:
if (digitalRead(relay_3)==LOW){
digitalWrite(led_3, HIGH);
digitalWrite(relay_3, HIGH);}
else
if (digitalRead(relay_3)==HIGH){
digitalWrite(led_3, LOW);
digitalWrite(relay_3, LOW);}
// Serial.println("case statement 3 entered");
break;
case button_switch_4:
if (digitalRead(relay_4)==LOW){
digitalWrite(led_4, HIGH);
digitalWrite(relay_4, HIGH);}
else
if (digitalRead(relay_4)==HIGH){
digitalWrite(led_4, LOW);
digitalWrite(relay_4, LOW);}
// Serial.println("case statement 4 entered");
break;
default:
// spurious switch index! Should never arise as this is controlled
// by the for loop within defined upper bound
break;
}
Serial.flush(); // flush out the output buffer
}
}
}
//
// generic button switch read function.
// reading is controlled by:
// a. the function parameter which indicates which switch
// is to be polled, and
// b. the switch control struct(ure), referenced by a).
//
// note that this function works in a nonexclusive way
// and incorporates debounce code
//
bool read_switch(int sw) {
int switch_pin_reading;
switch_pin_reading = digitalRead(switches[sw].switch_pin);
if (switch_pin_reading == switches[sw].switch_on) {
// switch is pressed (ON), so start/restart debounce process
switches[sw].switch_pending = true;
switches[sw].elapse_timer = millis(); // start elapse timing
return !switched; // now waiting for debounce to conclude
}
if (switches[sw].switch_pending && switch_pin_reading == !switches[sw].switch_on) {
// switch was pressed, now released (OFF), so check if debounce time elapsed
if (millis() - switches[sw].elapse_timer > debounce) {
// dounce time elapsed, so switch press cycle complete
switches[sw].switch_pending = false;
return switched;
}
}
return !switched;
}