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

"Przesuwanie" stanu wysokiego jednym przyciskiem-

wojtek2812 13 Cze 2010 13:02 1958 23
  • #1 8185257
    wojtek2812
    Poziom 22  
    Witam! W temacie się nie zmieściło więc wyjaśnię, że chodzi mi o Bascoma. Dopiero zaczynam przygodę z programowaniem i chciałbym wykonać następującą rzecz, ale niestety nie mam pomysłu jak i z której strony to ugryźć. Chodzi mi o coś takiego: W momencie włączenia urządzenia na którymś z portów, dajmy na to PB0 pojawia się stan wysoki. Domyślam się że da się to zrealizować komendą set. Chciałbym, żeby ten stan utrzymywał się dopóki nie nacisnę przycisku. Wówczas stan PB0 miałby zmienić się na niski i Na PB1 miałbym jedynkę. I znowu- po wciśnięciu przycisku na PB0 i PB1 stan niski a na PB2- wysoki. Przy następnym naciśnięciu przycisku PB0- stan wysoki, pozostałe niski, i tak w kółko. Proszę kolegów o podpowiedź jak to zrealizować. Domyślam się że kilka pętli Do...Loop załatwiłoby sprawę jednak kompletnie brak mi pomysłu bo zapewne dojdzie jakiś dodatkowy warunek który będzie wskazywał programowi wykonanie pętli i powrót na początek programu gdy na PB2 będzie stan wysoki i będę chciał by program "ruszył od nowa" czyli powrócił do stanu na chwilę po załączeniu urządzenia.
  • #2 8187033
    janbernat
    Poziom 38  
    Albo "rotate" albo "shift".
  • #3 8187040
    mateur
    Poziom 15  
    Czyli:

    - chcesz 3 porty jako wyjściowe po których cyklicznie przesuwa się stan wysoki
    - 1 przycisk po którego naciśnięciu stan wysoki przesunie się na kolejne wyjście
    - stan wysoki na wyjściu ma się utrzymywać do kolejnego naciśnięcia przycisku

    czy tak to ma wyglądać?
  • #5 8187693
    wojtek2812
    Poziom 22  
    Mikrokontroler jest konieczny ze względu na to że ma być to termometr z wyświetlaczem który ma podświetlenie diodami RGB i zmiany stanów portów mają posłużyć zmianie koloru podświetlenia wyświetlacza. Samą część programu dotyczącą termometru już mam, tylko te zmiany stanów blokują mi jego dokończenie
    mateur napisał:
    Czyli:

    - chcesz 3 porty jako wyjściowe po których cyklicznie przesuwa się stan wysoki
    - 1 przycisk po którego naciśnięciu stan wysoki przesunie się na kolejne wyjście
    - stan wysoki na wyjściu ma się utrzymywać do kolejnego naciśnięcia przycisku

    czy tak to ma wyglądać?

    Dokładnie tak.
  • #6 8189433
    mateur
    Poziom 15  
    
    $regfile = "attiny2313.dat"
    $crystal = 1000000
    
    Config Portb.0 = Output                                     'konfiguracja portów wyjściowych dla diod LED (przykład)
    Config Portb.1 = Output
    Config Portb.2 = Output
    Config Pinb.7 = Input                                       'port jako wejście dla sygnału z przycisku
    
    Dim A As Byte
    
    Declare Sub Kolor1                                          'deklaracje "podprogramów" dla różnych kolorów
    Declare Sub Kolor2
    Declare Sub Kolor3
    
    A = 0
    
    Do
    
    
    '<--- tu jest miejsce dla pozostałej części programu
    
    
    If Portb.7 = 1 Then                                         'zwiększanie zmiennej wyboru podprogramu
     Incr A
      End If
    
    If A = 0 Then                                               'przyporządkowanie wartości zmiennej dla danego podprogramu
     Gosub Kolor1
      End If
    
    If A = 1 Then
     Gosub Kolor2
      End If
    
    If A = 2 Then
     Gosub Kolor 3
      End If
    
    If A > 2 Then                                               'zerowanie zmiennej
     A = 0
      End If
    
    Loop
    
    End
    
    Kolor1:
    
    Set Portb.0                                                 'tu chyba wszystko wiadomo :)
    Reset Portb.1
    Reset Portb.2
    
    Return
    
    Kolor2:
    
    Reset Portb.0
    Set Portb.1
    Reset Portb.2
    
    Return
    
    Kolor3:
    
    Reset Portb.0
    Reset Portb.1
    Set Portb.2
    
    Return
    


    To jest oczywiście tylko przykład. Możliwe, że da się to zrobić w inny, ładniejszy sposób ale taki przyszedł mi do głowy :D nie wiem też jak to będzie działać. Być może trzeba będzie jeszcze coś dopisać (to oczywiście dopiero wyjdzie po uruchomieniu układu) ale myślę, że sama idea została przekazana.
    Sprawa była by oczywiście dużo łatwiejsza jeśli mikrokontroler miałby się zająć tylko zmianą kolorów, a jak wynika z tego co napisałeś ma to być jedynie dodatek :)

    Pozdrawiam
  • #8 8190061
    wojtek2812
    Poziom 22  
    Wiem że nie bolą ale niewiele daje mi czytanie pomocy. Czasem po prostu lepiej jak ktoś wytłumaczy. Dziękuję za dotychczasową pomoc.
    Powiem wam koledzy że też chodziły mi po głowie kombinacje z podprogramami jednak moja radosna (nie)twórczość kończyła się niedziałającym programem, zdenerwowaniem i rzuceniem tego na jakiś czas. :D
    Program wgrałem do procka ale niestety póki co nie działa ale chociaż mam jakiś punkt zaczepienia.
    Efekt jest taki, że po włączeniu procek idzie do pierwszego podprogramu i nie reaguje w ogóle na przycisk. W czym może tkwić problem?
  • #9 8190516
    mateur
    Poziom 15  
    Chyba już wiem :)
    
    $regfile = "attiny2313.dat"
    $crystal = 1000000
    
    Config Portb.0 = Output                                     'konfiguracja portów wyjściowych dla diod LED (przykład)
    Config Portb.1 = Output
    Config Portb.2 = Output
    Config Pinb.7 = Input                                       'port jako wejście dla sygnału z przycisku
    
    Dim A As Byte
    
    Declare Sub Kolor1                                          'deklaracje "podprogramów" dla różnych kolorów
    Declare Sub Kolor2
    Declare Sub Kolor3
    
    A = 0
    
    Do
    
    
    '<--- tu jest miejsce dla pozostałej części programu
    
    
    If Portb.7 = 1 Then                                         'zwiększanie zmiennej wyboru podprogramu :
     Incr A                                                     'do 1
      If Portb.7 = 1 Then
        Incr A                                                  'do 2
          If Portb.7 = 1 Then
            Incr A                                              'do 3
          End If
       End If
    End If
    
    If A > 3 Then                                               'zerowanie zmiennej
     A = 0
      End If
    
    If A = 1 Then                                               'przyporządkowanie wartości zmiennej dla danego podprogramu
     Gosub Kolor1
      End If
    
    If A = 2 Then
     Gosub Kolor2
      End If
    
    If A = 3 Then
     Gosub Kolor 3
      End If
    
    
    Loop
    
    End
    
    Kolor1:
    
    Set Portb.0                                                 'tu chyba wszystko wiadomo :)
    Reset Portb.1
    Reset Portb.2
    
    Return
    
    Kolor2:
    
    Reset Portb.0
    Set Portb.1
    Reset Portb.2
    
    Return
    
    Kolor3:
    
    Reset Portb.0
    Reset Portb.1
    Set Portb.2
    
    Return
    


    Spróbuj teraz :)
  • #10 8190572
    wojtek2812
    Poziom 22  
    Tym razem z kolei na PB0-PB2 są stany niskie, brak reakcji na przycisk
  • #11 8190983
    arktik1
    Poziom 27  
    Może tak:
    
    Dim A As Byte
    
    
    Do
    Debounce Pinb.7 , 0 , In , Sub
    
    If A = 0 Then Gosub 0
    
    If A = 1 Then Gosub 1
    
    If A = 2 Then Gosub 2
    
    Loop
    End
    
    In:
    Incr A
    If A = 3 Then A = 0
    Return
    
    0:
     Portb.0 = 1
     Portb.1 = 0
     Portb.2 = 0
     Return
    1:
     Portb.0 = 0
     Portb.1 = 1
     Portb.2 = 0
     Return
    2:
     Portb.0 = 0
     Portb.1 = 0
     Portb.2 = 1
     Return
    


    Dodano po 4 [minuty]:

    I chyba tak będzie lepiej:
    
    Config Portb = &B01111111
            Portb = &B10000000
    


    Dodano po 2 [minuty]:

    Dodał bym jeszcze zmienną ,by nie skakał cały czas do 0,1,2, tylko robił to raz.
  • #12 8191387
    wojtek2812
    Poziom 22  
    Program podany przez kolegę arktik1 za który bardzo dziękuję działa świetnie. Mam jeszcze jedno pytanie. Mam tu program obsługi termometru autorstwa naszego forumowego kolegi Ducha.Oczywiście jest on trochę okrojony bo pierwotnie obsługiwał 4 czujniki:

    
    'Termometr 4 punktowy DS18b20 by Duch na podstawie materiałów znalezionych w sieci
    'Kontakt duszkowski@o2.pl
    
    
    $regfile = "m8def.DAT"                                      'deklaracja procesora, w tym wypadku Atmega8
    $crystal = 1000000                                          'deklaracja cześtotlwiości pracy (wew oscylator 1MHz w zupełności wystarcza)
    'Deklaracja portów od wyświetlacza LCD
    Config Lcdpin = Pin , Db4 = Portb.0 , Db5 = Portb.1 , Db6 = Portb.2 , Db7 = Portb.3 , E = Portb.4 , Rs = Portb.5
    
    Config Lcd = 16 * 2                                         'ustawiamy typ wyświetlacza (soft jest dostosowany do pracy z wyświetlaczem 2x20, przy pracy z innym wyświetlaczem trzeba będzie skorygować wyświetlanie znaków)
    
    '*************************************WAŻNE**********************************************
    'Pamiętać o podłączeniu rezystora podciągającego o wartości 4.7kohm między linią DQ a VCC
    Config Portd = &B01111111
            Portd = &B10000000
    Config 1wire = Portc.0                                      'deklaracja portu na którym będą podpięte DS18b20
    
    Dim A As Byte
    Dim I1 As Integer , Ss As String * 6
    Dim I2 As Integer
    
    
    Dim Dsid1(8) As Byte
    Dim Dsid2(8) As Byte
    
    Dim B As Byte                                               'deklaracja zmiennej do odczytu kodów ID
    Dim W As Byte                                               'deklaracja zmiennej do odczytu ilośc czujników
    
    Deflcdchar 0 , 2 , 5 , 2 , 32 , 32 , 32 , 32 , 32
               'znak stopnia Celsjusza
    Deflcdchar 1 , 16 , 16 , 20 , 24 , 16 , 16 , 30 , 32        ' Ł
    Cursor Off                                                  'Wyłącza kursor
    Cls                                                         'Funkcja CLS czyści ekran
    Lcd "     MI" ; Chr(1) ; "EGO     " ;                       'ekran startowy (pojawia się tylko podczas włączania urządzenia)
    Lowerline
    Lcd "      DNIA      "
    Wait 2
    Cls
                                                      'Znajdź pierwszy czujnik podpięty do portu
    Dsid1(1) = 1wsearchfirst()                                  'Znajdź kolejny czujnik podpięty do portu
    Dsid2(1) = 1wsearchnext()                                   'Znajdź kolejny czujnik podpięty do portu
    
    
    
    
    
    
    
    
    Do
       1wreset
       1wwrite &H55
       1wverify Dsid1(1)                                        'wysyłamy adres pierwszego czujnika
       1wwrite &HBE
       I1 = 1wread(2)
    '---------------------------------
       1wreset
       1wwrite &H55
       1wverify Dsid2(1)                                        'wysylam adres drugiego czujnika
       1wwrite &HBE
       I2 = 1wread(2)
    '---------------------------------
    
       1wreset
       1wwrite &HCC
       1wwrite &H44
    Waitms 750
    
    '****Jeśli pracujesz z wyświetlaczem innym niż 2x20 to tutaj trzeba wprowadzić zmiany w LOCATE********
    
       I1 = I1 * 10
       I1 = I1 / 16
       'If I1 > 0 Then Cls                                       'korekta przesuniecia znaku st C przy przejściu z temp ujemnej na dodatnią
       Ss = Str(i1)
       Ss = Format(ss , " 0.0")
       Locate 1 , 1                                             'Pozycja wyświetlania nazwy i temperatury (1.1 -> 1 linia 1 kolumna, 2.10 -> 2 linia 10 kolumna itd)
       Lcd "Temp.wew:" ; Ss ; Chr(0) ; "C"
    
       I2 = I2 * 10
       I2 = I2 / 16
       'If I2 > 0 Then Cls
       Ss = Str(i2)
       Ss = Format(ss , " 0.0")
       Locate 2 , 1
       Lcd "Temp.zew:" ; Ss ; Chr(0) ; "C"
    
       Loop
    
    

    Gdzie "wpleść" kawałek kodu kolegi arktik1 aby programy nie "gryzły się ze sobą"? Z góry dziękuję za pomoc. Pomocnych nagrodzę.
  • #13 8193279
    Dexter77
    Poziom 28  
    Strasznie to pokomplikowaliscie. Pseudokod:
    
    init:
    konfiguracja portow
    zmienna = 1
    portwyjsciowy=portwyjsciowy | zmienna
    
    SprawdzKlawisz:
    if KlawiszWcisniety then
      portwyjsciowy=portwyjsciowy & F8
      portwyjsciowy=portwyjsciowy | zmienna
      shiftleft zmienna    ;lub zmienna=zmienna*2
      if zmienna = 8 then zmienna = 1
    endif
    
  • #14 8193944
    arktik1
    Poziom 27  
    to:
    
    Debounce Pinb.7 , 0 , In , Sub
    
    If A = 0 Then Gosub 0
    
    If A = 1 Then Gosub 1
    
    If A = 2 Then Gosub 2 
    

    włóż gdzie chcesz do pętli.
    a resztę przenieś za pętlę.
  • #15 8258979
    wojtek2812
    Poziom 22  
    Witam po dłuższej przerwie. Więc tak. "Wrzuciłem" program podany przez kolegę arktik1 w ten, który obsługuje termometr jednak nie wiem czy zrobiłem to dobrze, tzn czy w dobrym miejscu. Objaw jest taki że termometr działa ale zmiana stanu średnio. Objawia się to jakby niestabilnością programu odpowiadającego za przesuwanie stanu. Działa jakby z opóźnieniem, nieraz trzeba wcisnąć kilka razy przycisk by zmienić stan. Zamieszczam listing programu
    'Termometr 4 punktowy DS18b20 by Duch na podstawie materiałów znalezionych w sieci
    'Kontakt duszkowski@o2.pl
    
    
    $regfile = "m8def.DAT"                                      'deklaracja procesora, w tym wypadku Atmega8
    $crystal = 1000000                                          'deklaracja cześtotlwiości pracy (wew oscylator 1MHz w zupełności wystarcza)
    'Deklaracja portów od wyświetlacza LCD
    Config Lcdpin = Pin , Db4 = Portb.0 , Db5 = Portb.1 , Db6 = Portb.2 , Db7 = Portb.3 , E = Portb.4 , Rs = Portb.5
    
    Config Lcd = 16 * 2                                         'ustawiamy typ wyświetlacza (soft jest dostosowany do pracy z wyświetlaczem 2x20, przy pracy z innym wyświetlaczem trzeba będzie skorygować wyświetlanie znaków)
    
    '*************************************WAŻNE**********************************************
    'Pamiętać o podłączeniu rezystora podciągającego o wartości 4.7kohm między linią DQ a VCC
    Config Portd = &B01111111
            Portd = &B10000000
    Config 1wire = Portc.0                                      'deklaracja portu na którym będą podpięte DS18b20
    
    Dim A As Byte
    Dim I1 As Integer , Ss As String * 6
    Dim I2 As Integer
    
    
    Dim Dsid1(8) As Byte
    Dim Dsid2(8) As Byte
    
    Dim B As Byte                                               'deklaracja zmiennej do odczytu kodów ID
    Dim W As Byte                                               'deklaracja zmiennej do odczytu ilośc czujników
    
    Deflcdchar 0 , 2 , 5 , 2 , 32 , 32 , 32 , 32 , 32
               'znak stopnia Celsjusza
    Deflcdchar 1 , 16 , 16 , 20 , 24 , 16 , 16 , 30 , 32        ' Ł
    Cursor Off                                                  'Wyłącza kursor
    Cls                                                         'Funkcja CLS czyści ekran
    Lcd "     MI" ; Chr(1) ; "EGO     " ;                       'ekran startowy (pojawia się tylko podczas włączania urządzenia)
    Lowerline
    Lcd "      DNIA      "
    Wait 2
    Cls
                                                      'Znajdź pierwszy czujnik podpięty do portu
    Dsid1(1) = 1wsearchfirst()                                  'Znajdź kolejny czujnik podpięty do portu
    Dsid2(1) = 1wsearchnext()                                   'Znajdź kolejny czujnik podpięty do portu
    
    
    
    
    
    
    
    
    Do
       1wreset
       1wwrite &H55
       1wverify Dsid1(1)                                        'wysyłamy adres pierwszego czujnika
       1wwrite &HBE
       I1 = 1wread(2)
    '---------------------------------
       1wreset
       1wwrite &H55
       1wverify Dsid2(1)                                        'wysylam adres drugiego czujnika
       1wwrite &HBE
       I2 = 1wread(2)
    '---------------------------------
    
       1wreset
       1wwrite &HCC
       1wwrite &H44
    Waitms 750
    
    '****Jeśli pracujesz z wyświetlaczem innym niż 2x20 to tutaj trzeba wprowadzić zmiany w LOCATE********
    
       I1 = I1 * 10
       I1 = I1 / 16
       'If I1 > 0 Then Cls                                       'korekta przesuniecia znaku st C przy przejściu z temp ujemnej na dodatnią
       Ss = Str(i1)
       Ss = Format(ss , " 0.0")
       Locate 1 , 1                                             'Pozycja wyświetlania nazwy i temperatury (1.1 -> 1 linia 1 kolumna, 2.10 -> 2 linia 10 kolumna itd)
       Lcd "Temp.wew:" ; Ss ; Chr(0) ; "C"
    
       I2 = I2 * 10
       I2 = I2 / 16
       'If I2 > 0 Then Cls
       Ss = Str(i2)
       Ss = Format(ss , " 0.0")
       Locate 2 , 1
       Lcd "Temp.zew:" ; Ss ; Chr(0) ; "C"
    
       Loop
    
         Do
    Debounce Pind.7 , 0 , In , Sub
    
    If A = 0 Then Gosub 0
    
    If A = 1 Then Gosub 1
    
    If A = 2 Then Gosub 2
    
    Loop
    End
    
    In:
    Incr A
    If A = 3 Then A = 0
    Return
    
    0:
     Portb.0 = 0
     Portb.1 = 1
     Portb.2 = 1
     Return
    1:
     Portb.0 = 1
     Portb.1 = 0
     Portb.2 = 1
     Return
    2:
     Portb.0 = 1
     Portb.1 = 1
     Portb.2 = 0
     Return
     End
    
  • #16 8259145
    janbernat
    Poziom 38  
    Waitms 750- to powoduje "niestabilność".
  • #17 8262691
    wojtek2812
    Poziom 22  
    Jak sobie z tym poradzić? Jak już wcześniej mówiłem raczkuję w bascomie i każda rada doświadczonych kolegów jest dla mnie cenna.
  • #18 8262742
    arktik1
    Poziom 27  
    Spróbuj usunąć WAITMS całkiem ,zobaczysz co będzie się działo.

    Dodano po 2 [minuty]:

    Przede wszystkim usuń tą drugą pętlę.Dziwie się że to w ogóle działa
  • #20 8262852
    Mat_91
    Poziom 25  
    Bo ominiecie wait za pomocą przerwań od timera i jakiejś flagi przy odczycie z ds'a to jedyne sensowne rozwiązanie. Wręcz tak się powinno robić i stosować jak najmniej waitów tym bardziej jeżeli zatrzymują procesor na tak długo (750ms dla uC to wieczność i w tym czasie można zrobić masę innych pożytecznych rzeczy).
  • #21 8263355
    arktik1
    Poziom 27  
    Ja bym cały termometr przeniósł do przerwania a resztę napisał w pętli.
  • #22 8263388
    Mat_91
    Poziom 25  
    A co Ci to da? Wystąpi przerwanie a w przerwaniu będziesz miał wait na 750ms który i tak zatrzyma program, i tak samo wolno procesor będzie reagował na przycisk, albo w ogóle program pójdzie w maliny (w zależności jak często będzie występowało przerwanie). To jeszcze gorsze rozwiązanie niż masz teraz.

    Chyba że chcesz zrobić tak, że przerwanie będzie się zgłaszało co 750ms i w jednym będziesz zlecał konwersję a w drugim odczytywał temperaturę.
  • #23 8263500
    janbernat
    Poziom 38  
    Cytat:

    Chyba że chcesz zrobić tak, że przerwanie będzie się zgłaszało co 750ms. Wtedy by to miało sens tylko że musiałbyś tak robić że najpierw odczytujesz temperaturę a dopiero później zlecasz jej konwersję.
    .
    No i to jest słuszne.
    Pierwszy odczyt po resecie będzie błędny- jak to rozwiązałem swoim programie- już nie pamiętam, musiałbym zajrzeć.
    Pamiętam że ALARM służył do wykrywania błędnego odczytu czyli 85 stopni.
    I ustawiony był na > 40 stopni.
    A w pętli głównej można obsłużyć przyciski i co tam jeszcze.
    I taka uwaga- programy z sieci albo z książek zwykle dobrze obsługują jeden przykład- pod warunkiem że procesor służy do obsługi tylko tego przykładu i niczego innego.
    Tylko odczyt temperatury z DS- proszę bardzo, taki wait nie przeszkadza.
    Tylko sterowanie obrotami silnika- też.
    Ale próba połączenia takich programów skończy się porażką.
    Oprócz analizy co procesor ma robić należy przed napisaniem programu wykonać chociaż ogólną analizę zależności czasowych zadań procesora.
  • #24 8263724
    arktik1
    Poziom 27  
    Nie zrozumieliśmy się.
    "Ja bym cały termometr przeniósł do przerwania a resztę napisał w pętli."
    i nie stosował WAITMS.
    Zastosował bym licznik który liczył by w pętli do X i wyskakiwał do temperatury, poczym wracał bez Wait.
    Z tego co widzę to nie ma tu żadnego alarmu, więc 1 odczyt nie ma wielkiego znaczenia.
REKLAMA