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

[BASCOM][Atmega8] Licznik impulsów nie działa poprawnie.

Tomekddd 17 Lut 2010 15:22 4688 14
  • #1 17 Lut 2010 15:22
    Tomekddd
    Poziom 23  

    Mam silnik z przekładnią który daje 5 impulsów na jeden obrót przekładni, obrotów jest 139 to liczyłem na piechotę ale chcę wykorzystać Atmege 8 do sterowania tym silnikiem i nie mogę dojść do ładu z liczeniem tych impulsów.

    Próbowałem liczyć impulsy funkcja DEBOUNCE i szło dobrze dopóki nie zwiększyłem prędkości obrotowej, zaczęło gubić impulsy

    Następnie próbowałem przerwania INT1 ale z racji tego ze impuls podawany na to przerwanie utrzymuje się przez dłuższa chwile to cały program się ścinał (na osi przekładni jest kółko magnetyczne i kontaktron przez to w położeniach skrajnych przekładni po wyłączeniu się krańcówki ciągle jest zwarty kontaktron to powodowało zwiechę procesora)

    Próbowałem też funkcji IF...Then ale własnie w położeniach skrajnych ciągle liczyło a gdy procesor dostał impuls to zwiększał zmienną wiele razy w czasie jego trwania a nie tylko raz

    Próbowałem liczy impulsy za pomocą TIMER1 ale po wystąpieniu impulsu timer liczy aż do jego zaniku a to tez jest źle


    Proszę o jakąś pomoc z tym programem bo ja już nie mam pomysłów
    to jest mój aktualny kod bez funkcji zliczania tylko sterowanie silnikiem

    Code:
    $regfile = "m8def.dat"
    
    $crystal = 8000000

    Config Lcd = 16 * 2                                         'konfiguracja wyświetlacza
    Config Lcdpin = Pin , Db4 = Portc.3 , Db5 = Portc.2 , Db6 = Portc.1 , Db7 = Portc.0 , E = Portc.4 , Rs = Portc.5


    Config Int0 = Low Level                                     'konfiguracja przerwania INT0
    Config Rc5 = Pind.2                                         'konfiguracja lini odbioru z pilota



    Config Pinb.2 = Output                                      'wyciągarka gora
    Config Pinb.3 = Output                                      'Wyciagarka Dol
    Config Pinb.4 = Output                                      'ściskanie
    Config Pinb.5 = Output                                      'rozciaganie


    Portb.2 = 0
    Portb.3 = 0
    Portb.4 = 0
    Portb.5 = 0




    On Int0 Pobr_rc5                                            'przerwanie na odbiór z pilota






    Dim Adres As Byte , Komenda As Byte                         'zmienne do rc5
    Dim Odebr_kod As Bit                                        'flaga potwierdzajaca odebranie kodu
    Enable Interrupts                                           'odblokowanie przerwań
    Enable Int0

    Reset Odebr_kod                                             'wyzerowanie flagi odebrania kodu

    Dim Impuls As Integer                                       'zmienna pamietająca liczbe impulsów z siłownika
    Impuls = 0

    Cursor Off Noblink

    Cls
    Do

    Upperline : Lcd "impulsy:" ; Impuls


    If Odebr_kod = 1 Then
    If Adres = 0 And Komenda = 1 Then                           'komenda podniesienia głosników do góry
    Gosub Gora                                                  'skok do obsługi podnoszenia
    Elseif Adres = 0 And Komenda = 7 Then                       'komenda opuszczenia glosników na doł
    Gosub Dol                                                   'skok do obslugi opuszczania
    Elseif Adres = 0 And Komenda = 3 Then                       'komenda ściśniecia głosników
    Gosub Scisk                                                 'skok do podprogramu
    Elseif Adres = 0 And Komenda = 9 Then                       'komenda rozciagnięcia
    Gosub Rozciag                                               'skok do podprogramu
    Elseif Adres = 0 And Komenda = 5 Then                       'komenda STOP
    Gosub Zatrzymaj                                             'skok do zatrzymania
    End If
    Enable Int0
    End If


    Loop
    End



    Pobr_rc5:                                                   'podprogram odbioru danych z pilota
    Disable Int0
    Enable Interrupts

    Getrc5(adres , Komenda)                                     'odbiór adresu i komendy
    Komenda = Komenda And &B01111111

    Set Odebr_kod                                               'ustawienie flagi odebrania
    Return

    Gora:
    Portb.2 = 1
    Portb.3 = 0
    Return

    Dol:
    Portb.2 = 0
    Portb.3 = 1
    Return

    Scisk:
    Portb.4 = 1
    Portb.5 = 0
    Return

    Rozciag:
    Portb.4 = 0
    Portb.5 = 1
    Return

    Zatrzymaj:
    Portb.2 = 0
    Portb.3 = 0
    Portb.4 = 0
    Portb.5 = 0
    Return


    Poprawiłem tytuł. - arnoldziq

    Przeniesiono z Programowanie Ogólne. - arnoldziq

    0 14
  • Arrow Multisolution Day
  • #2 17 Lut 2010 16:18
    atom1477
    Poziom 43  

    Przerwanie musi być skonfigurowane jako reagujące na zbocze a nie na poziom. Wtedy program nie będzie sie zawieszał na przerwaniu.

    0
  • #3 17 Lut 2010 16:54
    Tomekddd
    Poziom 23  

    Teraz się nie zawiesza ale liczy jak mu się podoba tzn. pokazuje rożne wartości bez jakiejś reguły

    to jest przerwanie ustawione na zbocze FALLING

    Code:


    Licz:
    Disable Int1
    If Scisk = 1 Then
    Incr Impuls
    Elseif Scisk = 0 Then
    Decr Impuls
    End If
    Enable Int1
    Return

    0
  • #4 17 Lut 2010 18:18
    xury
    Poziom 38  

    Proponuję napisać program od nowa. Zrezygnować z Gosub'ów. A w przerwaniu ustawiać tylko flagę. Odsługę i zliczanie robić w pętli głównej.
    Gosuby to masakra programu. A w tym Twoim zupełnie nie potrzebne.

    0
  • #5 17 Lut 2010 18:20
    janbernat
    Poziom 38  

    Jakiś bałagan podajesz.
    1. Nie podałeś wersji z debounce- która chodziła przy wolnych obrotach.
    2. W programie który wkleiłeś nie ma żadnego odniesienia do Licz:
    Czy to jest podprogram czy obługa przerwania?
    3. Po co w tym Licz wyłączasz prerwanie?
    Jak to jest obsługa przerwania- to i tak inne przerwania są wyłączone.

    0
  • Arrow Multisolution Day
  • #6 17 Lut 2010 19:10
    atom1477
    Poziom 43  

    Przerwanie nie jest ustawione na Falling. Ustawia się je tak:

    Code:

    Config Int1 = Falling

    0
  • #7 17 Lut 2010 19:59
    Tomekddd
    Poziom 23  

    wersji z DEBOUNCE nie dałem bo nie ma jej już zapewne nie działała dlatego ze impulsy docierały zbyt szybko a DEBOUNCE ma opóźnienia eliminujące drgania styków co pewnie wpływało na wykrywanie impulsów. Wiem ze można tę instrukcje przestawić zmniejszając czas opóźnienia ale to nie ma sensu bo jak kiedyś wystąpią wyższe obroty to ich nie uwzględni

    ten fragment to własnie obsługa przerwania INT1 ustawionego na wykrywanie opadającego zbocza sygnału

    Kontaktron podaje masę na procesor ale jeśli będzie potrzeba mogę to zmienić np na podawanie plusa

    Wiem że GOSUB to tu wcale nie pasuje ale to pozostałość po próbach przeróbki, zaraz je wywalę i zrobię tak jak należy

    Jeszcze mam problem z wyświetlaniem na LCD jak dam CLS w pętli DO...LOOP to tak szybko odświeża ze nie widać znaków a jak dam poza nią to znowu nie czyści wyświetlacza i pozostają śmieci
    da sie to jakoś zrobić bez wprowadzania do programu niepotrzebnego opóźnienia?

    0
  • #8 17 Lut 2010 20:26
    janbernat
    Poziom 38  

    "bo jak kiedyś wystąpią wyższe obroty to ich nie uwzględni "
    Słusznie- debounce to paskuda.
    Ale od czegoś trzeba zacząć.
    Normalnie ma 25ms- można dać 1ms i chociaż sprawdzić.
    Kontaktron tak jak przycisk- ma drgania.
    Trzeba sprawdzić czy po 20ms ma ten sam stan- dla początkujących- debounce.
    A lepiej ale nie jako "pacaneum"- wygenerować przerwanie z jakiegos Timera i sprawdzać co jakis czas.
    CLS daje duże opóźnienia.
    Sprawdź $lib "Lcd4busy.lib"

    0
  • #9 17 Lut 2010 22:03
    Tomekddd
    Poziom 23  

    właśnie dlatego nie chce korzystać z DEBOUNCE bo później mogę mieć problemy

    odnośnie biblioteki to mi sie ona nie przyda bo tylko przyspiesza transmisję między wyświetlaczem a to mi nie pomoże bo znaki nadal będą migać i nic nie będzie widać
    może za pomocą LOCATE jakoś sobie poradzę

    Bardziej martwi mnie liczenie tych impulsów nieszczęsnych już nie wiem co wykorzystać do tego
    Przy przerwaniu zlicza ale przez czas trwania impulsu co powoduje że zwiększa zmienną wiele razy zamiast tylko raz


    Napisałem procedurę konfigurującą Timer1 jako licznik impulsów ale nie działa jak trzeba, licznik ciągle liczy bez względu na stan PORTB.0

    Code:
    $regfile = "m8def.dat"
    
    $crystal = 8000000

    Config Lcd = 16 * 2                                         'konfiguracja wyświetlacza
    Config Lcdpin = Pin , Db4 = Portc.3 , Db5 = Portc.2 , Db6 = Portc.1 , Db7 = Portc.0 , E = Portc.4 , Rs = Portc.5


    Config Int0 = Low Level                                     'konfiguracja przerwania INT0
    Config Rc5 = Pind.2                                         'konfiguracja lini odbioru z pilota

    Config Timer1 = Counter , Edge = Rising
    Config Pinb.0 = Input
    Set Portb.0

    Config Pinb.2 = Output                                      'wyciągarka gora
    Config Pinb.3 = Output                                      'Wyciagarka Dol
    Config Pinb.4 = Output                                      'ściskanie
    Config Pinb.5 = Output                                      'rozciaganie

    Portb.2 = 0
    Portb.3 = 0
    Portb.4 = 0
    Portb.5 = 0




    On Int0 Pobr_rc5                                            'przerwanie na odbiór z pilota

    Dim Adres As Byte , Komenda As Byte                         'zmienne do rc5
    Dim Odebr_kod As Bit                                        'flaga potwierdzajaca odebranie kodu
    Enable Interrupts                                           'odblokowanie przerwań
    Enable Int0
    Enable Timer1

    Timer1 = 0
    Start Timer1


    Reset Odebr_kod                                             'wyzerowanie flagi odebrania kodu

    Dim Scisk As Bit


    Cursor Off Noblink

    Cls
    Do

    Upperline : Lcd "impulsy:" ; Timer1


    If Odebr_kod = 1 Then
    If Adres = 0 And Komenda = 1 Then                           'komenda podniesienia głosników do góry
    Portb.2 = 1
    Portb.3 = 0
    Elseif Adres = 0 And Komenda = 7 Then                       'komenda opuszczenia glosników na doł
    Portb.2 = 0
    Portb.3 = 1
    Elseif Adres = 0 And Komenda = 3 Then                       'komenda ściśniecia głosników
    Portb.4 = 1
    Portb.5 = 0
    Scisk = 1
    Elseif Adres = 0 And Komenda = 9 Then                       'komenda rozciagnięcia
    Portb.4 = 0
    Portb.5 = 1
    Scisk = 0
    Elseif Adres = 0 And Komenda = 5 Then                       'komenda STOP
    Portb.2 = 0
    Portb.3 = 0
    Portb.4 = 0
    Portb.5 = 0
    End If
    Enable Int0
    End If


    Loop
    End


    Pobr_rc5:                                                   'podprogram odbioru danych z pilota
    Disable Int0
    Enable Interrupts

    Getrc5(adres , Komenda)                                     'odbiór adresu i komendy
    Komenda = Komenda And &B01111111

    Set Odebr_kod                                               'ustawienie flagi odebrania
    Return

    0
  • #10 18 Lut 2010 18:11
    xury
    Poziom 38  

    Jeszcze raz od nowa. Tym razem postaraj się bardziej. Ustaw wreszcie te przerwania INTx na jakieś zbocze, a nie poziom. Co z tego, że ustawiłeś Timer1 jako licznik jak nie ma to związku z resztą kodu. Timer sobie działa,a ja się pytam - i co z tego ? gdzie obsługa tego timera?

    0
  • #11 18 Lut 2010 19:00
    Tomekddd
    Poziom 23  

    Przerwanie mam ustawione na LOW LEVEL bo steruje to pilotem RC5
    a chciałem zrobić drugie INT1 na zbocze to nie działa tylko zmula program pewnie dlatego ze w skrajnych położeniach ciągle jest stan niski

    Jak obsługiwać ten Timer? czy on nie będzie zliczał zewnętrznych impulsów? bo własnie czytałem ze liczy impulsy na PB.0 a on wcale na to nie reaguje tylko ciągle sobie liczy

    Zrobiłem jeszcze z obsługą DEBOUNCE i czasem opóźnienia 5ms to niby liczy ale za każdym razem jest inny wynik podejrzewam ze gubi impulsy bo któreś mogą trafić akurat na opóźnienie

    0
  • #12 18 Lut 2010 20:13
    atom1477
    Poziom 43  

    Jeżeli ustawił być INT1 na zbocze to ciągły stan niski nie zamulał by Ci programu.
    Jeszcze raz dla pewności: masz ustawić INT1 na zbocze, a nie implementować w programie programową obsługę reakcji na zbocze podczas gdy INT1 będzie ustawione na wyzwalanie poziomem.. Bo tak do tej pory miałeś.

    0
  • #13 19 Lut 2010 00:29
    Tomekddd
    Poziom 23  

    Ok po kolei, wywalam wszystko z programu, zostawiam tylko sterowanie IR i dopisuję obsługę przerwania INT1 wyzwalanego zboczem FALLING, w przerwaniu dodaje lub odejmuje jeden od zmiennej "impulsy" zależnie od zmiennej "ścisk"

    zmienna impulsy jest zwiększana o kilkanaście a nie tylko o jeden

    Code:
    $regfile = "m8def.dat"
    
    $crystal = 8000000

    Config Lcd = 16 * 2                                         'konfiguracja wyświetlacza
    Config Lcdpin = Pin , Db4 = Portc.3 , Db5 = Portc.2 , Db6 = Portc.1 , Db7 = Portc.0 , E = Portc.4 , Rs = Portc.5


    Config Int0 = Low Level                                     'konfiguracja przerwania INT0
    Config Rc5 = Pind.2                                         'konfiguracja lini odbioru z pilota

    Config Int1 = Rising

    Config Pinb.2 = Output                                      'wyciągarka gora
    Config Pinb.3 = Output                                      'Wyciagarka Dol
    Config Pinb.4 = Output                                      'ściskanie
    Config Pinb.5 = Output                                      'rozciaganie

    Portb.2 = 0
    Portb.3 = 0
    Portb.4 = 0
    Portb.5 = 0


    On Int0 Pobr_rc5                                            'przerwanie na odbiór z pilota
    On Int1 Licz

    Dim Adres As Byte , Komenda As Byte                         'zmienne do rc5
    Dim Odebr_kod As Bit                                        'flaga potwierdzajaca odebranie kodu
    Enable Interrupts                                           'odblokowanie przerwań
    Enable Int0
    Enable Int1


    Reset Odebr_kod                                             'wyzerowanie flagi odebrania kodu

    Dim Ok As Bit
    Ok = 0
    Dim Scisk As Bit
    Scisk = 1
    Dim Impulsy As Integer
    Impulsy = -1

    Cursor Off Noblink

    Cls
    Do

    Upperline : Lcd "impulsy:" ; Impulsy


    If Odebr_kod = 1 Then
    If Adres = 0 And Komenda = 1 Then                           'komenda podniesienia głosników do góry
    Portb.2 = 1
    Portb.3 = 0
    Elseif Adres = 0 And Komenda = 7 Then                       'komenda opuszczenia glosników na doł
    Portb.2 = 0
    Portb.3 = 1
    Elseif Adres = 0 And Komenda = 3 Then                       'komenda ściśniecia głosników
    Portb.4 = 1
    Portb.5 = 0
    Scisk = 1
    Ok = 1
    Elseif Adres = 0 And Komenda = 9 Then                       'komenda rozciagnięcia
    Portb.4 = 0
    Portb.5 = 1
    Scisk = 0
    Ok = 1
    Elseif Adres = 0 And Komenda = 5 Then                       'komenda STOP
    Portb.2 = 0
    Portb.3 = 0
    Portb.4 = 0
    Portb.5 = 0
    Ok = 0
    End If
    Enable Int0
    End If


    Loop
    End


    Pobr_rc5:                                                   'podprogram odbioru danych z pilota
    Disable Int0
    Enable Interrupts

    Getrc5(adres , Komenda)                                     'odbiór adresu i komendy
    Komenda = Komenda And &B01111111

    Set Odebr_kod                                               'ustawienie flagi odebrania
    Return



     'PRZERWANIE INT1
    Licz:
    If Scisk = 1 And Ok = 1 Then
    Incr Impulsy
    Elseif Scisk = 0 And Ok = 1 Then
    Decr Impulsy
    End If
    Return

    0
  • Pomocny post
    #14 19 Lut 2010 02:55
    emarcus
    Poziom 35  

    Tomekddd napisał:
    Ok po kolei, wywalam wszystko z programu, zostawiam tylko......

    zmienna impulsy jest zwiększana o kilkanaście a nie tylko o jeden

    Code:

    ............
    Licz:
    If Scisk = 1 And Ok = 1 Then
    Incr Impulsy
    Elseif Scisk = 0 And Ok = 1 Then
    Decr Impulsy
    End If
    Return


    Kontaktron (Reed switch) generalnie jest stosowany jako proxy switch, czyli w ukladach statycznych. Niemniej jednak z uwagi na ich relatywnie "wysoka" szybkosc reakcji dopuszcza sie stosowanie ich do pomiarow dynamicznych z pewnymi zastrzezeniami i ograniczeniami. Mankamentem ich jest powszechnie znany fenomenon 'drganie stykow' (BOUNCE). W zaleznosci od modelu , wielkosci (dopusczalnego obciazenia pradowego), ten czas (bounce time) moze zawierac sie w granicach: od 0,7 ms do nawet 7 ms. W skrajnym przypadku jest to czas bardzo duzy. Stosujac kontaktron jako sensor impulsow (obiektow w ruchu) musisz liczyc sie ze stosowaniem procedury "Debounce" niezaleznie od tego czy to lubisz lub nie.
    W twoim przykladzie zrezygnowales calkowocie z procedury Debounce.
    Zatem masz oczywisty skutek; mozesz nawet policzyc ile srednio tych drgan wystepuje!!!!

    Aby ci tu zbyt duzo nie mieszac; sprobuj dac taki 'prowizoryczny debounce':
    W subrutynie od INT1 Licz:
    jako pierwsza linia wstaw waitms 8 albo 10 ms
    Mozesz probowac jeszcze mniejszych czasow.
    Gdy to zawiedzie, to jest jeszcze rada na zastosowanie hallotronu (Hall effect switch - nie sensor) jezeli chcesz pozostac przy magnetycznej metodzie zliczania impulsow.
    Idealnym do tych celow jest np: A3213 (Allegro Microsystem inc) lub inny (Infinion) unipolarny - te reaguja nizaleznie od biegunowosci pola mag., ani tez nie wymagaja stosowania debounce.
    Sa tanie!!

    e marcus

    0
  • #15 19 Lut 2010 10:15
    Tomekddd
    Poziom 23  

    W takim razie zrobię to na DEBOUNCE będzie lepiej a czas opóźnienia ustawie na 5ms i myślę że to pomoże

    0