logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[atmega8] [atmega8][c] - Jak obsłużyć czujnik Mobot przez I2C i wyświetlić wynik w mm?

false 13 Sie 2014 13:55 1170 5
REKLAMA
  • #1 13874160
    false
    Poziom 10  
    Witam, potrzebuje stworzyć prosty układ obsługujący ultradźwiękowy czujnik odległości firmy Mobot. Wynik wyświetlany jest na wyświetlaczu w mm. Korzystam z bibliotek TWI_Master od AVR oraz jakiś ogólnodostępnych hd44780. Dodkowo korzystam z biblioteki dostarczonej przez producenta:

    Sonar_TWI.c:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    oraz Sonar_TWI.h:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Do tego plik z deklaracjami Main.h:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod



    Mój kod wygląda tak:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    I wszystko działa bardzo ładnie. Jednak chciałbym aby sonar 'obsługiwany' był przez timer 8 bitowy. Próbnie napisałem taki kod żeby sprawdzić działanie timera:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    I wszystko działa ok. Problem pojawia sie dopiero gdy timerem chcę obsłużyć sonar:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Taki kod nie działa. Tzn. na wyświetlaczu pojawia się napis "mm", ale przed nim albo nie ma nic, albo jest 0, albo jakieś totalne krzaki.

    Nie wiem w czym leży problem. Samo i2c działa normalnie, natomiast w połączeniu z timerem już nie chce hulać.
  • REKLAMA
  • #2 13874214
    pm.m
    Poziom 9  
    false napisał:

    I wszystko działa ok. Problem pojawia sie dopiero gdy timerem chcę obsłużyć sonar:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod



    Wg. mnie to takie umieszczanie delay'a w przerwaniu Timera jest ryzykowne. Czy oby na pewno w czasie tych 40 ms nie nastąpi ponowne żądanie przerwania?
    Trzeba by policzyć czasy i nie mieszać Timera z delay.
  • REKLAMA
  • #3 13874407
    false
    Poziom 10  
    Przerwanie z timera powinno być coś ok. 4 razy na sekundę (preskaler 1024). A da się tą funkcję delay jakoś zastąpić? Bo odczekać te 40ms muszę (tyle mija zanim sonar wyśle i odbierze odbity sygnał dźwiękowy).
  • REKLAMA
  • #4 13874995
    excray
    Poziom 41  
    Nie wiem czy te delay jest jakieś krytyczne ale jeśli nie to sonar wyzwalaj na końcu przerwania a wynik pobieraj na początku w kolejnym przerwaniu. W ten sposób unikniesz tego delaya.
  • REKLAMA
  • Pomocny post
    #5 13875531
    Akane
    Poziom 27  
    Problem leży w sposobie działania biblioteki TWI_Master i miejsca, skąd jej pośrednio używasz.
    TIMER0_OVF_vect, jak i każde inne przerwanie, uruchamia się z czasowo wyłączonymi przerwaniami, dlatego ani sonar_request, ani sonar_gets_distance nie zadziała z tego miejsca. Polecenia zostają zakolejkowane, i może tylko TWI::START zostaje wykonany.

    Możesz:
    1. wstawić sei(); przed sonar_request, lub dodać atrybut do funkcji: ISR(TIMER0_OVF_vect, ISR_NOBLOCK). Takie rozwiązanie stosujemy tylko wtedy, gdy następne przerwanie timera nastąpi dopiero po wyjściu z aktualnego. Nie mając takiej pewności, można sobie wstawić flagę "przerwanie timera jest aktywne", by zapewnić ekskluzywny dostęp do danego przerwania, by kolejne przerwanie nie nakładało się na aktualne, które czeka na coś.

    Kod: text
    Zaloguj się, aby zobaczyć kod


    2. Nie odblokowuj przerwania timera, ani nie pisz dla niego przerwania, tylko w main, w pętli, sprawdzaj flagę przerwania i gdy jest ustawiona, to wyzeruj ją (wpisując jedynkę) i wykonaj odczyt z sonaru, identycznie, jak aktualnie masz w przerwaniu.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #6 13877410
    false
    Poziom 10  
    Akane dzięki wielkie, działa.
REKLAMA