This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revision | |||
| de:examples:digi:switch_debounce [2011/10/11 15:44] – wittkoepper | de:examples:digi:switch_debounce [2020/07/20 12:00] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== Vermeidung von Kontaktprellung | ||
| + | //Vajalikud teadmised: [HW] [[en: | ||
| + | |||
| + | ===== Theorie ===== | ||
| + | |||
| + | [{{ : | ||
| + | |||
| + | Wie bereits im einleitenden Kapitel zu Schaltern erwähnt, gibt es im Ungang mit mechanischen Schaltern den Effekt des Prellens (ungewolltes, | ||
| + | |||
| + | |||
| + | [{{ : | ||
| + | |||
| + | Die bekannteste Methode zur Vermeidung von Kontaktprellung ist die Filtrierung. Dieses kann elektrisch oder durch Software erfolgen. Um elektrisch zu filtern muss der Schalter an einen Tiefpassfilter angeschlossen werden - zum Beispiel an einen RC Filter - welcher die Spannungschwankungen beseitigt sodass der Pin des Mikrocontrollers keine schwankenden Werte erhält. Ein solcher RC Filter ist auf der Zeichnung abgebildet. Filtrierung mittels Software wird durchgeführt, | ||
| + | |||
| + | |||
| + | ===== Praktisches Beispiel ===== | ||
| + | |||
| + | Elektrische Filtrierung wird für die HomeLab Schalter nicht verwendet, da hier die Beseitigung von Fehlschaltungen mit Hilfe von Software geübt werden soll. Die Übung besteht aus zwei Teilen. Das Ziel des ersten Teils ist, das Prellen der Schalter des digitalen Input/ | ||
| + | <code c> | ||
| + | // | ||
| + | // Das Programm um Kontaktprellung am digitalen Input/ | ||
| + | // | ||
| + | #include < | ||
| + | |||
| + | // | ||
| + | // Festlegung der LED-Pins und Schalter. | ||
| + | // | ||
| + | pin leds[3] = { PIN(C, 5), PIN(C, 4), PIN(C, 3) }; | ||
| + | pin button | ||
| + | |||
| + | // | ||
| + | // Hauptprogramm | ||
| + | // | ||
| + | int main(void) | ||
| + | { | ||
| + | unsigned char new_value, old_value = 0; | ||
| + | unsigned char index, counter = 0; | ||
| + | |||
| + | // LED-Pins als Output setzen. | ||
| + | for (index = 0; index < 3; index++) | ||
| + | { | ||
| + | pin_setup_output(leds[index]); | ||
| + | } | ||
| + | |||
| + | // Schalter-Pins als Input setzen. | ||
| + | pin_setup_input(button); | ||
| + | |||
| + | // Endlosschleife | ||
| + | while (true) | ||
| + | { | ||
| + | // Status des Schalters auslesen. | ||
| + | new_value = pin_get_value(button); | ||
| + | |||
| + | // Kontolle, ob der Schalter heruntergedrückt wurde, | ||
| + | // was bedeutet, dass der neue Status 1 ist, der alte 0. | ||
| + | if ((new_value) && (!old_value)) | ||
| + | { | ||
| + | // Erweiterung des Lesegerätes und Nutzungvon Modul 3 | ||
| + | counter = (counter + 1) % 3; | ||
| + | |||
| + | // Aufleuchten der LED, welche mit dem Wert des Lesegerätes übereinstimmt. | ||
| + | for (index = 0; index < 3; index++) | ||
| + | { | ||
| + | pin_set_to(leds[index], | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // Berücksichtigung des alten Status. | ||
| + | old_value = new_value; | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Es gibt diverse Softwarelösungen zur Filtrierung. Sie können einfach oder komplex sein, wobei jede ihre Vor- und Nachteile hat. Sieht das Programm nur wenige seltene Betätigungen des Schalters vor, kann eine lange Pause als Folge der Betätigung eingefügt werden. Auf diese Weise können durch Kontaktprellung verursachte Wirkungen auf die Schaltung vermieden werden. Jedoch muss bei Anwendung dieser Lösung bedacht werden, dass, sofern der Nutzer den Schalter für eine längere Zeit gedrückt hält, das Programm ebenfalls auf die Fehlschaltung, | ||
| + | |||
| + | <code c> | ||
| + | // | ||
| + | // Funktion zum Auslesen filtrierter Werte aus dem I/O Erweiterungsmodul. | ||
| + | // | ||
| + | unsigned char pin_get_debounced_value(pin button) | ||
| + | { | ||
| + | unsigned char buffer = 0xAA; | ||
| + | unsigned char timeout = 100; | ||
| + | |||
| + | // Abwarten, bis der Status des Schalters 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 definitely pressed down | ||
| + | if (buffer == 0xFF) | ||
| + | { | ||
| + | return 1; | ||
| + | } | ||
| + | |||
| + | // If all 8 bits are low, then the button is definitely up. | ||
| + | if (buffer == 0x00) | ||
| + | { | ||
| + | return 0; | ||
| + | } | ||
| + | |||
| + | // 1 ms break. | ||
| + | // This function can be found from the library of the HomeLab. | ||
| + | sw_delay_ms(1); | ||
| + | } | ||
| + | |||
| + | // If we can not examine the state, then we assume that the button was not pressed. | ||
| + | return 0; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Diese Funktion generiert eine Verzögerung durch Nutzung einer Funktion, die in der entsprechenden Übung erläutert wurde. Zu dieser Zeit müssen wir nur wissen, dass die Verzögerungsfunktion eine Verzögerung von 1 ms am Ende jedes Zyklus generiert, um den Status des Schalters lesen zu können. Befindet sich der Schalter 8 Lesezyklen lang in der gleichen Position, | ||
| + | |||
| + | <code c> | ||
| + | // | ||
| + | // The program for filtering the debounce of buttons of Digital i/o module. | ||
| + | // | ||
| + | #include < | ||
| + | #include < | ||
| + | |||
| + | // | ||
| + | // Determining pins of LEDs 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 the pins of LEDs as outputs. | ||
| + | for (index = 0; index < 3; index++) | ||
| + | { | ||
| + | pin_setup_output(leds[index]); | ||
| + | } | ||
| + | |||
| + | // Setting the pins of button as input. | ||
| + | pin_setup_input(button); | ||
| + | |||
| + | // Endless loop. | ||
| + | while (true) | ||
| + | { | ||
| + | // Reading the state of the button. | ||
| + | new_value = pin_get_debounced_value(button); | ||
| + | |||
| + | // Control whether the button was pressed down, that means, | ||
| + | // is the new state 1 and the old state 0. | ||
| + | if ((!new_value) && (old_value)) | ||
| + | { | ||
| + | // Widening the counter and taking module number 3. | ||
| + | counter = (counter + 1) % 3; | ||
| + | |||
| + | // Lighting the LED witch corresponds to the value of the counter. | ||
| + | for (index = 0; index < 3; index++) | ||
| + | { | ||
| + | pin_set_to(leds[index], | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // Remember the old state. | ||
| + | old_value = new_value; | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Testen wir das Programm nun, leuchten die LEDs in genau der Sequenz auf, in welcher der Nutzer den Schalter betätigt. | ||