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

atmega16 + 2xDS1820, kłopot z temperaturami ujemnymi.

dawid512 19 Gru 2007 11:02 1958 12
REKLAMA
  • #1 4603309
    dawid512
    Poziom 32  
    Posty: 1439
    Pomógł: 229
    Ocena: 6
    Witam wszystkich forumowiczow. Mam problem z termometrem dwu punktowym na DS1820. Problem polega na tym ze jesli temp jest dodatnia to wszystko jest ok ale problem mam z ujemnymi. Rozdzielczosc jest do 0.1 stopnia. Jezeli temperatura spadnie ponizej zera to jej wartosc wynosi 0.1 czyli -1 stopien. Wydzielilem z 0.1 jedynke i jest Ok ale jezeli temp wynosi +0.1 to wyskakuje mi -1 stopien:(. Jak sie z tym uporac? Ponizej program.

    
    $regfile = "m16def.dat"
    $crystal = 8000000
    
    Config Lcd = 16 * 2
    Config Lcdpin = Pin , Db4 = Pb.4 , Db5 = Pb.5 , Db6 = Pb.6 , Db7 = Pb.7 , E = Pb.3 , Rs = Pb.2
    Config 1wire = Portb.0
    
    Dim Iodczyt(9) As Byte
    Dim It1 As Single
    Dim It2 As Single
    Dim It3 As Single
    Dim Igotowa As String * 4
    Dim Itemp As Integer
    Dim Itemperatura As Single
    
    Dim Odczyt(9) As Byte
    Dim T1 As Single
    Dim T2 As Single
    Dim T3 As Single
    Dim Gotowa As String * 4
    Dim Temp As Integer
    Dim Temperatura As Single
    Dim Ujemna As Byte
    Dim Cyfra As String * 1
    Dim Ujemna1 As Byte
    Dim Cyfra1 As String * 2
    
    
    Dim Dsid1(8) As Byte
    Dim Dsid2(8) As Byte
    
    Dsid1(1) = 1wsearchfirst()
    Dsid1(1) = 1wsearchnext()
    
    Do
    Cls
    
    
    1wreset
       1wwrite &H44
       1wverify Dsid1(1)                                        'wysyłamy adres pierwszego czujnika
       1wwrite &HBE
       Waitms 750
       Iodczyt(1) = 1wread(9)
    
      1wreset
       1wwrite &H44
       1wverify Dsid2(1)                                        'wysyłamy adres drugiego czujnika
       1wwrite &HBE
       Waitms 750
       Odczyt(1) = 1wread(9)
    
    
        1wreset
        1wwrite &HCC
          1wwrite &H44
    '---------------------------------
    
    
    
    It3 = It2
    Itemp = Makeint(iodczyt(1) , Iodczyt(2))
    Itemperatura = Itemp / 2
    It1 = Iodczyt(8) - Iodczyt(7)
    It1 = It1 / Iodczyt(8)
    Itemperatura = Itemperatura - 0.25
    It2 = Itemperatura + It1
    
    Igotowa = Fusing(it2 , "##.#")
    
    
    Cyfra1 = Mid(igotowa , 1 , 2)
    Ujemna1 = Val(cyfra1)
    
    If Ujemna1 < 10 Then
    Cyfra = Mid(igotowa , 3 , 1)
    Ujemna = Val(cyfra)
    End If
    
    
    T3 = T2
    Temp = Makeint(odczyt(1) , Odczyt(2))
    Temperatura = Temp / 2
    T1 = Odczyt(8) - Odczyt(7)
    T1 = T1 / Odczyt(8)
    Temperatura = Temperatura - 0.25
    T2 = Temperatura + T1
    
    Gotowa = Fusing(t2 , "###.#")
    
    
    Lcd Igotowa
    Lowerline
    Lcd Gotowa
    
    
    If Ujemna1 = 0 Then
    Cls
    Locate 1 , 1
    Lcd "Zew. -" ; Ujemna
    Locate 2 , 1
    Lcd "Dom" ; Gotowa
    End If
    
    Wait 1
    
    Loop
    End
    
  • REKLAMA
  • #2 4603479
    korrus666
    Poziom 40  
    Posty: 5219
    Pomógł: 584
    Ocena: 476
    Nie bardzo czaje Bascoma bo pisze w asemblerze ale coś mieszasz z tymi temperaturami. Temperatura jest zapisana w 2 bajtach z czego pierwszy to znak. czyli pierwszy bajt jak ma wartość 0xff to temperatura jest ujemna a jak ma wartość 0x00 to jest dodatnia i cała filozofia.
  • REKLAMA
  • #3 4603539
    dawid512
    Poziom 32  
    Posty: 1439
    Pomógł: 229
    Ocena: 6
    Wiem ze tak jest i z tym problemu nie ma bo wyskakuje - nawet jesli nic nie przerabiam ale gdy temp wynosi -1 to sie pokazuje -0.1 zamiast -1....
  • #4 4603596
    pokornom
    Poziom 12  
    Posty: 22
    Hej , strasznie komplikujesz sobie życie przy tym odczycie temperatury.

    zamiast pisać:

    Iodczyt(1) = 1wread(9)
    i potem robić z tego zmienna integer
    Itemp = Makeint(iodczyt(1) , Iodczyt(2))

    napisz tak jak niżej bedzie szybciej i prościej

    1wwrite &HBE
    Itemp = 1wread(2)
    w pierwszym bajcie 12 bit decyduje o znaku
    if Itemp.12=1 then
    tu obsługa czesci ujemnej
    else
    tu obsługa czesci dodatniej
    end if

    dla dodatniej to wiesz co zrobic a żeby mieć temp ujemną trzeba odjąc od 256 to co byc obliczył gdyby to była temp dodatnia
    czyli
    temperatura_ujemna=256-temperatura_obliczona

    i to cała filozofia

    Jakbyś miał jeszcze problemy to się odezwij

    Dodano po 5 [minuty]:

    A i jeszcze jedno zamiast dzielić przez 2
    Itemperatura = Itemp / 2

    lepiej zrobić

    Shift Itemp , Right , 2

    będzie szybciej działało i mniej miejsca zajmuje w pamięci procesora. Skutek ten sam bo dzielenie polega na przesunięciu bitów zmiennej o dwa miejsca w prawo.:D
  • #5 4605699
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    pokornom napisał:
    Hej , strasznie komplikujesz sobie życie przy tym odczycie temperatury.

    Natomiast Ty , zastanów się co piszesz :evil:
    pokornom napisał:
    ...w pierwszym bajcie 12 bit decyduje o znaku

    Jak to możliwe , skoro bajt składa sie z 8-bitów :?:
    Z tego co mi wiadomo , o znaku liczby zapisanej w kodzie uzupełnień do dwóch , decyduje najstarszy bit :!:
    pokornom napisał:

    A i jeszcze jedno zamiast dzielić przez 2
    Itemperatura = Itemp / 2

    lepiej zrobić

    Shift Itemp , Right , 2

    Tzn jak , zamiast podzielić przez 2 , lepiej jest podzielić przez 4 :?:
    O przesuwaniu liczbę "zakodowanych" jako U2 - już nie wspomnę :|

    Piotrek
  • #6 4605838
    dawid512
    Poziom 32  
    Posty: 1439
    Pomógł: 229
    Ocena: 6
    Witam.

    Czy ktos moglby mi podac konkretna odpowiedz? NAjlepiej zmienic moj kod wtedy bedzie wszystko jasne.

    Pozdrawiam
  • REKLAMA
  • #8 4606196
    dawid512
    Poziom 32  
    Posty: 1439
    Pomógł: 229
    Ocena: 6
    Sprawdzilem ten programik. Moze i dziala ale wszystko jest w byte a nie single takze bez przecinka i zastanawiam sie po co az tyle danych w data?

    Pozdrawiam
  • REKLAMA
  • #9 4606232
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    dawid512 napisał:
    Sprawdzilem ten programik. Moze i dziala ale wszystko jest w byte a nie single takze bez przecinka i zastanawiam sie po co az tyle danych w data?

    Pozdrawiam

    No to jak już wyliczysz bez przecinka , to dodaj 1 linijkę kodu i będziesz miał single z przecinkiem.It2 = T/10.Te dane , to do obliczania sumy kontrolnej CRC.Skoro CRC jest dla Ciebie zbędne , to pomiń(usuń z kodu) zbędne rzeczy.Zresztą nie musisz korzystać z całego kodu , tylko "wytnij" sobie te kilka linijek , gdzie jest obliczana temperatura.

    Piotrek
  • #10 4606888
    pokornom
    Poziom 12  
    Posty: 22
    Znalazł się znawca od przesuwania liczb i bitów !
    Zrobiłem juz wiele sterowników używając nie jednego, dwóch a nawet więcej liczby ds'ów i zawsze działa bezbłęnie, nie tylko w BASCOMIE. A Ty Piotrusiu trochę pokory. Co za problem z przesuwaniem liczb zakodowanych w U2 ? Nie rozumiem . Z podziałem przez 2 i shiftem to zwyczajna literówka oczywiści powinno być
    shift T, right, 1 zamiast dzielenia przez 2. Każdemu może się przytrafić, nie miałem wczoraj za bardzo czasu i szybko pisałem.
    A jak bys znał DS18B20 to bys wiedział, że temperatura zakodowana jest tylko w dwóch bajtach i traktowane są one razem stąd 12 bit.
    -po pierwsze po co czytać aż 9 bajtów z układu jak sie potem z nich nie korzysta ?:?:
    ich znaczenie jest takie
    - temperatura LSB
    - temperatura MSB
    - th rejestr ulb bajt usera
    - tl rejestr lub bajt usera
    - rejestr koniguracji
    - zarezerwowane
    - zarezerwowane
    - zarezerwowane
    - CRC
    program używa tylko temperatury nie sprawdza CRC to po co to ciągnąc z układu, zamiast pobierać 4 bajty pobierasz 18 :!: ponad 4 razy dłuzszy czas na to potrzeba , po co :?:
    Wystarczy jak weźmiesz tylko dwa bajty i załadujesz do zmiennej integer
    T = 1wread(2)
    w zmiennej T sa wszystkie dane potrzebne do odczytania temperatury.
    Temperatura jest zakodowana na dwóch bajtach.

    - po drugie organizacja tych bajtów jest taka
    msb SSSSTTTT
    lsb TTTTTTTT

    gdzie S to bity mówiące o znaku , czyli wymądrzający się pan Piotr sie myli, ze znak jest zakodowany w najstarszym bicie, tylko aż na czterech najstarszych bitach bajtu msb. Natomiast temperatura zakodowana jest na 12 bitach, z czego 8 ma informację o stopniach a 4 o ułamkach stopnia,
    dodatkowo jak bity S sa równe 1 oznacza to temperature ujemna zakodowaną z dopełnieniem do 2. Co oznacza tylko tyle, że aby wiedziec jaka jest temp ujemna trzeba ja uzyskać odejmujac od 256 to co jest zapisane na bitach T. Proste ?
    Więc skoro ułamek jest zapisany na 4 bitach to max rozdzielczosc wynosi 0,0625 stopnia. :idea::D
    Tu możesz poczytac dokumentację http://www.solidchip.eu/download/DS18B20.pdf

    No dobra tyle teorii. Teraz praktyka
    t- zmienna integer

    T = 1wread(2)
    if T.12=0 then
    Shift T , Right , 4
    else
    T=&B111100000000 Or T
    Shift T , Right , 4
    T=256-T
    end if

    To najprostrzy sposób aby odczytać temperaturę bez częsci ulamkowej. zmienna T bedzie zawierała wartośc temperatury w stopniach.

    Jak chcesz ułamki bedzie trochę więcej kodu

    t- zmienna integer
    tu - zmienna byte

    T = 1wread(2)
    B=low(T)
    shift B, Left, 4
    shift B, Right,4
    if T.12=0 then
    Shift T , Right , 4
    else
    T=&B111100000000 Or T
    Shift T , Right , 4
    T=256-T
    B=16-B
    end if

    w ten sposób w zmiennej B masz liczbe odpowiadajaca ułamkowi jak to teraz wykorzystasz zależy od tego po co Ci ten ułamek. Jak chcesz dokładnie wiedzieć ile wynosi to pomnóż to co jest w B przez 0.0625 i bedziesz miał czesc ułamkowa stopnia.:D


    czyli jak dodasz
    s - zmienna single
    i zrobisz tak
    S=B*0,0625
    S=S+T
    To w S masz temperaturę (ujemna albo dadatnią) wraz z czescia ułamkową


    Jak chcesz wyśle Ci cały tekst programu , ale myslę ze juz sobie poradzisz.

    A i jak używasz więcej niż jednej kostki ds to musisz wysłac jeszcze
    1wwrite &H55 przed zaadresowaniem kostki.


    ps
    przepraszam jak są jakies literówki
  • #11 4607310
    dawid512
    Poziom 32  
    Posty: 1439
    Pomógł: 229
    Ocena: 6
    Bardzo fajny opis :) tylko czy bedzie dzialal na DS1820? Bo widze z ty opisujesz DS18B20...

    Pozdrawiam
  • #12 4609071
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    pokornom napisał:

    Zrobiłem juz wiele sterowników używając nie jednego, dwóch a nawet więcej liczby ds'ów i zawsze działa bezbłęnie, nie tylko w BASCOMIE. A Ty Piotrusiu trochę pokory.

    Cóż, wierzę Ci na słowo.
    pokornom napisał:

    Co za problem z przesuwaniem liczb zakodowanych w U2 ? Nie rozumiem

    No właśnie :| Gdybyś rozumiał , to zapewne 1-sze zdanie z Twojego poprzedniego postu , nie wyglądało by tak ...
    pokornom napisał:

    Znalazł się znawca od przesuwania liczb i bitów !

    ... jak wyglądało ;)

    pokornom napisał:

    A jak bys znał DS18B20 to bys wiedział, że temperatura zakodowana jest tylko w dwóch bajtach i traktowane są one razem stąd 12 bit.

    Ale zapominasz , że to forum czytają nie tylko fachowcy jak Ty i mogą zrozumieć to dosłownie.
    Poza tym , mówimy teraz o DS1820 , rozdzielczość 0.1C , więc trzeba odczytać przynajmniej 8 bajtów scratchpada.

    Piotruś
  • #13 4609713
    pokornom
    Poziom 12  
    Posty: 22
    No to rzeczywiście w ds1820 jest troche inna organizacja bitów. Temperatura zapisana jest na dwóch pierwszych bajtach. Przy czym msb jest w calosci przeznaczony na znak. Czyli jak wszystkie bity są równe 1 to jest temp ujemna a jak 0 to dodatnia. Rozdzielczość teperatury wynosi 0.5 stopnia, przez pewne obliczenia można dostać rozdzielczosc 0.1 stopnia ale to raczej taka umowna rozdzielczość. Ja bym proponował zastosowac ds18b20 z tego powodu że ds1820 nie jest już produkowany i tylko sprzedają jakies stare zapasy magazynowe. W razie awarii będzie trudno go dostać i trzeba będzie poprawiać program.

    No ale jak chcesz to uzyj ds1820. Wtedy rzeczywiście trzeba użyć az 8 bajtów aby zwiekszyć rozdzielczość, a jak ze sprawdzeniem CRC to 9.

