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

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

Manio95 18 Gru 2010 17:11 6403 13
  • #1 8884056
    Manio95
    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:

    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ę.
  • #2 8884102
    piotrva
    VIP Zasłużony dla elektroda
    
    $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:
    
    $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
    
  • #3 8884175
    Manio95
    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.
  • #4 8884260
    Konto nie istnieje
    Poziom 1  
  • #5 8884270
    Manio95
    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ę.
  • #6 8884304
    Konto nie istnieje
    Poziom 1  
  • #7 8884344
    Manio95
    Poziom 21  
    Chwilowo straciłem ten kod postaram się go znaleźć ale opierałem się na projektach z internetu.
  • Pomocny post
    #8 8884420
    Konto nie istnieje
    Poziom 1  
  • #9 8884816
    mirekk36
    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.
  • #10 8884996
    Konto nie istnieje
    Poziom 1  
  • #11 8885056
    mirekk36
    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ę.
  • #12 8885079
    Konto nie istnieje
    Poziom 1  
  • #13 8885166
    mirekk36
    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.
  • #14 8885275
    zumek
    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.
REKLAMA