Skocz do zawartości

Przerwania, a ponowne sprawdzenie stanu przycisku.


SOYER

Pomocna odpowiedź

Cześć, taki problem, a właściwie próba jego obejścia.

Czujnik dotykowy, w pewnych okolicznościach(prawdopodobnie  wpływ głośnika), choć nie zawsze, esp32 dostaje impuls z tego czujnika, choć fizycznie nie jest "naciskany".

W kodzie czujnik ten obsługuję za pomocą przerwania.

Nie chce mi się chwilowo rozlutowywać układu i go izolować od różnych "wpływów" tym bardziej, że nie jestem pewny efektu.

Jak, używając przerwań do czytania czujnika, sprawić by kod sprawdził czy np. po 100ms przycisk jest nadal naciśnięty i wtedy odpalić odpowiednią procedurę.

Po prostu po wywołaniu przerwania i odczekaniu 100ms dać jeszcze digitalRead?

Inne pomysły mile widziane.

Edytowano przez SOYER
Link do komentarza
Share on other sites

(edytowany)

Flagę teraz ustawiam w przerwaniu, potem na podstawie flagi robię co trzeba.

Czyli standard, na podstawie tej flagi z przerwania zrobić jeszcze digitalRead i potem dopiero akcja bądź nie.

Jutro to sprawdzę.

Edytowano przez SOYER
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

1 godzinę temu, SOYER napisał:

Czyli standard, na podstawie tej flagi z przerwania zrobić jeszcze digitalRead i potem dopiero akcja bądź nie.

Można tak, ale ja bym zrobił trochę inaczej.

uint8_t flaga=0;
const uint8_t ilosc = 2; // ile trzeba zliczyć aby zadziałało

void IRAM_ATTR przerwanie()
{
  if (digitalRead(cośtam)) 
    if (flaga < ilosc) flaga++; // liczymy dotyk
  }
  else {
    if (flaga != ilosc) flaga = 0; // to był impuls
  }
}

// w kodzie
      
if (flaga == ilosc) {
  rób_coś();
  flaga = ilosc+1; // czekaj na puszczenie dotyku
}
      

 

Link do komentarza
Share on other sites

@ethanak ja wiem, że Ty zawsze tak kombinujesz, że nic z tego nie rozumiem, ale tym razem... nic z tego nie rozumiem.

1 godzinę temu, ethanak napisał:
if (digitalRead(cośtam)) 
    if (flaga < ilosc) flaga++; // liczymy dotyk
  }
  else {
    if (flaga != ilosc) flaga = 0; // to był impuls

już nie piszę o nawiasach, ale jeśli jest spełniony ten warunek:

1 godzinę temu, ethanak napisał:
(flaga < ilosc)

to ten też jest spełniony:

1 godzinę temu, ethanak napisał:
(flaga != ilosc)

Zaś tego to już całkiem nie pojmuję:

1 godzinę temu, ethanak napisał:
if (flaga == ilosc) {
  rób_coś();
  flaga = ilosc+1; // czekaj na puszczenie dotyku
}

chodzi mi o 

1 godzinę temu, ethanak napisał:
flaga = ilosc+1; // czekaj na puszczenie dotyku
}

 

Link do komentarza
Share on other sites

21 minut temu, SOYER napisał:

ale jeśli jest spełniony ten warunek:

1 godzinę temu, ethanak napisał:
(flaga < ilosc)

to ten też jest spełniony:

1 godzinę temu, ethanak napisał:
(flaga != ilosc)

Niby tak... ale w drugą stronę to nie działa. Ta tajemnicza linijka:

flaga = ilosc + 1;

Jest to sygnał dla procedury przerwania, że można wyzerować flagę bo nastąpiła reakcja na dotyk. Nie zeruję jej bezpośrednio, bo ktoś może cały czas trzymać brudny paluch na czujniku.

Czyli pierwszy warunek (flaga < ilosc) nie będzie spełniony (nie będzie inkrementacji jeśli trzymam palec na czujniku), natomiast drugi (flaga != ilosc)  będzie spełniony i flaga zostanie wyzerowana, jeśli zdejmę palec z czujnika. Jednocześnie w kodzie jest sprawdzenie czy flaga == ilosc (co oznacza, że trzeba zareagować na dotyk). Jeśli flaga > ilosc to oznacza, że ktoś się przykleił do czujnika i trzeba poczekać żeby się odkleił.