Podsumowanie tematu

✨ Dyskusja dotyczy problemu z odczytem temperatur ujemnych z czujników DS1820 podłączonych do mikrokontrolera Atmega16. Autor zgłasza, że przy temperaturach dodatnich odczyt jest poprawny, natomiast przy ujemnych pojawia się błąd – np. dla -1°C wyświetla się -0.1°C. Problem wynika z nieprawidłowej interpretacji danych temperatury zapisanych w dwóch bajtach, gdzie pierwszy bajt zawiera znak temperatury. W DS1820 temperatura jest kodowana na dwóch bajtach, a rozdzielczość nominalna wynosi 0.5°C, choć można uzyskać rozdzielczość 0.1°C przez odpowiednie obliczenia i odczyt co najmniej 8 bajtów z pamięci scratchpad. Wskazano, że znak temperatury w kodzie uzupełnień do dwóch jest określany przez najstarszy bit MSB. Zalecane jest stosowanie przesunięć bitowych zamiast dzielenia, co przyspiesza działanie i zmniejsza zużycie pamięci. Zwrócono uwagę, że DS1820 jest już wycofywany z produkcji i lepszym wyborem może być DS18B20, który ma podobny sposób kodowania temperatury, ale jest bardziej dostępny i oferuje lepszą rozdzielczość. Wskazano również, że odczyt CRC jest istotny dla poprawności danych, choć w prostych aplikacjach można go pominąć. Podsumowując, problem z ujemnymi temperaturami wynika z błędnej interpretacji danych i nieprawidłowego przetwarzania bitów, a rozwiązaniem jest poprawne rozkodowanie wartości z uwzględnieniem kodu uzupełnień do dwóch oraz ewentualna zmiana czujnika na DS18B20.
REKLAMA