czwartek, 26 listopada 2015

Programowa oraz sprzętowa likwidacja drgań od przycisków

W tym poście opiszę sposób pozbycia się drgań jakie występują w trakcie wciśnięcia przycisku. 

Wstep


Przyciski nie zabezpieczone w żaden sposób powodują znaczne drgania, które mogą np. zliczyć za dużą liczbę wciśnięć. Spowodowane jest to drganiami styków w trakcie przełączania. Należy je w miarę możliwości eliminować czy to bezpośrednio w programie, czy poprzez dodanie dodatkowych elementów do schematu.


Sposób programowy


Te sposoby pozwalają na programową obsługę drgań styków. Jedną z zalet jest to, że ograniczona zostaje ilość elementów na schemacie, co przekłada się na koszty wykonania danego urządzenia. Minusem jest natomiast to, że zwiększona zostaje objętość programu, oraz tak naprawdę nie eliminuje się samego drgania tylko odpowiednio się je obsługuje, aby nie zostały wyłapane podczas przełączania.

Pierwszym sposobem właściwie najprostszym jest stosowanie zmiennej, która będzie się zmieniać po otrzymaniu sygnału od przycisku. Przez co zmiana jego stanu zostanie zablokowana.

//Zmienna wykorzystywana w przerwaniu
volatile uint8_t zabezpieczenie;
 
//Obsługa przerwania od przycisku
void EXTI1_IRQHandler(void)
{
//Jesli zgloszone przerwanie na linii
if (EXTI_GetITStatus(EXTI_Line1) != RESET) 
{
 //Jeśli zabezpieczenie = 0 oraz przycisk = 0 wtedy wykona program
 if (!zabezpieczenie && !(GPIO_ReadInputDataBit(Button_Off_Port, Button_Off_Pin)))
 {
    //Zmiana wartości przycisku
    zabezpieczenie=1;
    /*
       Wykonanie programu
    */
 }
 //Jesli zabezpieczenie = 1 oraz stan na pinie = 1 
 //zostanie wykonana nastepujaca petla
 else if (zabezpieczenie && (GPIO_ReadInputDataBit(Button_Off_Port, Button_Off_Pin))) 
 { 
    zabezpieczenie=0;
 }
 
    //wyczyszczenie flagi przerwania
    EXTI_ClearITPendingBit(EXTI_Line1);
 }
}

Drugi sposób polega na zastosowaniu pętli opóźniającej. Jeśli przycisk zostanie wciśnięty nastąpi odczekanie określoną ilość czasu, po czym program zacznie wykonywać dalsze zadania. Ma on za zadanie odczekanie, aż drgania z przycisku się ustabilizują.

//Obsługa przerwania od przycisku
void EXTI1_IRQHandler(void)
{
 //Jesli zgloszone przerwanie na linii
 if (EXTI_GetITStatus(EXTI_Line1) != RESET) 
 {
  //Pętla opóźniająca 20ms
  Delayms(20);
  if (!(GPIO_ReadInputDataBit(Button_Off_Port, Button_Off_Pin)))
  {
    /*
      Wykonanie programu
    */
  }
 
 //wyczyszczenie flagi przerwania
 EXTI_ClearITPendingBit(EXTI_Line1);
 }
}

Trzeci sposób działa na zasadzie sprawdzania stanu przycisku poprzedniego oraz teraźniejszego. Tym razem przykład przedstawiony dla Arduino. Jeśli po odczekaniu podanej wartości czasu przycisk nadal będzie wciśnięty nastąpi wykonanie programu w instrukcji if.

//Przechowuje informacje o stanach przycisków 
//poprzednim i teraźniejszym
boolean ostatniStan = HIGH;
boolean currentButton = HIGH;
 
boolean debounce(boolean ostatni)
{
  //odczytanie stanu przycisku
  boolean obecny = digitalRead(Przycisk);
  //Jesli stan sie zmienil
  if(ostatni != obecny)
  {
    //odczekaj
    delay(5);
    //sprawdz ponownie
    obecny = digitalRead(Przycisk);
  }
  //zwróć stan przycisku
  return obecny;
}
void setup()
{
  //Ustawienie pinów
}
 
void loop() 
{
  obecnyStan = debounce(ostaniStan);
  if(ostatniStan == HIGH && obecnyStan == LOW)
  {
    //wykonaj operacje
  }
  ostatniStan = obecnyStan;
}

Sposób sprzętowy


Jest to sposób trochę droższy, natomiast ułatwia i w znacznym stopniu upraszcza programowanie mikrokontrolera.

Sposób podstawowy podłączenia przycisku polega na dodaniu rezystora podciągającego do zasilania, przez co będzie wymuszany stan wysoki na pinie. Natomiast w momencie wciśnięcia, pin będzie zwierany do masy, po puszczeniu przycisku, zostanie wymuszany stan wysoki. Najlepiej do tego celu stosować dosyć duże rezystory np. 10kOhm aby maksymalnie zminimalizować prąd jaki popłynie przez ten element.


Rys. 1.1. Schemat podstawowy

Jest to najbardziej podstawowy sposób podłączenia przycisku. Jednak nie niweluje on zbytnio drgań jakie się na nim pojawią. 

Sposób drugi, zdecydowanie bardziej skuteczny, polega na dodaniu oprócz rezystora jeszcze kondensatora filtrującego. Będzie on niwelował drgania jakie wystąpią w momencie przełączania.


Rys. 1.2. Schemat rozszerzony 

Jednak i to rozwiązanie nie jest zbyt dobre. Z jednej strony drgania zostaną zmniejszone, natomiast z drugiej prąd jaki wystąpi podczas rozładowania kondensatora może uszkodzić elementy elektroniczne. W celu zniwelowania występujących zakłóceń z kondensatora należałoby ograniczyć prąd który się pojawi poprzez zastosowanie rezystora o wartości 100 ohm. Należy go podłączyć szeregowo z przyciskiem. 


Rys. 1.3. Schemat rozszerzony 2

Dodatkowo można dodać diodę zabezpieczającą pomiędzy wejściem mikrokontrolera a VCC. Pozwoli ona na dodatkowe zabezpieczenie przed zakłóceniami od zasilania.

Sposób przedstawiony na rysunku 1.3. działa bardzo dobrze w celu eliminacji zakłóceń. Natomiast zamiast przebiegu czystego prostokątnego otrzymuje się przebieg zaokrąglony tzn. nie opadający szybko do wartości 0.

Ostatni schemat polega na zastosowaniu odwracającego przerzutnika Schmitta. Pozwoli to na otrzymanie przebiegu czystego prostokątnego. Należy pamiętać, że taki przerzutnik odwróci nam wartość otrzymywaną z przycisku tzn. jeśli zwieramy do masy to na wejściu otrzymamy stan wysoki.

Oczywiście można także połączyć oba sposoby poprzez zastosowanie metod pośrednich z obu sposobów. Przez co można otrzymać przyzwoicie działającą obsługę całego układu. Przy stosowaniu najlepszej z każdych z tych metod, nie ma potrzeby aby je ze sobą wzajemnie łączyć.

Rys. 1.4. Schemat z przerzutnikiem schmitta