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

Zegar DCF77 z termometrem 2 x ds18b20 i podświetleniem .

11 Lut 2010 05:23 2766 9
  • Poziom 10  
    Witajcie ponownie , w głowie mojej zrodził się nowy pomysł , a że z Bascomem słabo więc znowu zwracam się do was .Jak w temacie chcę złożyć zegarek synchronizowany sygnałem DCF 77 , termometrem in - out na 2 x ds18b20 pod jedny gniazdem 1-wire , datą i podświetleniem włączanym czasowo po naciśnięciu klawisza. Mam parę programików do obsługi zegara dcf , do termometru i samodzielnie one działają ale po połączeniu ich do kupy nie wyświetlają nic,lub wyświetlają 1 z 4 żądanych linii a reszta pojawia się tylko na ułamek sekundy , bądź też wyświetla wszystko tj.
    1 linia - godzina
    2 linia - data
    3 linia - temp wew
    4 linia - temp zew
    ale linia godziny i daty nie są aktualizowane godzina pozostaje na 00:00:01, i koniec.
    W załączniku programiki z których próbowałem coś sklecić , może ktoś przerabiał już ten temat .Proszę o poradę ,pomoc. P.S Z czasem będę chciał dodać obsługę 2 klawiszy :
    1 do zmiany ustawianego parametru -godzina , minuta, dzień ,miesiąc,rok
    2 do zmiany wartości danego parametru
  • Poziom 14  
    wklej cały program, a nie poszczególne części, które i tak ci działają.
  • Poziom 10  
    Oto kod całego programu , wyświetla wszystkie linie ,jednak w momencie gdy zaczyna odczytywać temperature- ekran zaczyna mrygać, wygasza co ok 1s na 1s, potem kilka razu krócej aż przez całą sekundę jest obraz i tak od nowa .Po paru minutach chyba łapie błąd bo wyświetlacz zaczyna wyświetlać znaki graficzne jakie ma w pamięci.

    Code:
                'Zegar DCF77
    
    $regfile = "m8def.dat"
    $crystal = 8000000
    $lib "dcf77.lib"
    'Sygnał z odbiornika DCF podłączony do Portb.2
    Config Dcf77 = Pinb.2 , Debug = 1 , Inverted = 0 , Check = 1 , Update = 0 , Updatetime = 0 , Secondticks = 50 , Timer1sec = 1 , Powerlevel = 1 , Timer = 1 , Gosub = Sectic
    'Config Dcf77 = Pinb.2 , Debug = 1 , Inverted = 0 , Check = 1 , Update = 0 , Updatetime = 0 , Switchpower = 0 , Secondticks = 50 , Timer1sec = 1 , Powerlevel = 1 , Timer = 1 , Gosub = Sectic
    'Config Dcf77 = Pinb.1 , Debug = 1 , Inverted = 0 , Check = 2 , Update = 0 , Updatetime = 0 , Switchpower = 0 , Secondticks = 50 , Timer1sec = 1 , Powerlevel = 1 , Timer = 1 , Gosub = Sectic


    'Wyświetlacz LCD 16*2. Sygnały jak poniżej.
    Config Lcdpin = Pin , Db4 = Portc.3 , Db5 = Portc.2 , Db6 = Portc.1 , Db7 = Portc.0 , E = Portc.4 , Rs = Portc.5
    Config Lcd = 20 * 4
    Config 1wire = Portb.0                                      'deklaracja portu na którym będ? podpięte DS18b20

    Dim I1 As Integer , Ss1 As String * 6
    Dim I2 As Integer , Ss2 As String * 6


    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 , 8 , 20 , 11 , 4 , 4 , 4 , 3 , 32             'znak stopnia Celsjusza
    Cls
    'Lcd " " ;                                                   'ekran startowy (pojawia się tylko podczas wł?czania urz?dzenia)
    'Cursor Off
    'Locate 1 , 17
    'Lcd " termometr "
    'Wait 5
    'Cls
    W = 1wirecount()
    'Locate 2 , 17
    'Lcd "Czujniki:"                                             'Informuje ile czujników jest podpiętych do układu (pojawia się tylko podczas wł?czania urz?dzenia)
    'Waitms 500
    'Locate 2 , 27
    'Lcd W
    'Wait 3
    'Cls                                                         'Znajd? pierwszy czujnik podpięty do portu
    Dsid1(1) = 1wsearchfirst()                                  'Znajd? kolejny czujnik podpięty do portu
    Dsid2(1) = 1wsearchnext()


    Enable Interrupts
    Config Date = Dmy , Separator = /
    Do
    Wait 5

    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)
    '--------konwersja temp dla wszystkich dsow
    1wreset
    1wwrite &HCC
    1wwrite &H44
    Wait 1

    '****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?
    Ss1 = Str(i1)
    Ss1 = Format(ss1 , " 0.0")

    I2 = I2 * 10
    I2 = I2 / 16
    'If I2 > 0 Then Cls
    Ss2 = Str(i2)
    Ss2 = Format(ss2 , " 0.0")

    Loop

    Loop

    'Co sekundę aktualizuje wyświetlacz
    Sectic:
       Cls
       Locate 1 , 1
          Lcd Time$ ; "    ";
       If Pinb.2 = 0 Then Lcd "Rcvr" Else Lcd "    "
       Locate 2 , 1
       Lcd Date$

       Locate 2 , 17                                            'Pozycja wy?wietlania nazwy i temperatury (1.1 -> 1 linia 1 kolumna, 2.10 -> 2 linia 10 kolumna itd)
    Lcd "ZEW: " ; Ss1 ; Chr(0) ;
        Locate 1 , 17
    Lcd "WEW: " ; Ss2 ; Chr(0) ;
       Locate 2 , 1
       Lcd Date$
       Return

    End

    EDIT. Troszkę ztuningowałem , wyświetla poprawnie 4 linie,chociaż co 1 sekundę widoczne mrugnięcie, ale jest przesunięcie wyświetlanych temperatur:

    WEW:_26.6C
    ZEW:__-3.6C
    nie bardzo wiem jak to poprawić i gdzie oraz jak dopisać obsługę klawiszy.
    Może jakieś osobne suby w których będzie zawarta instrukcja , ale później trzeba ją wywołać naciśnięciem przycisku (gdzie dać wywołanie , jak rozbić czas na godz ,min ,żeby później móc je zwiększać).
  • Poziom 14  
    Po co ci te 2-a do..loop?
    W sectic powinneś mieć:
    cls
    wyświetlenie godziny
    wyświetlenie daty
    pobranie danych z DS-ów i ich wyświetlenie
    na końcu zlecenie konwersji temperatury dla DS

    i zlikwiduj to end sub na końcu!
  • Poziom 10  
    Na razie jest tak :
    Code:
                'Zegar DCF77
    
    $regfile = "m8def.dat"
    $crystal = 8000000
    $lib "dcf77.lib"
    'Sygnał z odbiornika DCF podłączony do Portb.2
    Config Dcf77 = Pinb.2 , Debug = 1 , Inverted = 0 , Check = 1 , Update = 0 , Updatetime = 0 , Secondticks = 50 , Timer1sec = 1 , Powerlevel = 1 , Timer = 1 , Gosub = Sectic
    'Config Dcf77 = Pinb.2 , Debug = 1 , Inverted = 0 , Check = 1 , Update = 0 , Updatetime = 0 , Switchpower = 0 , Secondticks = 50 , Timer1sec = 1 , Powerlevel = 1 , Timer = 1 , Gosub = Sectic
    'Config Dcf77 = Pinb.1 , Debug = 1 , Inverted = 0 , Check = 2 , Update = 0 , Updatetime = 0 , Switchpower = 0 , Secondticks = 50 , Timer1sec = 1 , Powerlevel = 1 , Timer = 1 , Gosub = Sectic


    'Wyświetlacz LCD 16*2. Sygnały jak poniżej.
    Config Lcdpin = Pin , Db4 = Portc.3 , Db5 = Portc.2 , Db6 = Portc.1 , Db7 = Portc.0 , E = Portc.4 , Rs = Portc.5
    Config Lcd = 20 * 4
    Config 1wire = Portb.0                                      'deklaracja portu na którym będ? podpięte DS18b20

    Dim I1 As Integer , Ss1 As String * 6
    Dim I2 As Integer , Ss2 As String * 6


    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 , 8 , 20 , 11 , 4 , 4 , 4 , 3 , 32             'znak stopnia Celsjusza
    Cls
    'Lcd " " ;                                                   'ekran startowy (pojawia się tylko podczas wł?czania urz?dzenia)
    'Cursor Off
    'Locate 1 , 17
    'Lcd " termometr "
    'Wait 5
    'Cls
    W = 1wirecount()
    'Locate 2 , 17
    'Lcd "Czujniki:"                                             'Informuje ile czujników jest podpiętych do układu (pojawia się tylko podczas wł?czania urz?dzenia)
    'Waitms 500
    'Locate 2 , 27
    'Lcd W
    'Wait 3
    'Cls                                                         'Znajd? pierwszy czujnik podpięty do portu
    Dsid1(1) = 1wsearchfirst()                                  'Znajd? kolejny czujnik podpięty do portu
    Dsid2(1) = 1wsearchnext()


    Enable Interrupts
    Config Date = Dmy , Separator = /
    Do
    Wait 5


    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)
    '--------konwersja temp dla wszystkich dsow
    1wreset
    1wwrite &HCC
    1wwrite &H44
    Wait 1

    '****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?
    Ss1 = Str(i1)
    Ss1 = Format(ss1 , " 0.0")

    I2 = I2 * 10
    I2 = I2 / 16
    'If I2 > 0 Then Cls
    Ss2 = Str(i2)
    Ss2 = Format(ss2 , " 0.0")



    Loop

    'Co sekundę aktualizuje wyświetlacz
    Sectic:
       Cls
       Locate 1 , 1
          Lcd Time$ ; "    ";
       If Pinb.2 = 0 Then Lcd "Rcvr" Else Lcd "    "
       Locate 2 , 1
       Lcd Date$

       Locate 2 , 17                                            'Pozycja wy?wietlania nazwy i temperatury (1.1 -> 1 linia 1 kolumna, 2.10 -> 2 linia 10 kolumna itd)
    Lcd "ZEW:" ;
        Locate 2 , 23
    Lcd Ss1 ; Chr(0) ;

        Locate 1 , 17
    Lcd "WEW:" ;
       Locate 1 , 23
    Lcd Ss2 ; Chr(0) ;

       Locate 2 , 1
       Lcd Date$
       Return

       End



    Zlikwidowanie drugej pętli do - loop powoduje po każdym wyświetleniu temperatury resetowanie i ponowne uruchomienie procedur mierzenia temperatury, i tak w kółko.
    Na razie programik działa ,tylko nie mogę ustawić wyświetlania równo , dziesiątki pod dziesiątkami ,jedności pod jednościami itp. Jak to zwalczę powalcze z klawiszami.
    Tylko nie wiem co będzie lepsze , czy obsługa 1 klaw. do godzin (zwiększanie ) i 1 klawisz do minut itd. ale da to minimum 5 klawiszy z datą , czy też 2 lub 3 klawisze jeden do wyboru jednostki która ma być zmieniana i 1 lub 2 do zmian , ale tego podprogramu to ja nie napisze.Jak zrobić ,żeby wyświetlacz nie był odświeżany a zmieniało się tylko to co na bieżąco się zmienia (minuty , sekundy itp), ewentualnie żeby był odświeżany na tyle szybko ,żeby było to nie zauważalne.
  • Poziom 14  
    Najlepiej na 3 klawisze, ale nadal masz złą koncepcje kodu. albo decydujesz się wyświetlać wszystko przy obsłudze przerwania ( DS potrzebuje 750ms na konwersję), w jedne sekundzie chyba się wyrobisz, albo za pomocą przerwania ustwaić flagę zlecenia wykonania programu (hm.. profesjonalnie :-) ).
    ogólny algorytm tego powinien wyglądać następująco:
    Code:



    ...
    dim flaga1 as bit
    ...
    ...
    do
        if flaga1=1 then
            flaga1=0
            wyświetl date
            wyświetl temp
            zleć konwersje
        end if
        ewentualna obsluga przycisku 1
        ewentualna obsluga przycisku 2
        itp...
    loop
    sectic:
        set flaga1
    return
  • Poziom 10  
    Witam , dzisiaj chyba za dużo nie powalczę -dopiero w niedziele będzie więcej czasu.
    Leon1313 dziękuje za pomoc ,czy obsługę klawiszy można napisać tak :
    Załóżmy flaga Mode której stan będzie się zmieniał po naciśnięciu przycisku 1 stan flagi 0, po naciśnięciu 1 i tak do 5 po 5 znów 0.
    If Mode > 5 then
    Mode = 0
    Klawisz UP i tu warunek
    If mode = 1 and up = 0 then incr (i tu jakieś odwołanie do godziny ) albo H=H+1
    If mode = 2 and up = 0 then incr minuta albo MIN=MIN+1
    podobnie z minutami i całą datą po kolei.
    Tylko nie wiem jak rozdzielić czas i datę na pojedyńcze wartości które będę mógł modyfikować.

    Code:

    Cls
       Locate 1 , 1
       Lcd Time$ ; "    ";                                     'Wyświetlenie czasu
       If Pinb.2 = 0 Then Lcd "Rcvr" Else Lcd "    "
       Locate 2 , 1
       Lcd Date$                                                'Wyświetlenie daty

       Locate 2 , 17                                           
    Lcd "ZEW:" ;
        Locate 2 , 23
    Lcd Ss1 ; Chr(0) ;
    Locate 1 , 17
    Lcd "WEW:" ;
       Locate 1 , 23
    Lcd Ss2 ; Chr(0) ;


    1wreset
    1wwrite &HCC
    1wwrite &H44
          Return

    Czy tak ma wyglądać ta flaga czy coś pominąłem ?
  • Poziom 14  
    Flaga to flaga, znacznik, że masz wykonać część programu :-)

    Wyjaśnię to inaczej. Przerwanie sectic co 1 sekundę ustawia flaga1 w stan wysoki. główny program w pętli do...loop, jeżeli wykryje, że flaga 1 jest ustawiona w stan wysoki, wykona polecenia między THEN a END IF, czyli najpierw:
    - zresetuje tą flagę, aby nie wykonać programu dopóki przerwanie znowu na to nie pozwoli
    - powinien wyświetlić czas i datę
    - odczytać temperaturę z DS ( czego ci brak) i wyświetlić ją
    - zlecić ponownie konwersję ( tu przypominam, pętla if flaga1..end if jest wykonywana co sekundę!), i przy ponownym przebiegu powtórzyć
    - to, co jest w do.loop a za if flaga1..end if będzie szybko wykonywane, więc warto tu dać obsługę klawiszy i menu
    Jeśli masz problemy z uporządkowaniem kodu, podziel to sobie na sub-y : wszakże to nieprofesjonalne, jak jeden z userów już zwrócił mi uwagę, ale pod względem czytelności przydatne.
  • Poziom 10  
    Witam , program w tej chwili wygląda tak :
    Code:
    'Zegar DCF77
    
    $regfile = "m8def.dat"
    $crystal = 8000000
    $lib "dcf77.lib"
    'Sygnał z odbiornika DCF podłączony do Portb.2
    Config Dcf77 = Pinb.2 , Debug = 1 , Inverted = 0 , Check = 1 , Update = 0 , Updatetime = 0 , Secondticks = 50 , Timer1sec = 1 , Powerlevel = 1 , Timer = 1 , Gosub = Sectic
    'Config Dcf77 = Pinb.2 , Debug = 1 , Inverted = 0 , Check = 1 , Update = 0 , Updatetime = 0 , Switchpower = 0 , Secondticks = 50 , Timer1sec = 1 , Powerlevel = 1 , Timer = 1 , Gosub = Sectic
    'Config Dcf77 = Pinb.1 , Debug = 1 , Inverted = 0 , Check = 2 , Update = 0 , Updatetime = 0 , Switchpower = 0 , Secondticks = 50 , Timer1sec = 1 , Powerlevel = 1 , Timer = 1 , Gosub = Sectic
    Config Lcdpin = Pin , Db4 = Portc.3 , Db5 = Portc.2 , Db6 = Portc.1 , Db7 = Portc.0 , E = Portc.4 , Rs = Portc.5
    Config Lcd = 20 * 4
    Config 1wire = Portb.0                                      'deklaracja portu na którym będ? podpięte DS18b20
    Klmode Alias Portb.3
    Klup Alias Portb.4
    Kldown Alias Pinb.5
    Set Klmode
    Set Klup
    Set Kldown

    Dim Flaga1 As Bit
    Dim I1 As Integer , Ss1 As String * 6
    Dim I2 As Integer , Ss2 As String * 6
    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 , 8 , 20 , 11 , 4 , 4 , 4 , 3 , 32             'znak stopnia Celsjusza
    Cls
    Lcd " " ;                                                   'ekran startowy (pojawia się tylko podczas wł?czania urz?dzenia)
    Cursor Off
    Locate 1 , 17
    Lcd " termometr "
    Wait 5
    Cls

    W = 1wirecount()
    Dsid1(1) = 1wsearchfirst()                                  'Znajd? pierwszy czujnik podpięty do portu
    Dsid2(1) = 1wsearchnext()                                  'Znajd? kolejny czujnik podpięty do portu

    Enable Interrupts
    Config Date = Dmy , Separator = /

    Do
    If Flaga1 = 1 Then
    Flaga1 = 0

    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)
    '--------konwersja temp dla wszystkich dsow
    1wreset
    1wwrite &HCC
    1wwrite &H44
    Wait 1

    I1 = I1 * 10
    I1 = I1 / 16
    If I1 > 0 Then Cls                                          'korekta przesuniecia znaku st C przy przej?ciu z temp ujemnej na dodatni?
    Ss1 = Str(i1)
    Ss1 = Format(ss1 , " 0.0")

    I2 = I2 * 10
    I2 = I2 / 16
    If I2 > 0 Then Cls
    Ss2 = Str(i2)
    Ss2 = Format(ss2 , " 0.0")
    Cls
    Locate 1 , 1
    Lcd Time$ ; "    ";
    If Pinb.2 = 0 Then Lcd "Rcvr" Else Lcd "    "
    Locate 2 , 1
    Lcd Date$
    Locate 2 , 17                                               'Pozycja wy?wietlania nazwy i temperatury (1.1 -> 1 linia 1 kolumna, 2.10 -> 2 linia 10 kolumna itd)
    Lcd "ZEW:" ;
    Locate 2 , 23
    Lcd Ss1 ; Chr(0) ;
    Locate 1 , 17
    Lcd "WEW:" ;
    Locate 1 , 23
    Lcd Ss2 ; Chr(0) ;
    Locate 2 , 1
    Lcd Date$
    End If
    ' klawisz 1
    ' klawisz 2
    ' klawisz 3
    Loop
    Sectic:
       Set Flaga1
       Return

       End

    Nie pozbyłem się jeszcze uciążliwego mrugnięcia co sekundę - wiem ,że to przez komendę CLS, ale jej nie mogę się pozbyć - czy można coś z tym zrobić ?
    Może da się zmodyfikować czas resetu wyświetlacza, lub niech zmienia tylko te wartości które uległy zmianie.
    Termometr momentami się nie wyrabia i na 1s pokazuje jakąś dziwną temperaturę .
    Jak podzielić godzinę i datę na pojedyńcze wartości do edytowania za pomocą klawiszy Mode ,Up i Down i warunków IF - może ktoś ma pomysł. Jak to jest z zapamiętaniem przez procesor tej modyfikacji, żeby nie było tak ,że zwiększe np. godzine o 1 za pomocą klawisza - a zegarek w pamięci będzie miał o 1 mniej i zwiększona godzina będzie na ekranie przez 2 godziny (mam nadzieje ,że ktoś zrozumiał o co mi chodzi ) .
    Pozdrawiam wszystkich.
    P.S. Cała robota posuwa się etapami , później będę chciał dodać to podświetlenie , i myśle jeszcze o zew kwarcu ew. innym generatorze czasu ,żeby zegarek nie wariował przy braku synchronizacji z dcf i nie skakał nagle o parę godzin ,dni czy lat jak teraz.
  • Poziom 14  
    CLS służy do czyszczenia całego LCD - metoda prosta i skuteczna, ale nie najlepsza. Lepiej jest sformatować wyświetlany teks, aby miał stałą długość i "podmieniać" to, co się zmieniło ( użyć rozsądnie Locate).
    Spróbuj usunąć to CLS z pętli DO...LOOP, powinno być ok ( choć nie wiem, jak się zachowa wyświetlanie temperatury