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.

DS18B20 - złe obliczenia??

31 Sie 2005 14:33 3314 14
  • Poziom 21  
    witam,
    robię termometr z dwoma ds18b20 i mam problem, ponieważ nie mogę wykalibrować tych pomiarów aby uzyskać dokładność do 0,1. Oraz wyświetlić wartość np. 21,5 st C. Termometr pokazuje mi 215, szukałem na forum, ale nic konkretnego nie znalazłem.
    Przedstawiam mój kod:
    Code:
    'Declare Sub Init
    
    Declare Sub Convallt                                        ' Convert T on ALL sensors
    Declare Sub Odczyt_z_ds18b21
    Declare Function Decigrades(byval Sc(9) As Byte) As Integer

    'Temp variables
    Dim B As Byte
    Dim W As Word
    Dim Ds1 As Integer                                          'DECIgrades, I call it, cause I have no space for commas on the display....
    Dim Ds2 As Integer
    Dim Min1 As Integer
    Dim Min2 As Integer
    Dim Max1 As Integer
    Dim Max2 As Integer
    Dim Dsid1(8) As Byte                                        'Dallas ID 64 bits incl CRC
    Dim Dsid2(8) As Byte
    Dim Sc(9) As Byte
    Dim Temp1 As Byte
    Dim T1 As Integer
    Dim T2 As Integer
    Dim Dz As Byte
    Dim X As Integer
    Dim Tmp As Byte
    Cls

    W = 1wirecount()
    DsId1(1) = 1wsearchfirst()
    Do
      DsId2(1) = 1wsearchnext()
    Loop Until Err = 1

    Locate 1 , 1 : Lcd "Sprawdzenie czujnikow"
    'Sprawdzenie czujnika numer 1
    if dsid1(8) = crc8(DsId1(1), 7) then ' Control that the received CRC match the calculated
       Locate 3 , 1
       Lcd "CRC - czujnik 1 = OK"
    End If
    'Sprawdzenie czujnika numer 2
    if dsid2(8) = crc8(DsId2(1), 7) then
       Locate 4 , 1
       Lcd "CRC - czujnik 2 = OK"
    end if
    Wait 3
    cls


    ' Main loop
    Do
    Convallt                                                    ' "Convert ALL T on the 1w-bus"
    Call Odczyt_z_ds18b21
    Locate 1 , 1 : Lcd Ds1
    Locate 2 , 1 : Lcd Ds2
    Locate 3 , 1 : Lcd Temp1
    Loop


    Sub Odczyt_z_ds18b21
    Waitus 200 : waitus 200 :   waitus 200 :   waitus 200      'if you use 2-wire, could be reduced to 200us
    'czujnik 1
      1wverify DsId1(1)                 'Issues the "Match ROM "
      locate 1,1
      if err = 1 then
        Lcd "ERR "                                              'Err = 1 if something is wrong
      elseif err = 0 then              'lcd " Sensor found"
        1wwrite &HBE
        Sc(1) = 1wread(9)                'read bytes into array
        if sc(9) = crc8(sc(1),8) then
           Ds1 = Decigrades(sc(9))
        End If
      End If


    'czujnik 2
      1wverify DsId2(1)
      locate 2,1
      if err = 1 then
        Lcd "ERR "
      elseif err = 0 then                                        ' lcd " Sensor found     "
        1wwrite &HBE
        Sc(1) = 1wread(9)
        if sc(9) = crc8(sc(1),8) then
           Ds2 = Decigrades(sc(9))
          end if
      end if
    End Sub

    Sub ConvAllT
       1wreset                                                  ' reset the bus
       1wwrite &HCC                                             ' skip rom
       1wwrite &H44                                             ' Convert T
    End sub


    Function Decigrades(byval Sc(9) As Byte)
       Decigrades = 0
       Decigrades = Makeint(Sc(1) , Sc(2))
       Decigrades = Decigrades * 10
       Decigrades = Decigrades / 16
    End Function


    Jak już widać piszę w BASCOM.
    Pozdrawiam :)
    Moderowany przez Light-I:

    Poprawiono literówkę w temacie.

  • Poziom 15  
    august_a napisał:

    [code]
    Decigrades = Decigrades * 10


    Czy przypadkiem ta linia nie jest odpowiedzialna za 10krotnie wyzszy wynik ? hmm

    Sprawdz i usun ja :P
  • Poziom 21  
    Cytat:
    Code:
    Decigrades = Decigrades * 10


    Jest chyba ok.
    Chodzi mi o wynik po przecinku tak aby pokazywał mi np: 21,1 a nie 211
  • Poziom 15  
    august_a napisał:

    Chodzi mi o wynik po przecinku tak aby pokazywał mi np: 21,1 a nie 211


    A to równanie jest prawidłowe 21,1 * 10 = 211 ?
    Pomysl co bedzie jesli nie pomnożysz liczby......
  • Poziom 23  
    august_a napisał:

    Decigrades = Decigrades * 10


    Ta linia jest dobra. Mnożysz *10 ponieważ wykonujesz obliczenia na INTEGER i aby zaoszczędzić kodu i pamięci a nie na SINGLE.

    Aby zamiast, np. 211 wyswietlic 21,1 trzeba zastosować jakiś chytry myk.
    Można na wiele sposobów. Najlepszy jest chyba taki (w zmiennej T mamy 211 i chcemy wyświetlić na pozycji, np. 2,7):
    1. Ustawiamy kursor w pozycji o 1 dalszej niż ma być liczba (jeszcze przecinek) czyli 8.
    2. Wyswietlamy zmienną T (211).
    3. T=T/10 (spowoduje to podzielenie i obcięcie ułamka: T=21).
    4. Ustawiamy kursor w pozycji 2,7 i wyswietlamy T + znak przecinka.
    Code:
    Locate 2 , 8
    
    Lcd T
    Locate 2 , 7
    T = T / 10
    Lcd T ; ","


    Pozdrawiam, Konrad.
  • Poziom 28  
    Ja pisze też w Basicu lecz na PIC'i i robie to tak:

    1. Czytam wartość z czujnika
    2. Podstawiam pod zmienną FLOAT
    3. Zmienną mnoże przez 0.0625
    4. Wyświetlam z dokładnością do jednego miejsca po przecinku i chodzi dobrze.
  • Poziom 23  
    I tu też by dobrze chodziło, ale działania na zmiennych rzeczywistych (w Bascomie - Single) zajmują bardzo dużo miejsca a prawie zawsze można te obliczenia dokonać na zmiennych całkowitych (np. tak jak w tym przykładzie).
  • Poziom 16  
    Problem wygląda tak:
    -temperatura np. 21.5 stopni.
    -odczytany wynik = 344 (21.5/0,0625)
    w procedurze wykonujesz:
    -mnożysz 344 * 10 = 3440
    -dzielisz 3440 / 16 = 215 !!!!!
    Sam widzisz, że teraz tylko sposób wyświetlenia jest istotny, bo wynik twoich obliczeń to 215 a nie 21,5. Więc skorzystaj z pomysłu kolegi Konrada lub wymyśl coś innego.
  • Pomocny post
    Poziom 28  
    A może tak:

    Code:
    Dim Temp As Integer 
    
    Dim Disp As String * 5

    Temp = 366 'odczytana wartość temperatury
    Disp = Str(Temp)
    Disp = Format(Disp , "  0.0")
    Locate 1 , 1
    Lcd Disp


    Pozdrawiam...
  • Poziom 21  
    Cytat:
    Dim Temp As Integer
    Dim Disp As String * 5

    Temp = 366 'odczytana wartość temperatury
    Disp = Str(Temp)
    Disp = Format(Disp , " 0.0")
    Locate 1 , 1
    Lcd Disp


    Jest to dobry sposób, ale wynik wyświetla się w formacie: 36,636666, jak go wyświetlić za pomocą tej procedury aby wyświetlił 36,6 ?
  • Pomocny post
    Poziom 28  
    Jeśli testujesz wyżej przytoczony przykład w symulatorze BASCOM'a to dodaj na jego końcu pętlę DO-LOOP lub komendę END i będzie OK.

    Code:
    Dim Temp As Integer 
    
    Dim Disp As String * 5

    Temp = 366 'odczytana wartość temperatury
    Disp = Str(Temp)
    Disp = Format(Disp , "  0.0") ' dwie spacje (kasowanie zer nieznaczących) + 0.0
    Locate 1 , 1
    Lcd Disp
    Do
    Loop

    End


    Podany przykład nie stanowi kompletnego kodu (brak $regfile, $crystal, Config Lcd, itd.) a jedynie sposób rozwiązania problemu wyświetlania sformatowanych string'ów.
  • Poziom 17  
    BASCOM ma taką funkcję jak FUSING(), do formatowania tekstu. Popatrz do helpa. Jest tam to dokładnie opisane.
  • Poziom 32  
    fusing jest super tylko jak sie robi odczyt ds-a na ATMEGA 8 lub kosci z wiekszą iloscią pamieci ;)
  • Poziom 23  
    Zrób tak jak Ci napisałem. Kiedyś sprawdzałem chyba wszystkie możliwości i jest to sposób najszybszy, najmniej pamięciożerny i jednocześnie najmniej programożerczy.:) A jeśli z jakichś powodów tak nie możesz to napisz a pomyślimy.
    Pozdrawiam, Konrad.
  • Poziom 21  
    Ok, już zrobiłem przez
    Code:
    Dim Temp As Integer 
    
    Dim Disp As String * 5

    Temp = 366 'odczytana wartość temperatury
    Disp = Str(Temp)
    Disp = Format(Disp , "  0.0") ' dwie spacje (kasowanie zer nieznaczących) + 0.0
    Locate 1 , 1
    Lcd Disp
    Do
    Loop

    End

    i działa.
    Dzięki jeszcze raz dla wszystkich.