Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[Atmega8][Bascom] Pomiar czasu zadziałania przekaźnika - nie działa jak powinien

peres 27 Lis 2011 15:43 2401 11
  • #1 27 Lis 2011 15:43
    peres
    Poziom 10  

    Witam. Napisałem program który mierzy czas między podaniem napięcia na cewke przekaźnika, a przyciągnięciem kotwicy i zwarcia styków.

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod

    problem polega na tym, że na wyświetlaczu cały czas pokazuje się identyczny wynik.Tak jakby procesor nie mierzył czasu przekaźnika, tylko jakiś inny czas. Jestem początkującym w dziedzinie programowania, także proszę o wyrozumiałość.

    0 11
  • #2 27 Lis 2011 22:46
    xury
    Poziom 38  

    Oj kolego jak Ty chcesz mierzyć coś używając Waitms w programie ?.
    W obsłudze przerwania od cewki startuj timer, a w drugim przerwaniu go zatrzymuj.

    0
  • #3 28 Lis 2011 16:09
    peres
    Poziom 10  

    To waitms jest tylko po to żeby zdążyć puścić przycisk który uruchamia pomiar. Bo tak to by się zapętlił (tak mi się wydaje).
    Idea programu polega na tym, że jak wcisnę przycisk, to portb.0, do którego jest podłączona cewka, ustawi się na 1, czyli załączy przekaźnik. W tym samym momencie startuje timer i liczy, po przepełnieniu generuje przerwanie które zwiększa zmienną Puls o 1. Po przyciągnięciu kotwicy i zwarciu styków (Pind.1) timer się zatrzymuje i liczbę przerwań mnoży przez obliczony współczynnik i dodaje to co zostało w timerze.
    Xury, mógłbyś opisać swój pomysł, bo trochę nie rozumiem.

    0
  • #4 29 Lis 2011 10:54
    SylwekK
    Poziom 29  

    Jak boisz się o zapętlenie to wykorzystaj dodatkowy znacznik albo badanie czy przycisk puszczony ale na litość nie WAIT'uj w programach, które mają coś dokładnie mierzyć!

    0
  • #5 29 Lis 2011 16:37
    M. S.
    Poziom 34  

    Styk przekaźnika podłącz do przerwania zewnętrznego i w obsłudze tego przerwania odczytuj wartość timera uruchomionego wraz z włączeniem cewki, a później przelicz. (Pamiętaj o drganiach styków).
    Po co korzystać z przerwania od przepełnienia timera? Użyj Timera1. Z tą samą dokładnością zmierzysz czas ponad 4ms zamiast 16us. Jak będzie za mało to włącz prescaler albo zmniejsz częstotliwość kwarcu. Ogranicz (wyeliminuj) zmienne typu Single. Wynik na wyświetlacz sformatuj instrukcją FORMAT zgodnie z helpem. uC przecież nie musi znać tego czasu w milisekundach.

    0
  • #6 03 Gru 2011 18:27
    peres
    Poziom 10  

    Doprowadziłem program do takiej postaci:

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod

    Umieściłem załączenie cewki, i pomiar czasu w przerwaniach. A co zrobić z wyświetlaniem czasu? Czytałem w innym wątku, że w przerwaniach nie zaleca się umieszczanie rozkazów LCD. A tak jak jest teraz, to nie działa dobrze, bo każdą literkę wyświetla z opóźnieniem i czas jest 0. Wydaje mi się, że to wina tego, że jak przyjdzie przerwanie w czasie obsługi wyświetlacza to się coś kiełbasi.

    Przerwanie od przepełnienia stosuje po to, by móc mierzyć też dłuższe odcinki czasu, np w przekaźnikach czasowych.
    Dlaczego wyeliminować zmienne Single? Na co to będzie miało wpływ?
    Jeszcze jedno pytanie. Dlaczego program z pierwszego postu nie działa? Gdy "symuluje" styki przekaźnika ręcznie, tzn zwieram do masy PD1 to wszystko działa, wyświetla się czas. Czy to może być spowodowane drganiem styków?

    0
  • #7 03 Gru 2011 19:13
    SylwekK
    Poziom 29  

    Przecież tu do niczego nie potrzebne są przerwania INT0 i INT1. Po prostu uruchom timer w momencie podania napięcia na cewkę, a dowolny pin wykorzystaj i badaj nim przyciągniętą kotwicę - kiedy dostanie sygnał to zastopuj timer. Odczytaj wtedy jego zawartość, przelicz i przekaż wynik na LCD. Możesz też w obsłudze przerwania inkrementować jakąś zmienną uzależniając inkrementację od pinu odpowiedzialnego za badanie stanu przyciągniętej głowicy. Rozwiązań jest 1000...
    I jeszcze jedno, popatrz na strukturę Twojego programu. Panuje tam totalny chaos - w dobrym tonie jest włączać przerwania jak już wszystko jest skonfigurowane, bo kiedyś się możesz nieźle rozczarować...

    0
  • #8 05 Gru 2011 01:02
    emarcus
    Poziom 35  

    peres napisał:
    Doprowadziłem program do takiej postaci:
    ............

    Wydaje mi się, że to wina tego, że jak przyjdzie przerwanie w czasie obsługi wyświetlacza to się coś kiełbasi.

    Przerwanie od przepełnienia stosuje po to, by móc mierzyć też dłuższe odcinki czasu, np w przekaźnikach czasowych.

    Jeszcze jedno pytanie. Dlaczego program z pierwszego postu nie działa? Gdy "symuluje" styki przekaźnika ręcznie, tzn zwieram do masy PD1 to wszystko działa, wyświetla się czas. Czy to może być spowodowane drganiem styków?


    No więc, tak jak napisał Sylwek troche porządku/systematyki by się przydało, ale nie to jest najgorsze w tym programie.
    Po pierwsze, nie możesz używać zarezerwowanych słów: - nazwa subrutyny od interruptu1 stoi u ciebie "START" - nazwij to jak chcesz ale z poza listy "Reserved Words".
    Obliczanie czasu załączenia przekaźnika nie jest ani poprawnie 'wychwycone', ani też poprawnie obliczane.
    Stosowanie interruptów jest często wygodne, ale jego skutek nie zawsze spełnia oczekiwania.
    Popatrz u ciebie: -załączasz przekaźnik w subrutynie od INT1; po wyjściu z interruptu juz na starcie masz zgubione/ naliczone ok 200 cykli z czego Timer0 zarejstruje ok 80. Jeżeli zastosujesz w tej samej formie "wychwycenie" momentu załączenia styków przekaźnika, musisz liczyć sie z podobnym procesem, co w efekcie daje zbyt duży błąd aby go pominąć (kosztowna w tym przykładzie obsługa stosu).
    Ponadto samo już obliczanie czasu masz także będne: bierzesz do obliczania czasu tylko liczbę przepełnień Timer0 (jakoś nie zauważyłem aktualnej zawartości timera0 dołączonej do czasu 'Total') .
    Odnośnie wyświetlanego wyniku: Być może coś tam się wyswietla, ale masz to ujęte w krótkiej, szybko przwijającej się pętli, za kazdym razem masz Cls i wyświetlenie rezultatu, więc może nie zdażysz odczytać gdy nastąpi kolejny cls, albo wyświetlacz zwyczajnie nie zdąży tego wyświetlić przed kolejnym Cls.

    Cytat:

    Dlaczego wyeliminować zmienne Single? Na co to będzie miało wpływ?


    To ty decydujesz w jakiej formie i jednostkach będzie końcowy wynik; czy będa to pełne (całkowite) sekundy czy też wynik ma być z jakąśtam dokładnościa miejsc dziesietnych.

    I jeszcze jedno na koniec: - configurujesz w programie INT0 i INT1 z akcją 'falling' a ich piny nie są podciągane do Vcc - jak więc maja one reagować.
    Gdzie jest to zbocze opadające?

    e marcus

    0
  • #9 06 Sty 2012 14:01
    peres
    Poziom 10  

    Witam wszystkich ponownie.
    Piny INT0 i INT1 były zewnętrznie podciągnięte przez rezystor do VCC.
    Myślę że z tymi przerwaniami to był zły pomysł. Poprawiłem trochę starą wersje programu. Zastosowałem badanie czy przycisk jest puszczony, i dopiero wtedy uruchamia się program:

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod

    Niby tak prosty program, a nie chce działać...
    Przekaźnik który badam ma czas zadziałania ok 4ms, a procesor z tym programem pokazuje mi wynik ok 10us(od 8us do 15us). Nie mam pomysłu co jest źle.

    0
  • #10 06 Sty 2012 14:33
    SylwekK
    Poziom 29  

    Nie chciał bym za Ciebie pisać tego programu, bo jest to naprawdę proste zadanie i dlatego spróbuj sam napisać go jeszcze raz od początku wg np. takiego algorytmu:

    Ustaw timer powiedzmy na 10khz aby każde przerwanie wykonywało się co 100 mikrosekund. Możesz też gęściej od tego zależy dokładność - tu 100us czyli 0,1ms
    Zdefiniuj sobie zmienną licznikową (byte - dla zakresu do 25ms, word - do 6,5s), która będzie zliczana w wymienionym przerwaniu jeśli znacznik bitowy (który też sobie zdefiniuj) przyjmie wartość np. 1, a jedynkę tą ustaw w momencie ustawienia portu sterującego przekaźnikiem na jego włączenie (czyli podczas wciśnięcia przycisku). Następnie badaj w pętli bez przerwy inne wejście portu do którego podłączasz wcześniej styk przekaźnika, który w momencie przyciągnięcia kotwicy poda na ten port powiedzmy stan 0. Jeśli w pętli, o której wspominałem wcześniej zostanie wykryte to 0 to natychmiast ustaw znacznik pozwolenia liczenia na 0 i wyjdź z pętli. Teraz już możesz odczytać zawartość inkrementowanej zmiennej i przeliczyć ją aby uzyskać wynik końcowy, np. jeśli zmienna zliczy 45 impulsów to 45*100us=4500us czyli 4,5ms
    Prościej sie chyba nie da...
    Pozdrawiam

    0
  • #11 06 Sty 2012 19:47
    emarcus
    Poziom 35  

    peres napisał:
    Witam wszystkich ponownie.
    Piny INT0 i INT1 były zewnętrznie podciągnięte przez rezystor do VCC.
    Myślę że z tymi przerwaniami to był zły pomysł. Poprawiłem trochę starą wersje programu. Zastosowałem badanie czy przycisk jest puszczony, i dopiero wtedy uruchamia się program:
    Niby tak prosty program, a nie chce działać...
    .


    Spróbuj takiej konstrukcji:
    Code:

    [syntax=basic4gl][/syntax]
    'Timer1 measures time interval between  falling edges
    'Time delay is counted from timer1 value (no overflows)

    $regfile = "m8def.dat"
    $crystal = 16000000

    Config Timer1 = Timer , Prescale = 8                        'step = 0.5 microsec
    Stop Timer1

    Config Pind.0 = Input                                       'to start pushbutton
    Config Pind.1 = Input                                       'to relay -contacts
    Config Portd.3 = Output                                     'to relay -coil
    Portd = 3

    Dim Del As Word

     Cls
    Lcd "Delay= " ; Del ; " " ; "uS"

    Do
      Timer1 = 0

    'wait for rising edge
      While Pind.0 = 0 : Wend
      While Pind.0 = 1 : Wend

      Start Timer1
      Set Portd.3
    'wait for falling edge
      While Pind.1 = 0 : Wend

      Stop Timer1


      Del = Timer1
      'Del = Del / 2
       Shift Del , Right

    'Display time delay
     Locate 1 , 8
     Lcd Del ; " " ; "uS" ; Spc(6)

    Loop
    End


    e marcus

    0
  • #12 06 Sty 2012 20:29
    SylwekK
    Poziom 29  

    Hehe, idea dokładnie jak moja tyle, że bez dodatkowych zmiennych. W sumie jeśli nie wykorzystuje się timera do czegoś innego, a program nie jest częścią czegoś większego to wersja jest faktycznie prostsza od mojej :-)

    0