Przeanalizuj zachowanie tego kawałka kodu dla różnych czasów dotyku.

BTW nawiasa poprawiłem - niechcący mi się insert wcisnął i coś go zeżarło 🙂

Komentarz też trochę rozbudowałem.

 

 

Edytowano przez ethanak
Link do komentarza
Share on other sites

Czekaj, może z maszyną stanów będzie łatwiej. Przykład dla wymagania trzech odczytów zanim nastąpi reakcja:

#define ILOSC 3

enum {
    STATE_START=0,
    STATE_MAX_WAIT=ILOSC-1,
    STATE_TOUCH,
    STATE_CONFIRMED
};

#define STATE_WAIT STATE_START..STATE_MAX_WAIT

uint8_t state = STATE_START;

void IRAM_ATTR przerwanie()
{
    uint8_t sensor=digitalRead(cośtam);
    // maszyna stanów:

    switch(state) {
        case STATE_WAIT:
        if (sensor) {
            //czekamy ileś tam kroków
            state++;
        }
        else {
            // czujnik puszczony przed osiągnięciem ilości
            state=0;
        }
        break;

        case STATE_TOUCH:
        // tu nie robimy nic dopóki program nie potwierdzi przyjęcia
        break;

        case STATE_CONFIRMED:
        //dopóki jest sygnał z czujnika nie robimy nic
        //po puszczeniu czujnika cały cykl zaczyna się od początku
        if (!sensor) state=STATE_START;
        break;
        
        default:
        // to się nie powinno zdarzyć ale trzeba się przygotować
        // na trzęsienie ziemi. Restart maszyny
        state = STATE_START;
        break;
    }
}

// no i w kodzie:
    if (state == STATE_TOUCH) {
        rób_co_trzeba();
        // poinformuj maszynę stanów że przyjąłeś polecenie
        state = STATE_CONFIRMED;
    }
    

Poprzedni kod robi to samo tyle że jest krótszy 🙂 Poza tym dla kilku czujników łatwiej jest zrobić tablicę "flagi" i prostą pętlę for.

Link do komentarza
Share on other sites

Ok, zanim zacznę to analizować dogłębnie to powiedz mi dwie rzeczy, w procedurze przerwania to chyba powinno być coś krótkiego, a taka maszyna stanów....

druga rzecz, sygnałem wywołującym przerwanie powinien być stan wysoki, wtedy przerwanie wywoła się kilkukrotnie w czasie wciśniętego przycisku, tak?

bo jeśli damy RAISING, albo FALLING, to przerwanie wywołamy raz, si?

 

jeszcze jedno, wolałbym by procedura po naciśnięciu przycisku wywoływała sie po samym naciśnięciu(i odczekaniu np. 200ms dla potwierdzenia), a nie po puszczeniu przycisku(tak jak mam teraz na filmie).

Link do komentarza
Share on other sites

Aj, to się trochę nie zrozumieliśmy.

Przerwanie wywoływane z timera np. co 100msec. Przy przerwaniu od czujnika doszedłby dodatkowy kod sprawdzający ile czasu minęło od wciśnięcia, jakieś dodatkowe nikomu nie potrzebne zmienne trzymające czas, ogólnie dużo więcej kombinacji w kodzie.

Coś w stylu:

#include <ESP32_TimerInterrupt.h>

static ESP32Timer ITimer1(1);
...
void setup()
{
  ...
  ITimer1.attachInterrupt(100000, przerwanie);
  ...
}

Jakby co - zerknij sobie do kodu mojego czytaka, plik keyvolt.cpp

Edytowano przez ethanak
Link do komentarza
Share on other sites

Ok, czyli przerwanie od timera, które 10x na sekundę sprawdza stan czujnika, jeśli w tym sprawdzaniu procedura digitalRead potwierdzi wciśnięcie to inkrementujemy flagę i po dwukrotnym potwierdzeniu reagujemy na przycisk.

Sporadycznie używam przerwań, nie za bardzo się na nich znam, takie 10 krotne na sekundę wywoływanie przerwania, nic nie będzie blokować? Pytanie laika.

Link do komentarza
Share on other sites

Ja w czytaku wywołuję przerwanie klawiatury 100 razy na sekundę, a on ma naprawdę co robić. W dodatku to klawiatura matrycowa, czyli więcej roboty niż prosty odczyt pinu. Nie masz się czym przejmować 🙂

Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.