Table of Contents

Switch

Neccesary knowledge: [HW] User Interface Module, [AVR] Registers, [AVR] Digital Inputs/Outputs, [LIB] Pins, [PRT] Light-emitting Diode

Theory

A switch is an electromagnetic device which can connect or break an electrical circuit. There are many different types of switches; the most common mechanical switch is mechanically connectible electrical connectors. If connectors are connected, electrical circuit is closed and electricity can flow through the switch. If connectors are disconnected, electricity cannot flow through the switch.

Switches are commonly used to electrify electrical circuits, but can also be used as sensors. Switch as a sensor is also the subject of this exercise and therefore examining specific high-voltage and high-amperage switches has been excluded. Switches can be differentiated by the number of contacts and by their connection method. Different types include: two contact switches and double switches, where contact pairs are connected, but also push button, sliding, rocker and toggle switches as well as switches which disconnect instead of connect electrical circuit.

Different schematic symbols are used for identifying different types of switches. Below are examples of typical electrical switches used in electrical drawings with their symbols:

Push button switch Toggle switch Rocker switch Micro switch DIL switch

In order to use a switch as a sensor connected to a microcontroller, one contact of the switch is connected to the microcontrollers pin and is set as input in the program. If contact is connected to the ground or input potential, the bus’s bit rate of microcontroller’s pin is changed. It would sound logical to use toggle switch, which allows connecting one contact with desired contact (in this case ground or input). For our purpose it is not as simple, since on the moment of shifting of the connections the contacts are not connected. The moment itself is very short (milliseconds), but during this moment microcontrollers input pin is connected to nowhere and therefore has indefinite value. Due to electromagnetic interference (which exists everywhere) input pin that is connected to nowhere can have a value of 0 or 1 at random moments in time.

The interferences complicate the usage of switches. Most common method for avoiding the undetermined results is to connect microcontroller’s input to the ground or input potential through a resistor. A resistor for this function is called pull-down or pull-up resistor. Usually the resistance of pull-down or pull-up resistor varies from 1 kΩ to 1 MΩ. With open switch, the input is charged with voltage of the resistor, by closing the switch, the input receives the voltage of the switch since the resistivity of the switch is a lot smaller (close to zero) compared to the one of the resistor. Basically it can be referred to as a volt-box.

Switch connection scheme with pull-up resistor

A simple two contact switch can be used as a sensor with pull-up or pull-down resistor, switch connects input with one and resistor to the other potential. Usually microcontrollers have built-in pull-up or pull-down resistor option; therefore, there is no need to add a resistor to the circuit. For example, AVR microcontrollers have 20 kΩ – 50 kΩ pull-up resistors on their IO pins. It must be mentioned that, mechanical switches have one more problem – switch bounce. This causes several very short missconnections at the moment of connection. It must be emphasized, that the examples used in this chapter are not affected by the switch bounce and the issue will be covered in more detail in the next chapter.

Practice

There are three push button-switches on the User interface module. Those switches connect the pins of microcontroller to the earth, however not directly through a resistor, this is to avoid short circuiting when pressing the button while setting the pins as output. The switches have also pull-up resistors, but those have much greater resistance than protective resistors, therefore while pressing the button, there will still be approximately 0 V voltages on the corresponding pin.

The switches are on PC0, PC1 and PC2 pins. In order to read the status of the switches, the corresponding pins of the microcontroller must be set as inputs. There is no need to put AVR internal pull-up resistors into operation, because the pins already have external resistors. When the button is pressed down, the corresponding bus of the pin has value 0, when the button is released, the value is 1. LED indicators can be used to see if the microcontroller understood the buttons action.

Sample code for using buttons is based on the HomeLab pins library, which was introduced in the example of LED.

//
// Homelab User interface board button test code
//
#include <homelab/pin.h>
 
//
// Main program
//
int main(void)
{
	// Set LED pins as output and switch pins as input
	pin_setup_output(led_green);
	pin_setup_input(S1);
 
	// Endless loop
	while (true)
	{
		// green LED turns on when switch S1 is pressed
		if(pin_get_value(S1) == 1)
		{
			pin_set(led_green);
		}
		else
		{
			pin_clear(led_green);
		}
	}
}

Filtration of switch bounce

Bouncing of contacts of a switch

As mentioned in the introductory chapter of switches, there exists an issue of bouncing or flickering when dealing with mechanical switches. Problem arises since contacts are made of metal which has some elasticity, at the moment of connecting or disconnecting the contacts bounce and this results in number of false switching’s. The number and duration of the switching's depends on the switch, but usually fits between just few milliseconds. In case a switch is used to start an electrical device it is not considered as a big issue but if the switch is used for controlling a device, multiple switching’s may turn out to be harmful for the device.

