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

[Bascom] Pasek poziomu głośności oraz czasowy wyłącznik LCD

buh 24 Mar 2010 21:03 3551 28
REKLAMA
  • #1 7875950
    buh
    Poziom 22  
    Witam, mam problem z napisaniem fragmentu kodu odpowiedzialnego za wyświetlanie paska poziomu głośności oraz wyłączenia wyświetlacza LCD po ustalonym czasie.

    Może zacznę od sprzętu jakim dysponuję:
    - uC ATTiny2313
    - wyśw. LCD 2x16 znaków

    Najpierw pasek:
    ma on "zmieniać" położenie w zależności od pewnej zmiennej, pasek wygląda tak: "----O-----------", czyli 16 pozycji, zmienna jest typu Byte, czyli w zakresie 0-15 ma mieć postać: "O---------------", 16-31: "-O--------------" itd.

    Udało mi się napisać poprawnie działający pasek, ale jest jedna ogromna wada mojego rozwiązania - nie mieści się we flashu, ponieważ uC musi zapamiętać tekst do wyświetlenia dla każdej z wszystkich 16 pozycji. Myślałem nad użyciem czegoś w rodzaju Shiftlcd albo For X = 0 To 15 itp. ale nie wychodzi mi to. Chodzi tylko o to, aby te "O" z paska przesuwać w zależności od zmiany zmiennej (mniejsza bądź większa) kolejno w lewo lub w prawo. LCD w tym wypadku nie musi być "czyszczony".

    Fragment mojego kodu:
    
    Dim L As Byte
    L = 130 'wartość początkowa
    
    Cls
    Do
    'w tym miejscu jest pozostały działający kod
    
    If L >= 0 And <= 15 Then
    Lowerline
    Lcd "O---------------"
    End If
    
    If L >=  16 And L <= 31 Then
    Lowerline
    Lcd "-O--------------"
    End If
    
    'itd. dla pozostałych 14 pozycji
    


    Dodam, że Upperline nie chcę zmieniać, ma pozostać nienaruszona.

    Teraz wyłącznik czasowy LCD:
    Nie mam pojęcia czy takie coś idzie zrobić tylko na uC czy trzeba będzie użyć jakichś przerzutników bądź bramek. Od razu mówię, że nie chodzi mi o użycie komendy Display off, która kasuje tylko tekst z wyświetlacza. Chodzi mi o wyłączenie podświetlenia wyświetlacza. Czyli w skrócie: jeśli zmieni się cokolwiek na wyświetlaczu ma zostać włączone podświetlenie (Set na którymś z wybranych pinów uC) na jakiś tam czas (5-20s). Tak jak jest w komórkach. Po tym czasie wyświetlacz ma się znowu wyłaczyć (Reset na tym pinie). Cały problem polega na tym, że dane są cały czas wysyłane z uC do LCD i cały czas się zmienia stan wszystkich pinów (patrzyłem podłączając LED'a - migał na każdym), dlatego nie wiem jak to zrobić i proszę o pomoc.
  • REKLAMA
  • #2 7876013
    tadzik85
    Poziom 38  
    Podświetlenie a wyłączenie wyświetlacza komendą display off to zupełnie co innego.

    A pasek poziomu można zrobić w dużo prostszy sposób. Przesuń zmienną o 4 bity w prawo. Ustaw kursor na pozycji wskazanej przez zmienną rysując 'O'. Najpierw zapełnij linie kreskami. Więc zdecyduj się czy chodzi ci o podświetlenie czy o wyłączenie wyświetlacza.
  • REKLAMA
  • #3 7876061
    buh
    Poziom 22  
    Chodzi mi o włączenie podświetlenia, czyli ustawienie setu na anodzie LEDa w wyświetlaczu na jakiś czas, po tym czasie podświetlenie ma się wyłączyć.
  • #5 7876091
    tadzik85
    Poziom 38  
    Więc timer do dzieła a podświetlenie steruj poprzez klucz tranzystorowy.
  • #6 7876281
    arktik1
    Poziom 27  
    Jeśli chcesz to zrobić w ten sposób, to zrób to tak:
    
    Locate 2 , 1
    If L = 0 Then Lcd "0---------------"
    If L = 16 Then Lcd "-0--------------"
    

    Itd...

    Dodano po 5 [minuty]:

    Poza tym musisz ruszyć Timer gdy wartość będzie wynosiła 0.
    Wtedy gdy głośność będzie równa 0 timer odliczy czas i wyłączy wyświetlacz.
  • #7 7876367
    tadzik85
    Poziom 38  
    arktik1 podałeś złe warunki.
  • #8 7876378
    arktik1
    Poziom 27  
    Jak to złe??
  • REKLAMA
  • #9 7876403
    tadzik85
    Poziom 38  
    
    Locate 2 , 1
    If L < 16 Then Lcd "0---------------"
    If L >= 16 And L < 32 Then Lcd "-0--------------" 


    Takie a w twoim przypadku brak obsługi wartości pomiędzy.
  • #10 7876460
    arktik1
    Poziom 27  
    No tak ,nie przepisałem dokładnie tylko wziąłem kawałek swojego programu.
    Sorki.
  • #11 7876654
    buh
    Poziom 22  
    Ale to mi nic nie da, pisałem o tym w pierwszym poście. Chodzi mi o to, żeby nie pisać 16x tego co ma wyświetlić, bo to zajmuje dużo flasha, tylko napisać to raz i przesuwać w lewo/prawo. Pobawię się jutro z kursorem, zobaczymy co mi z tego wyjdzie.

    A co do podświetlania LCD - timerem mogę liczyć sobie ten czas podświetlenia ale to nie w tym tkwi problem. Konkretnie chcę wiedzieć skąd wziąć info o tym, że na wyświetlaczu coś się zmieniło albo, że został wciśnięty jakiś przycisk (konkretniej będę używał enkodera i 1 mikroswitcha). Na wyświetlacz idą cały czas jakieś informacje, czyli odpada. Może lepiej będzie sprawdzać info na przyciskach i jakiś przerzutnik, klucz prądowy (czyli bez udziału uC)?
  • REKLAMA
  • #12 7876711
    tadzik85
    Poziom 38  
    Jak ograniczyć ilość napisów w pamięci powiedziałem ci w moim 1 poście. Akcje do zapalenie wyświetlacza masz, jakiekolwiek, dodatkowo startujesz (zerujesz) nimi licznik. Licznik odmierzy ci odpowiedni czas, a jego przerwanie spowoduje wyłączenie podświetlenia. Klucz tranzystorowy sterowany z portu procesora.
  • #13 7877116
    Logan
    Poziom 30  
    Można prościej. Rysujesz sobie 16 razy "-", a później:
    If L < 16 then poz = 1
    If L >=16 AND <= 32 then poz =2

    itd.

    Następnie:
    Locate 2, poz
    Lcd "0"


    Instrukcja Select Case może być w tym przypadku nawet lepsza. Zapraszam do Helpa :)
    Zobacz jeszcze ten wskaźnik:
    Deflcdchar 0 , 31 , 16 , 16 , 16 , 16 , 16 , 16 , 31       ' replace ? with number (0-7)
    Deflcdchar 1 , 31 , 32 , 32 , 32 , 32 , 32 , 32 , 31       ' replace ? with number (0-7)
    Deflcdchar 2 , 31 , 1 , 1 , 1 , 1 , 1 , 1 , 31       ' replace ? with number (0-7)
    Deflcdchar 3 , 31 , 16 , 23 , 23 , 23 , 23 , 16 , 31       ' replace ? with number (0-7)
    Deflcdchar 4 , 31 , 32 , 31 , 31 , 31 , 31 , 32 , 31       ' replace ? with number (0-7)
    Deflcdchar 5 , 31 , 1 , 29 , 29 , 29 , 29 , 1 , 31       ' replace ? with number (0-7)
    Cls
    
    Locate 2 , 1
    Lcd Chr(0)
    For A = 1 To 14
    Lcd Chr(1)
    Next
    Lcd Chr(2)
    Locate 2 , 1
    Lcd Chr(3)
    Waitms 40
    For A = 1 To 14
    Lcd Chr(4)
    Waitms 40
    Next
    Lcd Chr(5)
    Return
    
  • #14 7877586
    tadzik85
    Poziom 38  
    If L < 16 then poz = 1
    If L >=16 AND <= 32 then poz =2


    Zamiast 16-stu ifów zmienną L podziel przez 16 lub przesuń o 4 bity w prawo wówczas jako wynik otrzymasz pozycje znaku 'O' w linii.
  • #16 7880987
    Konto nie istnieje
    Poziom 1  
  • #17 7882291
    arktik1
    Poziom 27  
    Można jeszcze nie używać timera.
    
    If Q = 101 Then Q = 0
    
    If P <= 1 Then
    Incr Q
    Else
    Q = 0
    Portb.x = 1
    Display On
    End If
    
    If Q = 100 Then
    Display Off
     Portb.x = 0
    End If
    

    Tylko trzeba odpowiednio dobrać wartość Q.
  • #18 7883228
    buh
    Poziom 22  
    tadzik85 napisał:
    If L < 16 then poz = 1
    If L >=16 AND <= 32 then poz =2


    Zamiast 16-stu ifów zmienną L podziel przez 16 lub przesuń o 4 bity w prawo wówczas jako wynik otrzymasz pozycje znaku 'O' w linii.


    Zrobiłem tak jak napisałeś, ponieważ jest to dla mnie chyba najlepsze rozwiązanie (ledwo 3 linijki kodu) i tu pojawia się następny problem. Gdy podzielę 256 / 16 wychodzi liczba całkowita, natomiast gdy zmienna będzie równa np. 237 i podzielę to na 16 to wyjdzie liczba z ułamkiem, której program nie "trawi", w efekcie moje "O" nie chce się przesuwać. Jakaś rada?
  • #19 7884211
    tadzik85
    Poziom 38  
    O ile dobrze pamiętam bascom na 2 rodzaje operacji dzielenia jedno w wyniku daje liczbę całkowita 2 liczbę rzeczywistą. Poza tym wykorzystanie dzielenia to przesada, lepiej i szybciej jest wykonać 4-krotne przesunięcie w prawo, które jest równoważne podzieleniu przez 16. AVR nie ma instrukcji dzielenia wobec tego wykorzystujesz skomplikowany algorytm. a przesunięcie to tylko 4 instrukcje.
  • #20 7887077
    buh
    Poziom 22  
    Przesunięcie zmiennej o 4 w prawo także nic nie daje, ten sam efekt jak przy dzieleniu przez 16.
  • #21 7887727
    arktik1
    Poziom 27  
    Pokaż cały kod.
  • #22 7889056
    Jacek Rutkowski
    Poziom 28  
    Wyświetlanie paska głośności:
    
    Dim L As Byte
    Dim Temp_l As Byte                                          'pomocnicza zmienna
    Config Lcd = 16 * 2
    
    L = 130                                                     'wartość początkowa
    
    Cls
    Do
    
          Temp_l = L / 16
    
          Temp_l = L + 1
          Locate 2 , 1
          Lcd "----------------"
    
          Locate 2 , Temp_l
          Lcd "0"
    Loop
    

    Czy dzielisz L przez 16 tzn zmienna Byte i wynikiem dzielenia też jest zmienna Byte?
  • #24 7892106
    Jacek Rutkowski
    Poziom 28  
    Zgadza się powinno być:
    
    Temp_l = L / 16
    
    Temp_l = Temp_l + 1
    

    pisałem to na szybkiego i przeoczyłem.
  • #25 7895939
    buh
    Poziom 22  
    Poradziłem sobie z paskiem, ale dalej mam problem z ustawieniem timera.

    Znalazłem taki oto kod napisany przez kolegę emarcus:

    
    $regfile = "m8def.dat" 
     $crystal = 4000000 
      Config Portd.0 = Input                                    'przykladowe wejscie 
      ' do wejscia dolaczono  przycisk (momentary push ON/OFF) 
      Config Portd.1 = Output                                   'przykadowe wyjscie 
      Portd.0 = 1 
      Portd.1 = 0 
    Config Portb = Output                                       'lcd display 
    
    Const T_max = 10                                            ' preset zmiennej 'czas' 
    Const Timer1reload = 62500      ' tyle tikow zegara potrzeba dla 1 sec. 
    Config Timer1 = Timer , Prescale = 64 
    Dim Czas As Byte 
    
    Dim Z As Bit 
    Z = 0 
    load timer1 , Timer1Reload 
    On Ovf1 Timer1_isr 
    Enable Timer1 
    Enable Interrupts 
    Cls 
    Lcd "START" 
    Waitms 500 
    Cls 
    
    Do 
    If Portd.0 = 1 And Z = 0 Then 
      Locate 1 , 1 
      Lcd "czekaj na pind" 
       End If 
    If Portd.0 = 0 And Z = 0 Then 
     Set Z 
     Czas = 0 
      Load Timer1 , Timer1reload 
    End If 
    If Z = 1 Then 
     Locate 1 , 1 
     Lcd "UPLYW CZASU:" ; Czas ; "sec" 
     Locate 2 , 1 
     Lcd "TIMER1: " ; Timer1 
       End If 
    
    If Z = 1 And Czas = T_max Then                              'dla potrzeb testowych  czas przyjeto 10 sec. (zakres czasu jest: 0 do 255) 
    Portd.1 = 1 
    Gosub Upd_displ 
    
     Portd.1 = 0 
     End If 
    Loop 
    
      Timer1_isr: 
     Load Timer1 , Timer1reload 
        Incr Czas 
      Return 
    
      Upd_displ: 
         Cls 
         Lcd "TIME OUT" 
         Locate 2 , 1 
         Lcd "CZAS:" ; Czas ; "sec." 
         Czas = 0 
         Z = 0 
         Waitms 500 
         Cls 
      Return
    


    Dodam, że przesiadłem się na Atmege 8 (potrzebny mi będzie większy flash).
    Jak ustawić Timer1, aby odliczał 10s po zmianie stanu na wejściu i po odliczeniu tego czasu ustawiał inny stan na wyjściu? Na moje potrzeby przerobiłem to tak:

    
    $regfile = "m8def.dat" 
    $crystal = 4000000
     
    Config Pind.3 = Input
    Set Pind.3                                                     'wejście pinu impulsatora
    
    Config Portd.7 = Output                                 'wyjscie dla anody podswietlenia 
    Reset Portd.7
     
    Const T_max = 10                                            'ustawienie 10s 
    Config Timer1 = Timer , Prescale = 64
     
    Dim Czas As Byte 
    
    load timer1 , 62500 
    On Timer1 Tmr 
    Enable Timer1 
    Enable Interrupts
     
    Do 
    If Pind.3 = 0 Then  
      Czas = 0 
      Load Timer1 , 62500 
    End If 
    
    If Czas = T_max Then
      Portd.7 = 0   
      End If 
    Loop 
    
    Tmr: 
    Load Timer1 , 62500 
    Incr Czas 
    Return 
    


    Będzie to chodzić, czy bit Z był tu potrzebny?
  • #26 7897049
    arktik1
    Poziom 27  
    Jeśli nie potrzebny ci dokładny czas to zrób to na liczniku.
  • #27 7897080
    buh
    Poziom 22  
    Programowym czy sprzętowym?
  • #28 7897785
    Konto nie istnieje
    Poziom 1  
  • #29 7898575
    arktik1
    Poziom 27  
    Programowym ,przecież podałem ci wyżej.
REKLAMA