This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
en:examples:digi:switch_debounce [2010/02/07 07:58] – priitj | en:examples:digi:switch_debounce [2015/03/05 10:26] (current) – removed raivo.sell | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Filtration of switch debounce | ||
- | //Vajalikud teadmised: [HW] [[en: | ||
- | |||
- | ===== Theory ===== | ||
- | |||
- | [{{ : | ||
- | |||
- | As in the introductory chapter about switches was said, there is a problem called debouncing when we are dealing with mechanical switches or flickering. Because contacts are made of metal, what is a bit elastic, on the moment of connecting or disconnecting contacts are bouncing and it results in quite a lot of misswitchings. The number and duration of these switchings depends on the switch, but it is usually about some milliseconds. If the switch is used to start some electrical device it is not so big issue, but if the switch is used to control some device multiple switching may be harmful. | ||
- | |||
- | |||
- | [{{ : | ||
- | |||
- | Main method to avoid flickering is filtering. Filtering can be done by electrically and with software. To filter electrically there must be a low-pass filter after switch – for example a RC filter – witch anti aliases changes of voltage and therefore the pin of micro controller does not have momentary values. //RC filter is shown on the drawing//. Filtering using software is done so that the value of the pin where the switch is connected is assessed on several moments and if this value is the same on every assessment the conclusion is made that the switch is in steady position and there is no flickering. But when filtering delay for assessing the position must be taken into account. | ||
- | |||
- | |||
- | ===== Practice ===== | ||
- | |||
- | We do not use electrical filtering on home lab’s switches, because in this case we could not practice the exercise of eliminating misswitching with software. The exercise is in two parts. The goal of the first part is to demonstrate the debouncing of digital input-output module’s switches. The following program is for this, each pressing on the button lights next LED. Misswitching causes LED to light several times and it seems that LED lights arbitrarily. | ||
- | <code c> | ||
- | // | ||
- | // The Program for demonstrating switch debounce on digital input-output module of home lab. | ||
- | // | ||
- | #include < | ||
- | |||
- | // | ||
- | // ˇDetermining pins of LED-s and buttons. | ||
- | // | ||
- | pin leds[3] = { PIN(C, 5), PIN(C, 4), PIN(C, 3) }; | ||
- | pin button | ||
- | |||
- | // | ||
- | // Main program | ||
- | // | ||
- | int main(void) | ||
- | { | ||
- | unsigned char new_value, old_value = 0; | ||
- | unsigned char index, counter = 0; | ||
- | |||
- | // Setting LED pins as output. | ||
- | for (index = 0; index < 3; index++) | ||
- | { | ||
- | pin_setup_output(leds[index]); | ||
- | } | ||
- | |||
- | // Setting button' | ||
- | pin_setup_input(button); | ||
- | |||
- | // Endless loop | ||
- | while (true) | ||
- | { | ||
- | // Reading the state of the button. | ||
- | new_value = pin_get_value(button); | ||
- | |||
- | // Control, wether the button is pushed down, | ||
- | // that means is the new state 1 and old 0. | ||
- | if ((new_value) && (!old_value)) | ||
- | { | ||
- | // Enlarging the reader and taking module 3 | ||
- | counter = (counter + 1) % 3; | ||
- | |||
- | // Lighting LED witch corresponds to the value of the reader. | ||
- | for (index = 0; index < 3; index++) | ||
- | { | ||
- | pin_set_to(leds[index], | ||
- | } | ||
- | } | ||
- | |||
- | // Remember the old state. | ||
- | old_value = new_value; | ||
- | } | ||
- | } | ||
- | </ | ||
- | |||
- | There are several methods to filter using software. It can be done easy way or complex way each way has advantages and defects. If the program is such that pressing the button is seldom, there may be a long pause after registering pushing the button, this excludes reaction on the switching caused by debounce. When using that solution one thing must be taken into account – if the user holds the button down for a long time, the program reacts also on misswitching caused by releasing the button. Dependable is such program witch controls the state of the switch several times after certain time periods (the more and longer time the merrier). The following is a function for reading filtered values of a button of digital input-output expansion module. | ||
- | |||
- | <code c> | ||
- | // | ||
- | // Funktsioon mõne IO laiendusplaadi lüliti filtreeritud väärtuse lugemiseks | ||
- | // | ||
- | unsigned char pin_get_debounced_value(pin button) | ||
- | { | ||
- | unsigned char buffer = 0xAA; | ||
- | unsigned char timeout = 100; | ||
- | |||
- | // Ootame, kuni nupu olek on selgunud või oleku selgitamine aegunud | ||
- | while (timeout-- > 0) | ||
- | { | ||
- | // 8-kohalise (bitise) olekupuhvri pidamine | ||
- | // Kõik eelmised olekud (bitid) nihutatakse vasakule | ||
- | // ja paremale lisatakse uus olek (bitt). | ||
- | buffer <<= 1; | ||
- | buffer |= (pin_get_value(button) ? 0x01 : 0x00); | ||
- | |||
- | // Kui kõik 8 bitti on kõrged, siis | ||
- | // nupp on kindlasti alla vajutatud | ||
- | if (buffer == 0xFF) | ||
- | { | ||
- | return 1; | ||
- | } | ||
- | |||
- | // Kui kõik 8 bitti on madalad, siis | ||
- | // nupp on kindlasti üleval | ||
- | if (buffer == 0x00) | ||
- | { | ||
- | return 0; | ||
- | } | ||
- | |||
- | // Paus 1 millisekund | ||
- | // See funktsioon sisaldub kodulabori teegis | ||
- | sw_delay_ms(1); | ||
- | } | ||
- | |||
- | // Kui olekut ei õnnestunud välja selgitada, siis oletame, | ||
- | // et nuppu ei vajutatud | ||
- | return 0; | ||
- | } | ||
- | </ | ||
- | |||
- | See funktsioon kasutab viite tekitamise funktsiooni, | ||
- | |||
- | <code c> | ||
- | // | ||
- | // Kodulabori digitaalse sisend-väljundmooduli | ||
- | // nuppude põrkumise filtreerimise programm. | ||
- | // | ||
- | #include < | ||
- | #include < | ||
- | |||
- | // | ||
- | // LED-ide ja nupu viikude määramine | ||
- | // | ||
- | pin leds[3] = { PIN(C, 5), PIN(C, 4), PIN(C, 3) }; | ||
- | pin button | ||
- | |||
- | // | ||
- | // Põhiprogramm | ||
- | // | ||
- | int main(void) | ||
- | { | ||
- | unsigned char new_value, old_value = 0; | ||
- | unsigned char index, counter = 0; | ||
- | |||
- | // LED-ide viikude väljundiks seadmine | ||
- | for (index = 0; index < 3; index++) | ||
- | { | ||
- | pin_setup_output(leds[index]); | ||
- | } | ||
- | |||
- | // Nupu viigu sisendiks määramine | ||
- | pin_setup_input(button); | ||
- | |||
- | // Lõputu tsükkel | ||
- | while (true) | ||
- | { | ||
- | // Nupu oleku lugemine | ||
- | new_value = pin_get_debounced_value(button); | ||
- | |||
- | // Kontroll, kas nupp vajutati alla, | ||
- | // ehk kas uus olek on 1 ja vana 0 | ||
- | if ((!new_value) && (old_value)) | ||
- | { | ||
- | // Loenduri suurendamine ja mooduli 3 võtmine | ||
- | counter = (counter + 1) % 3; | ||
- | |||
- | // Loenduri väärtusele vastava LED süütamine | ||
- | for (index = 0; index < 3; index++) | ||
- | { | ||
- | pin_set_to(leds[index], | ||
- | } | ||
- | } | ||
- | |||
- | // Peame vana olekut meeles | ||
- | old_value = new_value; | ||
- | } | ||
- | } | ||
- | </ | ||
- | |||
- | Kui nüüd programmi proovida, siis LED-id süttivad täpselt sellises järjekorras nagu kasutaja nupplülitit vajutab. |