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][Bascom]Program nie działa zgodnie z założeniem.

hanibal0 21 Lut 2010 12:35 2249 11
REKLAMA
  • #1 7727797
    hanibal0
    Poziom 11  
    Witam wszystkich na forum, jestem nowym użytkownikiem i zaczynam zabawę z mikrokontrolerami. Udało mi się już kilka razy zaprogramować prostymi programikami atmega8, jednak nie wiem dlaczego jeden z programów nie działa tak jak powinien.
    
    $regfile = "m8def.dat"
    $crystal = 1000000
    
    Config Portb = &B11111111
               Portb = &B11111111
    Config Portd = &B1111100
               Portd = &B11111111
    Do
        If Pind.0 = 0 Then Portb.0 = 0
        Waitms 200
        Portb.0 = 1
    
        If Pind.1 = 0 Then Portb.0 = 0
        Waitms 500
        Portb.0 = 1
    
    Loop
    End
    


    Zamierzeniem programu jak widać miało być:
    1. wciśnięcie przycisku SW1 = zapalenie diody na porcie PB0, świecenie przez 200 ms i wygaśnięcie diody (ustawienie PB0 = 1)
    2. wciśnięcie przycisku SW2 = zapalenie diody na porcie PB0, świecenie przez 500 ms i wygaśnięcie diody (ustawienie PB0 = 1)

    Niestety po zaprogramowaniu atmegi8 program nie działa prawidłowo, tzn. po 3-krotnym naciśnięciu przycisku reaguje następne 3 razy prawidłowo a później kolejne 3 wciśnięcia nie reaguje, chyba że przytrzymam wciśnięty przycisk przez ok. 1s

    Może mi ktoś powiedzieć co jest nie tak?
  • REKLAMA
  • #2 7727950
    mirekk36
    Poziom 42  
    A to jest nie tak, że nie doczytałeś o tzw "drganiach styków" i ich w ogóle nie eliminujesz programowo. A jakbyś jeszcze helpa bascomicznego poczytał to zobaczyłbyś, że masz w tym celu gotowe polecenie jak Debounce, które od razu załatwi te problemy z obsługą klawiszy ;)
  • REKLAMA
  • #3 7727957
    wywrot88
    Poziom 17  
    Witam, przez 0.7 sekundy program nie widzi stanu pinów, wiec na nie nie reaguje. Proponuję dwa wyjścia
    1) wstrzymanie również umieścić w warunku
    if pind.0=0 then
    portb.0=0
    waitms 200
    portb.0=1
    endif

    2) chyba lepsze: zastosować timer
  • #4 7727971
    mirekk36
    Poziom 42  
    wywrot88 napisał:

    2) chyba lepsze: zastosować timer


    Do tak prostej rzeczy wystarczy najspokojniej w świecie Debounce - po to ono jest, albo jakaś własna najprostsza metoda obsługi drgań styków - toż ta metoda to tylko jeden dodatkowy warunek i króciutkie oczekiwanie rzędu 40-50ms
  • REKLAMA
  • #5 7728431
    janbernat
    Poziom 38  
    Z bólem serca- bo wait jest bee- podobnie debounce jest bee ale wklejam działający kod
    
    $regfile = "m8def.dat"
    $crystal = 1000000
    
    Config Portb = &B11111111
               Portb = &B11111111
    Config Portd = &B1111100
               Portd = &B11111111
    
    Dim Temp_0 As Byte
    Dim Temp_1 As Byte
    
    Do
    
        If Pind.0 = 0 Then
         Waitms 20
           If Pind.0 = 0 Then
              If Temp_0 = 1 Then
                Portb.0 = 0
                Temp_0 = 0
                Waitms 200
                Portb.0 = 1
              End If
           End If
         Else
          Temp_0 = 1
         End If
    
        If Pind.1 = 0 Then
         Waitms 20
           If Pind.1 = 0 Then
             If Temp_1 = 1 Then
                Portb.0 = 0
                Temp_1 = 0
                Waitms 500
                Portb.0 = 1
              End If
            End If
         Else
          Temp_1 = 1
         End If
    
    Loop
    


    A tu druga wersja:
    
    $regfile = "m8def.dat"
    $crystal = 1000000
    
    Config Portb = &B11111111
               Portb = &B11111111
    Config Portd = &B1111100
               Portd = &B11111111
    
    Do
    
      Debounce Pind.0 , 0 , Procedura_1
    
      Debounce Pind.1 , 0 , Procedura_2
    
    Loop
    
     Procedura_1:
        Portb.0 = 0
        Waitms 200
        Portb.0 = 1
     Return
    
      Procedura_2:
        Portb.0 = 0
        Waitms 500
        Portb.0 = 1
      Return
    

    Naucz się korzystać z przerwań od timerów bo powyżej wklejony kod rozwiązuje problem tylko pozornie.
    Działa w prostych programach ale blokuje działanie procesora na czas wszystkich poleceń wait.
    Po pewnym czasie zapragniesz zrobić program który ma działać szybko i wtedy wszystkie wait i debounce okrutnie się zemszczą.
    A tu w ostatnim poście tak to zrobiłem:
    https://www.elektroda.pl/rtvforum/topic1575861.html
  • #6 7731153
    hanibal0
    Poziom 11  
    dzięki wszystkim za odpowiedź, chciałbym podkreślić że dopiero się uczę programowania, a ogólnie raczej programistą nie zostanę, zależy mi raczej na prostych programach, które będę często sterować przekaźnikami.
    Z problemem poradziłem sobie następująco:
    
    $regfile = "m8def.dat"
    $crystal = 1000000
    
    Config Portb = &B11111111
               Portb = &B11111111
    Config Portd = &B1111100
               Portd = &B11111111
    
    
    Do
    
        If Pind.0 = 0 Then Gosub Dioda
        If Pind.1 = 0 Then Gosub Dioda
    
    Loop
    
    Dioda:
    
        Portb.0 = 0
        Waitms 4000
        Portb.0 = 1
    
    Return
    
    
    End
    

    Proszę o skomentowanie czy to właściwy tok rozumowania w moim przypadku, tzn. czy są jakieś przeciw wskazania do takiego kodu?
    Dodam, że program na diodzie działa idealnie, a różne czasy działania zamierzam zmienić poprzez dodanie drugiego podprogramu (Dioda1).
  • REKLAMA
  • #7 7731584
    janbernat
    Poziom 38  
    I ten program będzie chodził dopóki w podprogramie będzie waitms 4000.
    Jeśli z jakichkolwiek powodów w podprogramie nie będzie waitms albo np. będzie waitms 1 to program może zacząć chodzić dziwnie.
    Lepiej zastosować w tym wypadku drugą z podanych wyżej wersji z drobną zmianą:
    Debounce Pind.0 , 0 , Dioda , sub

    A hobby trzeba uprawiać starannie i zgodnie z regułami sztuki.
    To zawodowcy czasem robią na "odwal" bo im się spieszy.
  • #8 7731855
    hanibal0
    Poziom 11  
    ok zrobiłem tak jak radził kolega janbernat, program wygląda następująco:
    $regfile = "m8def.dat"
    $crystal = 1000000
    
    Config Portb = &B11111111
               Portb = &B11111111
    Config Portd = &B1111100
               Portd = &B11111111
    
    
    Do
    
      Debounce Pind.0 , 0 , Dioda
    
      Debounce Pind.1 , 0 , Dioda1
    
    Loop
    
     Dioda:
        Portb.0 = 0
        Waitms 4000
        Portb.0 = 1
     Return
    
      Dioda1:
        Portb.0 = 0
        Waitms 2000
        Portb.0 = 1
      Return
    


    czy może mi ktoś wyjaśnić tak "łopatologicznie" zasadę działania polecenia Debounce? po co na końcu dodaje się komende SUB?

    kolejna prośba czy może mi ktoś podać jakieś wskazówki jak nauczyć się kożystać z TIMERA, w helpie nie wiele jest na ten temat, może ma ktoś jakiś prosty programik na podstawie którego mógł by mi wytłumaczyć zasadę działania TIMERA w atmega8.

    Rozumiem że dla większości są to śmieszne pytania, ale dla kogoś kto nigdy nie miał styczności z uC i programowaniem to nie jest takie proste. Z rozumowaniem raczej nie mam problemów, tylko z odnalezieniem odpowiednich komend (języka programu).

    Chciałbym ten programik przerobić tak aby po naciśnięciu SW2, dioda mrugała do momentu ponownego naciśnięcia SW2, czyli:
    1. wciskam SW2
    2. dioda mruga
    3. wciskam SW2
    4 wracam do początku programu
  • #9 7731880
    wywrot88
    Poziom 17  
    Debounce na chłopski rozum: mierzy dwukrotnie stan wejścia (eliminuje drganie) i jeśli jest taki jak oczekiwany wtedy działa tak jak Gosub
  • #10 7731894
    hanibal0
    Poziom 11  
    dzięki wywrot88, czyli wychodzi na to że w tym przypadku faktycznie lepiej użyć polecenia Debounce, ale co zmieni jeśli na końcu dodam polecenie SUB?

    i jak przerobić ten programik, żeby mi mrugały diody na SW2?
  • #11 7731929
    wywrot88
    Poziom 17  
    Najlepiej wykorzystaj timer. Możesz zastosować warunek
    config timer1=timer , prescale=1024
    if timer1>500 then portb.0=0
    if timer1>1000 then
    portb.0=1
    timer1=0
    endif

    jeśli się mylę lub jest prostszy sposób to sam chętnie skorzystam z podpowiedzi.
    a co robi sub na końcu- różnica jest mniej więcej taka jak pomiędzy goto a gosub.
  • #12 7735181
    janbernat
    Poziom 38  
    1. Wejdź na stronę firmową MCSElectronic i poszukaj pliku pomocy po polsku Bascom Help by Zbigniew Gibek po czym ściągnij i uruchamiaj przed uruchomieniem Bascoma.
    90% Twoich pytań tam znajdzie rozwiązanie.
    2. Kup książkę "Mikrokontrolery dla początkujących" Piotra Góreckiego.
    Nie szukaj w księgarniach tylko zamów przez internet w wydawnictwie BTC.
    3. Ściągnij notę katalogową procesora ATMega8 ze strony Atmel'a.

    Sub jest opcjonalne w poleceniu debounce.
    Do etykiety- czyli podprogramu bezparametrowego- możesz się odwoływać bez uprzedniej deklaracji declare sub.
    Tak że w tym szczególnym wypadku można wpisać sub lub nie- bez znaczenia.
REKLAMA