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.

[Attiny2313]+DS18B20[Bascom] Termometr i ujemna temperatura.

18 Gru 2010 17:11 5845 13
  • Poziom 21  
    Witam.
    Składam sobie zegar z termometrem na Attiny2313 i DS18B20 lecz mam problem z ujemną temperaturą. Do odczytu temperatury używam programu kolegi "Elektrooonik" ponieważ zajmuje najmniej kodu co jest tu dla mnie ważne i z 1-Wire styczność mam pierwszy raz więc wpierw wolę mieć jakiś przykład.
    Program Oryginalny do pomiaru temperatury wygląda tak:

    Code:
    Config Portb = Output
    
    Config Portd = Output
    Portb = 255
    Portd = 127
    Dim Zmienna As Byte
    Dim Liczba As Byte
    Dim Jednosci As Byte
    Dim Dziesiatki As Byte
    Dim Temp As Byte
    Dim 1cyfra As Byte
    Dim 2cyfra As Byte
    Dim A As Byte
    Dim Odczyt(2) As Byte
    Dim T As Integer
    Portd.0 = 1
    Portd.1 = 0

    Config 1wire = Portd.0
    Liczba = 77

    Do
       1wreset : 1wwrite &HCC : 1wwrite &HBE                    'polecenie odczytu DS18x20
       Odczyt(1) = 1wread(2)                                    'odczytaj dwa pierwsze bajty - temperaturę
       T = Odczyt(2)                                            '          starszy bajt temperatury
       Shift T , Left , 8                                       'przesuń w lewo o 8 miejsc
       T = T + Odczyt(1)                                        'w zmiennej Integer jest dziwna "ułamkowa" wartość
       Shift T , Right , 4                                      'zamiast dzielić przez 16 przesuń w prawo
     '   Shift T , Right , 1       'dla kostek DS18S20, DS1820 przesuń o 1 bit



         1wreset                                                '   dopiero teraz daj polecenie konwersji:
         1wwrite &HCC                                           'polecenie SKIP ROM, bo pojedyncza kostka
         1wwrite &H44                                           '   dokonaj konwersji - zmierz temperaturę
                                                     'po cyklu pracy poczekaj
                                                     Liczba = T
                                                     Gosub Wyswietlanie
    Loop

    Wyswietlanie:
    Portd.1 = 1
    Gosub Oblicz
    For A = 0 To 125
    Dziesiatki:
    If Dziesiatki = 0 Then
    Portd.6 = 1
    Goto Jednosci
    End If
    Portb = 1cyfra
    Portd.6 = 0
    Waitms 3
    Jednosci:
    Portb = 2cyfra
    Portd.6 = 1
    Portb.0 = 0
    Waitms 3
    Next A
    A = 0
    Portd.1 = 0
    Return


    Oblicz:
    Temp = Makebcd(liczba)
    Jednosci = Temp And &B00001111
    Shift Temp , Right , 4
    Dziesiatki = Temp

    1cyfra = Lookup(dziesiatki , Tabela)
    2cyfra = Lookup(jednosci , Tabela)

    'Dziesiatki = Liczba / 10
    'Jednosci = Dziesiatki * 10
    'Jednosci = Liczba - jednosci

    Return


    End
    Tabela:
    Data 3 , 111 , 133 , 37 , 105 , 49 , 17 , 99 , 1 , 33

    Ten program odczytuje od 0 do 99st C a ja potrzebuję również ujemnych temperatur przy czym kod musi zajmować jak najmniej miejsca.
    Próbowałem już kilkadziesiąt różnych sposobów ale nic to nie dało.
    Obsługa wyświetlacza musi zostać taka gdyż oba timery mam zajęte.
    Proszę o szybką pomoc i z góry dziękuję.
  • Moderator na urlopie...
    Code:

    $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 1wire = Portd.5                                      'deklaracja portu na którym będą podpięte DS18b20

    Dim I1 As Integer , Ss As String * 6
    Dim I2 As Integer
    Dim I3 As Integer
    Dim I4 As Integer

    Dim Dsid1(8) As Byte
    Dim Dsid2(8) As Byte
    Dim Dsid3(8) As Byte
    Dim Dsid4(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
    Deflcdchar 1 , 4 , 21 , 14 , 27 , 14 , 21 , 4 , 32          'znak zewnętrzna
    Deflcdchar 2 , 16 , 0 , 23 , 21 , 21 , 21 , 21 , 32         'znak wewnętrzna

    Cursor Off                                                  'Wyłącza kursor
    Cls                                                         'Funkcja CLS czyści ekran
    Lcd "   Termometr    " ;                                    'ekran startowy (pojawia się tylko podczas włączania urządzenia)
    Lowerline
    Lcd "      2007      "
    Wait 5
    Cls
    W = 1wirecount()
    Lcd "Ilosc czujnikow:"                                      'Informuje ile czujników jest podpiętych do układu (pojawia się tylko podczas włączania urządzenia)
    Waitms 500
    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()                                   'Znajdź kolejny czujnik podpięty do portu
    Dsid3(1) = 1wsearchnext()                                   'Znajdź kolejny czujnik podpięty do portu
    Dsid4(1) = 1wsearchnext()

    '*******************Odczyt numerów ID czujników temperatury*********************

    If Dsid1(8) = Crc8(dsid1(1) , 7) Then                       'ta opcja pojawia się tylko przy włączaniu urządzenia
     Locate 1 , 1
     Lcd "CRC OK Termo1 ID"
     Wait 1
     Locate 1 , 1
     For B = 1 To 8
     Lcd Hex(dsid1(b))
     Next
    End If
    Wait 2

    If Dsid2(8) = Crc8(dsid2(1) , 7) Then
     Locate 2 , 1
     Lcd "CRC OK Termo2 ID"
     Wait 1
     Locate 2 , 1
     For B = 1 To 8
     Lcd Hex(dsid2(b))
     Next
    End If
    Wait 2

    If Dsid3(8) = Crc8(dsid3(1) , 7) Then
     Locate 1 , 1
     Lcd "CRC OK Termo3 ID"
     Wait 1
     Locate 1 , 1
     For B = 1 To 8
     Lcd Hex(dsid3(b))
     Next
    End If
    Wait 2

    If Dsid4(8) = Crc8(dsid4(1) , 7) Then
     Locate 2 , 1
     Lcd "CRC OK Termo4 ID"
     Wait 1
     Locate 2 , 1
     For B = 1 To 8
     Lcd Hex(dsid4(b))
     Next
    End If
    Wait 2
    Cls

    '*******************koniec odczytu ID czujników temperatury*********************

    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 &H55
       1wverify Dsid3(1)                                        'wysylam adres trzeciego czujnika
       1wwrite &HBE
       I3 = 1wread(2)
    '---------------------------------
       1wreset
       1wwrite &H55
       1wverify Dsid4(1)                                        'wysylam adres czwartego czujnika
       1wwrite &HBE
       I4 = 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                                           '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 Chr(1) ; Ss ; Chr(0) ;
       Else
       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 Chr(1) ; Ss ; Chr(0) ;
       End If

       I2 = I2 * 10
       I2 = I2 / 16
       If I2 > 0 Then
       Ss = Str(i2)
       Ss = Format(ss , "  0.0")
       Locate 1 , 10
       Lcd Chr(2) ; Ss ; Chr(0) ;
       Else
       Ss = Str(i2)
       Ss = Format(ss , " 0.0")
       Locate 1 , 10
       Lcd Chr(2) ; Ss ; Chr(0)
       End If

       I3 = I3 * 10
       I3 = I3 / 16
       If I3 > 0 Then
       Ss = Str(i3)
       Ss = Format(ss , "  0.0")
       Locate 2 , 1
       Lcd Chr(1) ; Ss ; Chr(0) ;
       Else
       Ss = Str(i3)
       Ss = Format(ss , " 0.0")
       Locate 2 , 1
       Lcd Chr(1) ; Ss ; Chr(0) ;
       End If

       I4 = I4 * 10
       I4 = I4 / 16
       If I4 > 0 Then
       Ss = Str(i4)
       Ss = Format(ss , "  0.0")
       Locate 2 , 10
       Lcd Chr(2) ; Ss ; Chr(0) ;
       Else
       Ss = Str(i4)
       Ss = Format(ss , " 0.0")
       Locate 2 , 10
       Lcd Chr(2) ; Ss ; Chr(0) ;
       End If

       Loop

    tu masz obsługę czterech czujników z temperaturami ujemnymi, przerób sobie według własnych potrzeb ;-)
    albo znalazłem jeszcze to:
    Code:

    $regfile = "m1280def.dat"
    $crystal = 11059200
    $lib "glcd.lib"

    $hwstack = 100
    $swstack = 120
    $framesize = 100


    Config Graphlcd = 240 * 64 , Dataport = Porte , Controlport = Porth , Ce = 0 , Cd = 1 , Wr = 2 , Rd = 3 , Reset = 4 , Fs = 5 , Mode = 6
    Cursor Off Noblink
    Cls

    Config Porta = Output                                       'DATA 0-7 (P1.0-LPT2;P1.1-LPT3;...;P1.7-LPT9)
    Config Pinj.0 = Output                                      'STROBE (P2.0-LPT1)
    Config Pinj.1 = Input

    Declare Sub Sendbyte(byval D As Byte)
    Declare Sub Print_buffer()
    Declare Sub Print_text(byval S As String)

    Set Portj.0
    Call Sendbyte(27)
    Call Sendbyte(64)
    Wait 1

    Dim Lsb As Byte
    Dim Msb As Byte
    Dim Tempa As Single
    Dim Tekst1 As String * 10
    Dim X As Byte , Y As Byte
    Dim C As Byte , Y2 As Byte , M As Byte , X31 As Byte , X32 As Byte
    Dim Wykres(80) As Single
    X = 0
    Y = 64
    C = 0




    'Pin do czujnika DS18B20
    Config 1wire = Pind.4
    Dim Ds(8) As Byte

    1wreset
    1wwrite &H33
    Ds(1) = 1wread(8)

    While C < 81

    1wreset
    1wwrite &HCC
    1wwrite &H44

    Waitms 250
    Locate 1 , 18
    Lcd "*"
    Waitms 250
    Locate 1 , 18
    Lcd " "

    1wreset

    1wwrite &HCC
    1wwrite &HBE

      Lsb = 1wread():
      Msb = 1wread():

      Tempa = Msb * 256
      Tempa = Tempa + Lsb
      Tempa = Tempa / 16
      If Tempa > 128 Then

    Tempa = 4096 - Tempa   

    'Tempa = 4095.9375 - Tempa
       M = 1
      Else
       M = 0
      End If
      Tekst1 = Fusing(tempa , "#.##")
      If Tempa < 10 Then Tekst1 = " " + Tekst1
      Locate 1 , 1
      If M = 1 Then
      Lcd "T =-" ; Tekst1 ; " st. C "
      Else
      Lcd "T =+" ; Tekst1 ; " st. C "
      End If
      Wykres(c) = Tempa
      Tempa = Tempa / 50
      Tempa = Tempa * 64
      Y2 = Tempa
      Y2 = 64 - Y2
      X31 = 3 * X
      X32 = X31 + 3
      Line(x31 , Y) -(x32 , Y2) , 255
      C = C + 1
      X = C
      Y = Y2
    Wend

    Locate 1 , 18
    Lcd "|| Printing..."
    '(
    For Lsb = 0 To 60
    For Msb = 0 To 79
    Tempa = 60 - Lsb
    Tempa = Tempa / 2
    If Tempa < Wykres(msb) Then
    Call Sendbyte(219)
    Else
    Call Sendbyte(32)
    End If
    Next Msb
    Call Sendbyte(10)
    Next Lsb
    'Call Sendbyte(12)
    ')
    End                                                         'end program

    Sub Sendbyte(byval D As Byte)

    Porta = D
    Reset Portj.0
    Waitms 1
    Set Portj.0
    Do
    If Pinj.1 = 0 Then Exit Do
    Loop
    End Sub

    Sub Print_buffer()
    Call Sendbyte(32)
    Call Sendbyte(8)
    End Sub

    Sub Print_text(byval S As String)
    Local Carcount As Byte , Ssize As Byte , Temp As Byte , Tempstring As String * 1
    Ssize = Len(s) - 1
    For Carcount = 0 To Ssize
    Temp = Carcount + 1
    Tempstring = Mid(s , Temp , 1)
    Temp = Asc(tempstring)
    Call Sendbyte(temp)
    Next Carcount
    Call Print_buffer()
    End Sub
  • Poziom 21  
    Jakoś dalej nie umiem tego zrozumieć, jeśli mógłby ktoś wstawić ten kawałek za to odpowiedzialny do tamtego kodu. Próbuję już długi czas i nic.
  • Poziom 43  
    A w ogóle dysponujesz na wyświetlaczu znakiem "-"?
  • Poziom 21  
    Znak minus jest tu na razie nie istotny. Jak mam temperaturę ujemną to wyświetla mi 95 st.C . Nie wiem już jak z tym dać se radę.
  • Poziom 43  
    Piszesz że próbujesz już przez długi czas. Pokaż jak próbowałeś.
  • Poziom 21  
    Chwilowo straciłem ten kod postaram się go znaleźć ale opierałem się na projektach z internetu.
  • Pomocny post
    Poziom 43  
    Manio95 napisał:
    Chwilowo straciłem ten kod postaram się go znaleźć ale opierałem się na projektach z internetu.

    No bez jaj. Na 99% nic nie masz tylko czekasz na gotowca. Ale dobra, zlituję się na święta :D
    Pomijając całą beznadziejność kodu do multipleksowania wyświetlacza, takie coś powinno działać:
    Code:
    $regfile = "ATTiny2313.dat"
    
    $crystal = 8000000

    Dim Jednosci As Byte
    Dim Dziesiatki As Byte
    Dim 1cyfra As Byte
    Dim 2cyfra As Byte
    Dim T As Integer
    Dim A As Byte

    Config Portb = Output
    Config Portd = Output
    Portb = 255
    Portd = 127

    Portd.0 = 1
    Portd.1 = 0

    Config 1wire = Portd.0

    Do
       1wreset
       1wwrite &HCC
       1wwrite &HBE                    'polecenie odczytu DS18x20
       T = 1wread(2)                                    'odczytaj dwa pierwsze bajty - temperaturę



       1wreset                                                '   dopiero teraz daj polecenie konwersji:
       1wwrite &HCC                                           'polecenie SKIP ROM, bo pojedyncza kostka
       1wwrite &H44                                           '   dokonaj konwersji - zmierz temperaturę
                                                     'po cyklu pracy poczekaj

       Gosub Wyswietlanie
    Loop

    Wyswietlanie:
    Portd.1 = 1
    Gosub Oblicz

    For A = 0 To 125
    Dziesiatki:
    If Dziesiatki = 0 Then
    Portd.6 = 1
    Goto Jednosci
    End If
    Portb = 1cyfra
    Portd.6 = 0
    Waitms 3
    Jednosci:
    Portb = 2cyfra
    Portd.6 = 1
    Portb.0 = 0
    Waitms 3
    Next A
    A = 0
    Portd.1 = 0
    Return


    Oblicz:
      'T = T * 10
      T = T / 16

      If T < 0 Then
          T = -T

          'Wlacz_znak_minus
      Else
          'Wylacz_znak_minus
      End If

      Dziesiatki = T / 10
      Jednosci = T Mod 10

      1cyfra = Lookup(dziesiatki , Tabela )
      2cyfra = Lookup(jednosci , Tabela)
    Return


    End
    Tabela:
    Data 3 , 111 , 133 , 37 , 105 , 49 , 17 , 99 , 1 , 33
  • Poziom 42  
    Ludzie co wy robicie? wchodzi ktoś kto nie ma zielonego jeszcze pojęcia o podstawach programowania a wy go zasypujecie i to ponoć z litości i z chęci pomocy przedświątecznej - coraz dłuższymi kodami źródłowymi.

    I to pomimo, że autor sam pisze, że nic z tego nie rozumie. Czy do was nie dociera, że pomóc komuś początkującemu to nie podać gotowy kod bo jak ma go zrozumieć skoro nie zna podstaw???

    O wiele lepiej dopytać się co autor już sam zrobił, postarać się żeby spróbował podzielić swój problem na jakieś mniejsze etapy i zadał jakieś bardziej szczegółowe pytania.

    W przeciwnym wypadku nadal będzie przekonany że programowanie mikrokontrolerów polega tylko i wyłącznie na próbach mniej lub bardziej nieudolnego zlepiania różnych fragmentów kodu i tworzenie "małego frankensteina" - licząc na to że może ożyje. Szok ;)

    atom1477 --> no twoja litość dzisiaj i tutaj to mnie rozłożyła ;)

    --------------------------------------------

    ale dobra panie autor, toż w swoim pierwszym pokazanym kodzie łamiesz wszystkie zasady. Nie dajesz nawet odetchnąć czujnikom aby zdążyły dokonać pomiaru a już odczytujesz.

    temperatura 95st nie oznacza, że jest ujemna tylko że coś źle (bardzo) źle robisz. Proponuję ci rozłożyć całość na mniejsze kroczki. Weź najprostszy przykład z Helpa Bascoma i przećwicz go na wszystkie sposoby żeby zawsze pokazywał dobrze temperaturę. Spróbuj poczytać troszkę o tych czujnikach, co to znaczy że potrzebują czas i jaki na konwersję. To na prawdę przyjemny proces uczenia ..... a przy okazji po stosunkowo krótkim czasie zobaczysz że przyniesie pierwsze efekty w postaci samodzielnego już programu i z pełnym zrozumieniem tego co się robi.

    Powodzenia.
  • Poziom 43  
    -->mirekk36: a zadałeś sobie trud sprawdzenia czy aby mój kod jest na pewno dłuższy od kodu autora tematu? Czy tylko spojrzałeś i już krytykujesz? :D
    Bo tak się składa że jest krótszy :D
    W dodatku jest chyba napisany najprościej jak się da. Więc myślę że mimo że to gotowiec, to da się coś z niego zrozumieć.
  • Poziom 42  
    atom1477 --> ja nie krytykuję kodu (tzn nie krytykowałem - nawet jeszcze nie spojrzałem na niego) ;) nie zaperzaj sie tak, toż widzę że krótszy.

    .....Ale powiedz mi gdzie masz w tym krótki kodzie oczekiwanie na konwersję, co najmniej 750ms ??? bo jakoś nie widzę.
  • Poziom 43  
    mirekk36 napisał:
    atom1477 --> ja nie krytykuję kodu (tzn nie krytykowałem - nawet jeszcze nie spojrzałem na niego) ;) nie zaperzaj sie tak, toż widzę że krótszy.

    .....Ale powiedz mi gdzie masz w tym krótki kodzie oczekiwanie na konwersję, co najmniej 750ms ??? bo jakoś nie widzę.

    Tym oczekiwaniem jest odświeżanie wyświetlacza (i napisałem że jest beznadziejne :D).
    Poprawiłem tylko to co sprawiało kłopot, czyli temperatury ujemne.
    Ale oczywiście też uważam że ten cały kod jest skrajnie błędny. Napisany na kolanie po prostu.
  • Poziom 42  
    atom1477 napisał:
    Tym oczekiwaniem jest odświeżanie wyświetlacza (i napisałem że jest beznadziejne :D).
    Poprawiłem tylko to co sprawiało kłopot, czyli temperatury ujemne.
    Ale oczywiście też uważam że ten cały kod jest skrajnie błędny. Napisany na kolanie po prostu.


    No więc widzisz, nie obrażaj się, ale jednak taka pomoc na kolanie też nic nie da komuś kto nic się jeszcze nie orientuje. Bo pomijam już to multipleksowanie i nie czepiam się - toż napisałeś że to tak na chybcika i niech będzie - choć tego to już mi się nawet nie chce analizować.

    Ale pobieżnie patrząc twoje odświeżanie używa opóźnienia Waitms 3 w pętli o 128 przebiegach. Co daje połowę może potrzebnego czasu konwersji dla ds18B20. Biorąc pod uwagę Bascom dorzućmy jeszcze ze 20% narzutu - to i tak dużo za mało. Efektem będą jeszcze większe dziwolągi (o ile multipleksowanie z kolana by zadziałało) jeśli chodzi o odczytywane wartości temperatury - w większości byłoby 85st C ;)

    Wychodzi więc tym bardziej na moje w tym co powiedziałem wcześniej.
  • Poziom 39  
    Manio95 napisał:
    ...Ten program odczytuje od 0 do 99st C a ja potrzebuję również ujemnych temperatur ...

    Przecież do tego wystarczą podstawy algebry.
    Manio95 napisał:
    Próbowałem już kilkadziesiąt różnych sposobów ale nic to nie dało.

    Sprawdzasz czy odczytana temperatura jest mniejsza od zera i jeśli jest,
    to zapamiętujesz to sobie w zmiennej lub "zapalasz" znak minus.
    Następnie wartość temperatury "przerabiasz" na dodatnią
    i dalej postępujesz jak z temp. dodatnią - dosłownie 2 linie kodu + 1 zmienna.

    Temat uważam za wyczerpany i zamykam.