This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| et:examples:digi:switch_debounce [2010/02/10 16:39] – external edit 127.0.0.1 | et:examples:digi:switch_debounce [2020/07/20 12:00] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== Lüliti põrkumise filtreerimine ====== | ||
| + | //Vajalikud teadmised: [HW] [[et: | ||
| + | |||
| + | ===== Teooria ===== | ||
| + | |||
| + | [{{ : | ||
| + | |||
| + | Nii nagu lüliteid tutvustavas peatükis öeldud, eksisteerib mehhaaniliste lülititega kontaktide põrkumise probleem. Kuna kontaktid on tehtud metallist, millel on teatav elastsus, siis kontaktide ühendamise või lahti-ühendamise hetkel need põrkuvad ning tulemusena tekib hulga väärlülitusi. Lülituste arv ja kestus sõltub lülitist, kuid enamasti jääb see mõne millisekundi piiresse. Kui lülitit kasutatakse mõne elektriseadme käivitamiseks, | ||
| + | |||
| + | [{{ : | ||
| + | |||
| + | Põhiline kontaktide põrkumisest tekkinud väärlülitusi välistav meetod on filtreerimine. Filtreerida saab nii elektriliselt kui ka tarkvaraliselt. Elektriliseks filtreerimiseks tuleb lüliti ühendada läbi madalpääsu filtri – näiteks RC filter - mis silub pingemuutusi ja sellest tulenevalt ei omanda mikrokontrolleri viik hetkelisi väärtusi. Tarkvaraline filtreerimine toimub põhimõttel, | ||
| + | |||
| + | ===== Praktika ===== | ||
| + | |||
| + | Kodulabori lülititel ei kasutada elektrilist filtreerimist, | ||
| + | |||
| + | <code c> | ||
| + | // | ||
| + | // Kodulabori digitaalse sisend-väljundmooduli | ||
| + | // nuppude kontaktide põrkumise demonstreerimise programm. | ||
| + | // | ||
| + | #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_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-i süütamine | ||
| + | for (index = 0; index < 3; index++) | ||
| + | { | ||
| + | pin_set_to(leds[index], | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // Peame vana olekut meeles | ||
| + | old_value = new_value; | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Tarkvaraliseks filtreerimiseks on mitmeid meetodeid. Seda võib teha lihtsalt ja keeruliselt, | ||
| + | |||
| + | < | ||
| + | |||
| + | Töökindlam on programm, mis kontrollib nupu olekut teatud aja jooksul mitu korda (mida rohkem ja mida pikema aja jooksul, seda kindlam). Järgnevalt on toodud Digitaalse sisend-väljundmooduli nupu filtreeritud väärtuse lugemise funktsioon: | ||
| + | |||
| + | <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 kontaktide 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. | ||