RC-filter of a switch

Main method used for avoiding flickering caused by the bouncing of contacts is filtering. Filtering can be done electrically or by software. To filter electrically the switch must be connected through a low-pass filter – for example a RC filter – witch smoothed changes of voltage and therefore the pin of microcontroller does not have transient values. RC filter is shown on the drawing. Filtering by software is done by assessing the value of the pin where the switch is connected; if the value remains the same at number of times in pre set time limit, it is considered to have a steady position and hence has no flickering problem. However, with each type of filtering a delay factor in defining the status must be taken under consideration.

Practice

Electrical filtering is not used on HomeLab switches, since it would not allow practicing the elimination of miss switching’s with software. The exercise is in two parts. The goal of the first part is to demonstrate the bouncing of User interface module switches. The following program is used for this; each pressing on the button will light the next LED in line. Wrongly pressed button will causes LEDs to light several times and it appears as the LEDs light randomly.

//
// Homelab User interface board switch debounce test program
//
#include <homelab/pin.h>
 
//
// Main program
//
int main(void)
{
	int counter = 0;
 
	// Set LED pins as output and switch pin as input
	pin_setup_output(led_red);
	pin_setup_output(led_yellow);
	pin_setup_output(led_green);
 
	pin_setup_input(S1);
 
	// Endless loop
	while(1)
	{
		// Check if switch S1 is pressed
		if(pin_get_value(S1) == 0)
		{
			// Light the corresponding LED
			if(counter == 0)	led_on(led_green);
			else			led_off(led_green);
			if(counter == 1)	led_on(led_yellow);
			else			led_off(led_yellow);
			if(counter == 2)	led_on(led_red);
			else			led_off(led_red);
 
			// Add counter and take a module
			counter = (counter + 1) % 3;
 
			// Wait until switch is unpressed
			while(pin_get_value(S1) == 0);
		}
	}
}

Several software solutions are used for filtering, this can be performed either easy or complex way both with its advantages and disadvantages. If the program is set to have only few infrequent pressings of the button, a long pause can be set to follow the pressing, this will rule out reaction to the switching caused by bounce. However, while using this solution must be considered – in case the user holds the button down for a long period of time, the program reacts also on the miss witching caused by the release of the button. A program which controls the state of the switch several times in fixed period of time is more dependable (the longer is the time and the higher is the number of controls performed, the better is the result). Below is a function for reading filtered values of a button for User interface module:

//
// Function for reading filtered values of a IO extension module.
//
unsigned char button_read(pin button)
{
	unsigned char buffer = 0xAA;	
	unsigned char timeout = 100;
 
	// We wait until the status of the button is celar 
	// or clearing the state expires
	while (timeout-- > 0)
	{
		// Having 8 place (bit) bufffer of state.
		// All previous states (bits) are shifted to left
		// and a new state(bit) is added to the right.
		buffer <<= 1;
		buffer |= (pin_get_value(button) ? 0x01 : 0x00);
 
		// If all 8 bits are high, then the button is pressed down
		if (buffer == 0xFF)
		{
			return 0;
		}
 
		// If all 8 bits are low, then the button is definitely up.
		if (buffer == 0x00)
		{
			return 1;
		}
 
		// 1 ms break.
		// This function can be found from the library of the HomeLab.
		_delay_ms(1);
	}
 
	// If can't examine the state, then assume that button was not pressed.
	return 0;
}

wfjsölfjsäöadflksöä

//
// The program for filtering the debounce of buttons of User interface module.
//
#include <homelab/pin.h>
 
//
// Main program
//
int main(void)
{
	int counter = 0;
 
	// Set LED pins as output and switch pin as input
	pin_setup_output(led_red);
	pin_setup_output(led_yellow);
	pin_setup_output(led_green);
 
	pin_setup_input(S1);
 
	// Endless loop
	while(1)
	{
		// Check if switch S1 is pressed
		if(button_read(S1))
		{
			// Light the corresponding LED
			if(counter == 0)	led_on(led_green);
			else			led_off(led_green);
			if(counter == 1)	led_on(led_yellow);
			else			led_off(led_yellow);
			if(counter == 2)	led_on(led_red);
			else			led_off(led_red);
 
			// Add counter and take a module
			counter = (counter + 1) % 3;
 
			// Wait until switch is unpressed
			while(pin_get_value(S1) == 0);
		}
	}
}

If we test this program now, the LEDs are lighting exactly in this sequence as the user is pressing the switch.