/*
There is a tactile switch and LED connected to Arduino Nano. The LED is off initially.
Depending on switch press, the LED blinks in following way.
1st Switch press: LED blinks at frequency of 0.5 Hz.
2nd Switch press: LED blinks at frequency of 1 Hz.
3rd Switch press: LED blinks at frequency of 2 Hz.
4th Switch press: LED turns off. Reset the Switch Press Counter. Repeat.
*/
#include "TimerOne.h"
#define RESET 0 // Constant for flags
#define SET !RESET // Constant for flags
#define SWITCH_PIN 3 // Defining switch input pin as pin 3 of Arduino Nano because it has interrupt available
#define LED_PIN 13 // Defining output for LED blinking as pin 13 of Arduino Nano because LED is at pin 13 on board
#define REFERENCE_TIME 1000000 // 1000000 us that is 1 second of reference time is set based on which different
// constants are set
#define SWITCH_DEBOUNCE_FREQUENCY 20 // 50 ms time that is 20 Hz frequency is set for testing valid switch input
#define TIMER_ONE_INTERRUPT_TIME 10 // Timer 1 interrupt occurance time in us
#define SWITCH_DEBOUNCE_TIME_LIMIT (REFERENCE_TIME / SWITCH_DEBOUNCE_FREQUENCY) / TIMER_ONE_INTERRUPT_TIME // Switch // debounce time limit count for correct switch press detection
#define LED_PIN_TOGGLE_TIME_TWO_Hz (REFERENCE_TIME / 2) / TIMER_ONE_INTERRUPT_TIME // Output LED toggle time count
// for 2 Hz of blinking
#define LED_PIN_TOGGLE_TIME_ONE_Hz REFERENCE_TIME / TIMER_ONE_INTERRUPT_TIME // Output LED toggle time count for 1 Hz // of blinking
#define LED_PIN_TOGGLE_TIME_HALF_Hz (REFERENCE_TIME * 2) / TIMER_ONE_INTERRUPT_TIME // Output LED toggle time count // for 0.5 Hz of blinking
#define LED_PIN_OFF digitalWrite(LED_PIN, LOW) // Switching LED Off
#define LED_PIN_TOGGLE digitalWrite(LED_PIN, !digitalRead(LED_PIN)) // Toggling LED
uint16_t switch_pressed_counter = 0;
uint32_t led_pin_toggle_counter = 0; // Counter for LED blinking which, when reaches to specific limit based on
// operation, resets
uint8_t led_blink_frequency_counter = 0; // Counter for deciding the LED Blinking frequency, which resets after
// being greater than 3
bool switch_current_state = HIGH; // Variable that stores the current state of the digital input pin 3 by reading
// its value, set to HIGH because HIGH indicates the switch is open
bool switch_previous_state = HIGH; // Variable used for switch debouncing correction, set to HIGH because HIGH
// indicates the switch is open
bool switch_interrupt_flag = RESET; // Flag that is polled in the Timer ISR to decide whether the switch is pressed
bool switch_pressed_flag = RESET; // Once the switch_interrupt_flag becomes TRUE, this flag becomes TRUE and gets
// reset to FALSE after SWITCH_DEBOUNCE_TIME_LIMIT
void timer_one_isr(void)
{
if(switch_interrupt_flag == SET) // Falling Edge detected at Pin 3
{
switch_interrupt_flag = RESET; // Resetting the switch interrupt flag
switch_current_state = digitalRead(SWITCH_PIN); // Reading Switch Pin 3 and storing
if(switch_current_state == LOW) // The state of the Pin 3 has to be LOW to proceed further
{
switch_pressed_flag = SET; // Flag is set to correct switch debounce
switch_previous_state = switch_current_state; // Reference is stored to check switch debounce later
}
}
if(switch_pressed_flag == SET) // Polling the flag to re-enter for cofirming correct switch input entry
// everytime till SWITCH_DEBOUNCE_TIME_LIMIT is reached
{
switch_pressed_counter++; // Increment the counter till SWITCH_DEBOUNCE_TIME_LIMIT
if(switch_pressed_counter >= SWITCH_DEBOUNCE_TIME_LIMIT) // SWITCH_DEBOUNCE_TIME_LIMIT is achieved
{
switch_current_state = digitalRead(SWITCH_PIN); // Reading Switch Pin 3 and storing
if(switch_current_state == switch_previous_state) // Comparing the reading with the stored
// reference value
{
led_blink_frequency_counter++; // Switch press is valid and hence increment a counter
// the value of which decides the frequency of LED Blinking
}
switch_pressed_flag = RESET; // Reset the flag
switch_previous_state = HIGH; // Reset the reference value to HIGH because HIGH indicates
// the switch is open
switch_current_state = HIGH; // Reset the current reading value to HIGH because HIGH indicates
// the switch is open
switch_pressed_counter = 0; // Reset the counter
}
}
switch(led_blink_frequency_counter) // Taking the counter in switch statement - it has values 0, 1, 2 and 3
{
case 1:
led_pin_toggle_counter++; // Incrementing the counter till LED_PIN_TOGGLE_TIME_HALF_Hz
// that makes LED Blinking Time 2000 ms
if(led_pin_toggle_counter >= LED_PIN_TOGGLE_TIME_HALF_Hz) // Counter has reached the value
// LED_PIN_TOGGLE_TIME_HALF_Hz
{
led_pin_toggle_counter = 0; // Resetting the counter
LED_PIN_TOGGLE; // Toggling the LED
}
break;
case 2:
led_pin_toggle_counter++; // Incrementing the counter till LED_PIN_TOGGLE_TIME_ONE_Hz
// that makes LED Blinking Time 1000 ms
if(led_pin_toggle_counter >= LED_PIN_TOGGLE_TIME_ONE_Hz) // Counter has reached the value // LED_PIN_TOGGLE_TIME_ONE_Hz
{
led_pin_toggle_counter = 0; // Resetting the counter
LED_PIN_TOGGLE; // Toggling the LED
}
break;
case 3:
led_pin_toggle_counter++; // Incrementing the counter till LED_PIN_TOGGLE_TIME_TWO_Hz
// that makes LED Blinking Time 500 ms
if(led_pin_toggle_counter >= LED_PIN_TOGGLE_TIME_TWO_Hz) // Counter has reached the value
// LED_PIN_TOGGLE_TIME_TWO_Hz
{
led_pin_toggle_counter = 0; // Resetting the counter
LED_PIN_TOGGLE; // Toggling the LED
}
break;
default:
led_pin_toggle_counter = 0; // Resetting the counter
led_blink_frequency_counter = 0; // Resetting the counter
LED_PIN_OFF; // Switching the LED Off
break;
}
}
void switch_input_isr(void)
{
switch_interrupt_flag = SET; // flag is set as FALLING Edge is detected
}
void setup()
{
pinMode (SWITCH_PIN , INPUT_PULLUP); // Pin 3 as Digital Input with internal pull up because
// the switch is placed in such a way that when pressed,
// Pin 3 connects to ground
pinMode(LED_PIN, OUTPUT); // Pin 13 which connected to the On-Board LED is set as output pin
LED_PIN_OFF; // Switching LED Off as initialization
Timer1.initialize(TIMER_ONE_INTERRUPT_TIME); // Initializing Timer 1 with
// Timer overflow time as TIMER_ONE_INTERRUPT_TIME
Timer1.attachInterrupt(timer_one_isr); // Taking 'timer_one_isr' as ISR
attachInterrupt(digitalPinToInterrupt(SWITCH_PIN),switch_input_isr,FALLING); // Setting the digital input
// interrupt at Pin 3
// with the mode
// set for FALLING Edge
TIMSK1 = _BV(TOIE1); // sets the timer 1 overflow interrupt enable bit
}
void loop()
{
}