Elektroda.pl
Elektroda.pl
X

Wyszukiwarki naszych partnerów

Wyszukaj w ofercie 200 tys. produktów TME
Proszę, dodaj wyjątek elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Zmierzenie szerokości impulsu z użyciem INT1/INT2

Jakub17 18 Lip 2017 10:39 483 11
  • #1 18 Lip 2017 10:39
    Jakub17
    Poziom 6  

    Witam.

    Procesor ATmega32
    Za pomocą przerwań zewnętrznych chciałem sobie zmierzyć szerokość impulsu ECHO w sonarze HC-SR04. Niestety coś w kodzie nie trybi ponieważ dioda informująca o dokonanym pomiarze się nie zapala. Napisałem już obsługe jednego czujnika za pomocą INPUT_CAPTURE i działa, ale niestety w ATmega32 jest tylko jeden pin do obsługi takie zdarzenia więc wybrałem przerwania zewnętrzne...

    Kod: c
    Zaloguj się, aby zobaczyć kod

  • Pomocny post
    #3 20 Lip 2017 12:59
    dondu
    Moderator Mikrokontrolery Projektowanie

    Analizując pobieżnie Twój program - manipulowanie przerwaniami wygląda OK.

    Jakub17 napisał:
    Niestety coś w kodzie nie trybi ponieważ dioda informująca o dokonanym pomiarze się nie zapala.

    Wniosek nieuprawniony, ponieważ w pokazanym wyżej programie nie migasz diodą w przerwaniu, ani w części kodu sprawdzającej stan zmiennej end_echo_flag, a jedynie:
    - zieloną, gdy pomiar mieści się w granicach 0 do DYSTANS_w_cm
    - żółtą, zależnie od stanu licznika TCNT1.

    Pomijam już fakt, że nie bierzesz pod uwagę możliwości przepełnienia się licznika TCNT1.

    Prawdopodobną przyczyną może być jednak pewna przypadłość tych czujników, a mianowicie brak powrotu sygnału echo na stan niski. W takiej sytuacji należy pin ten ściągnąć do GND za pomocą pinu mikrokontrolera, do którego jest podłączony. W związku z tym pytanie - sprawdzałeś oscyloskopem stan pinu echo?

    Drobna uwaga: Nie włączaj przerwań na początku programu tylko wtedy, gdy już przygotujesz układ do pracy.

  • #4 20 Lip 2017 13:11
    Jakub17
    Poziom 6  

    Zadziałało. Winny był czujnik, niestety chińskie badziewie nie zawsze chce działać. Też o tym myślałem jeśli chodzi o licznik... Jak się przepełni to wyrażenie echo_end_sonar - echo_start_sonar zostanie wyliczone nieprawidłowo. Masz jakiś pomysł jak rozwiązać ten problem?

  • #5 20 Lip 2017 13:17
    dondu
    Moderator Mikrokontrolery Projektowanie

    Włącz przerwanie przepełnienia timera 1 i dodaj zmienną globalną, która będzie inkrementowana w tym przerwaniu oraz uwzględniona we wzorze liczącym ilość impulsów timera1, którą przekazujesz później do funkcji odleglosc_w_cm().

  • Pomocny post
    #6 20 Lip 2017 13:23
    EuroGenio
    Poziom 17  

    Witam
    Nowsza seria tych czujników jest znacznie uproszczona względem poprzedniej - pracuje jednak gorzej.
    Nie działa w nich resetowanie wysokiego stanu na ECHO poprzez wymuszenie niskiego.
    I tak trzymają wysoki, aż do ok. 200 ms.
    Pomaga krótkie wyłączenie zasilania (10-100 us) ;)
    Pozdrawiam
    Eurogenio

  • #7 20 Lip 2017 13:28
    Jakub17
    Poziom 6  

    dondu napisał:
    Włącz przerwanie przepełnienia timera 1 i dodaj zmienną globalną, która będzie inkrementowana w tym przerwaniu oraz uwzględniona we wzorze liczącym ilość impulsów timera1, którą przekazujesz później do funkcji odleglosc_w_cm().


    Niestety nie mogę zmieniać sposobu wyzwalania przerwania na liczniku TC1 ponieważ jest on używany także do drugiego takiego czujnika który działa w oparciu o przerwania input capture.

  • #8 20 Lip 2017 13:34
    EuroGenio
    Poziom 17  

    Ale możesz użyć jednego przerwania dla dwóch czujników a tylko wyzwalać osobnymi pinami.
    W tych nowszych czujnikach wyjście już nie jest typu otwarty kolektor i trzeba separować czujniki diodami a na wejściu przerwania włączyć PULLUP
    Ale wtedy musisz upewniać się, że poprzedni zakończył pomiar aby wyzwolić następny lub je profilaktycznie resetować przed każdym pomiarem
    Eurogenio

  • #9 20 Lip 2017 15:07
    dondu
    Moderator Mikrokontrolery Projektowanie

    Jakub17 napisał:
    Niestety nie mogę zmieniać sposobu wyzwalania przerwania na liczniku TC1 ponieważ jest on używany także do drugiego takiego czujnika który działa w oparciu o przerwania input capture.

    Przeczytaj proszę jeszcze raz co napisałem :)

  • #10 12 Sie 2017 17:14
    Jakub17
    Poziom 6  

    Pozwolę sobie odświeżyć temat dopiero teraz gdyż wcześniej nie miałem czasu:(
    Oprócz przerwania od przechwycenia licznika dodałem jeszcze przerwanie od przepełnienia:
    Do funkcji licznik dodałem: TIMSK |= (1<<TOIE1);
    oraz procedura obsługi przerwania:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    a funkcja mierząca odległość wygląda teraz tak:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    W main() zaraz po jej wywołaniu zeruje zmienne cykl1 i cykl2 ktore sa przekazane do powyższej funkcji jako argument


    Oto całość:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Wyrzucam wyniki pomiarow na wyswietlacz. Troche pomogło dodanie przerwania od przepełnienia ale i tak czasami pojawiają się takie babole że wyrzucą wartosć np. 500 cm gdy zasłaniam sonar kartką papieru w odległości 20 cm. Rzuciłem okiem na tablice wektorów przerwań. Przerwaniem OVF dla Timera 1 ma dużo niższy priorytet niż przerwanie INPUT CAPTURE od tegoż timera także czy może to powodować właśnie ten problem ze gdy zgłoszone zostaną dwa przerwania jednocześnie to i tak wykona się przerwanie CAPTURE i zafałszuje wynik pomiaru gdy dojdzie do przepełnienia licznika?

    Próbowałem zerować zmienne cykl przekazując ich adres do funkcji odleglosc_w_cm aby odbywało się to już wewnątrz tej funkcji a nie po jej wywołaniu ale pojawia się warrning: passing argument 2 of 'odleglosc_w_cm' discards volatile qualifier from pointer target type czyli ze tak zmienna cykl przekazana do funkcji, a raczej jej adres, powoduje ze przestaje byc ona volatile. Dlaczego tak sie dzieje?

  • Pomocny post
    #11 12 Sie 2017 17:56
    Piotrus_999
    Poziom 39  

    oczywiście że tak. Wewnątrz funkcji już nie jest traktowane jako volatile. A dlaczego - bo w "scope" tej funkcji nie zadeklarowałeś jej jako volatile. zobacz sobie jaka jest różnica.

    Takie operacje w C++ są już nie legalne i trzeba jawnie dokonać konwersji typów inaczej wywołają bład.

    A róznica w kodzie - bardzo prosty przykład do analizy własnej :)

    https://godbolt.org/g/4zSr3t

  • #12 12 Sie 2017 21:39
    Jakub17
    Poziom 6  

    Dzięki, z volatile spraw jasna:) A odwołując się do mojego pierwszego posta gdzie odległość jest obliczana przez funkcję i zapisywana w zmiennej pomiar:
    pomiar = odleglosc_w_cm((echo_end_sonar - echo_start_sonar),STALA_CZASOWA);
    to jeżeli licznik przepełni się w trakcie trwania pomiaru to końcowa wartość licznika echo_end_sonar może być mniejsza od początkowej echo_start_sonar (no bo licznik zacznie liczyć od 0). Spróbowałem to rozwiązać tak jak zaprononował dondu ale nie działa to idealnie, opisałem post wyżej... Czy można to jakoś poprawić w inny sposób? Wydaje mi się że przyczyną jest gęste występowanie przerwań no bo od tego samego licznika timer1 występuje przerwanie Capture i Overflow, z tym że OVF ma wyższy priorytet...

 Szukaj w ofercie
Zamknij 
Wyszukaj w ofercie 200 tys. produktów TME