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

[Bascom] Termoetr - dlaczego nie mogę podać własnej wartości

xamrex 30 Lis 2010 20:29 2496 17
REKLAMA
  • #1 8810223
    xamrex
    Poziom 28  
    Witam,
    Mam czujnik DS18B20
    i taki kod do niego:
    'Jednopunktowy termometr z czujnikiem DS18B20
    'www.portalnaukowy.edu.pl
    'Program na podstawie kursu z ksiażki "Mikrokontrolery dla Poczatkujacych" Pana Piotra Góreckiego
    
    $crystal = 4000000                  'deklaracja częstotliwosci pracy kwarcu
    
    $regfile "attiny2313.dat"               'model procesora dla którego jest ten program
    Deflcdchar 1 , 14 , 17 , 17 , 14 , 32 , 32 , 32 , 32        ' definicja znaki stopnia
    
    
    Config 1wire = Portd.5                                      ' konfiguracja portu PD.5 jako wescia magistrali 1-wire
    
    Dim Odczyt(2) As Byte , A As Byte , Licznik As Byte , T As Integer , T1 As Single , Napis As String * 5
    'Deklaracja wszystkich zmiennych potrzebnych do pracy programu
    
    Do
      1wreset                                                   'reset
      1wwrite &HCC                                              'jedna kostka, więc wykorzystujemy rozkaz SKIP ROM
      1wwrite &H44                                              'dokonaj konwersji
      Waitms 750                                                'przeczekaj czas konwersji
      1wreset                                                   'reset
      1wwrite &HCC                                              'rozkaz adresowy SKIP ROM
      1wwrite &HBE                                              'rozkaz funkcyjny - polecenie odczytu DS18x20
      Odczyt(1) = 1wread(2)                                     'odczytaj dwa pierwsze bajty
      T = Odczyt(2)                                             'przepisz starszy bajt do zmiennej typu Integer
      Shift T , Left , 8                                        'przesuń ten bajt w lewo na wyższe pozycje
      T = T + Odczyt(1)                                         'przepisz - dodaj młodszy bajt
    
      T1 = T * 0.0625                                               'wyraz w stopniach Celsjusza, wynik wpisz do zmiennej Single
    
    Napis = Fusing(t1 , "#.#")
      Cls : Cursor Off : Lcd "* Temperatura *"
      Lowerline
      Lcd "Wynik: " ; Napis ; " " ; Chr(1) ; "C"                'wyswietl wynik ze zmiennej Single
    Loop : End
    
    'Powodzenia


    Oczywiście wszystko w realu działa:)

    Chciałbym teraz za symulować ten układ.

    [Bascom] Termoetr - dlaczego nie mogę podać własnej wartości

    Ustalmy sobie na początek temperaturę np.10.125C
    czyli (0000 0000 1010 0010)Bin
    (162)DEC

    Robimy drobne poprawki w kodzie:
       $sim
    $regfile = "attiny2313.dat"
       $crystal = 1000000
      Config Lcd = 16 * 2
    
    
       Config Lcdpin = Pin , Db4 = Portb.0 , Db5 = Portb.1 , Db6 = Portb.2 , Db7 = Portb.3 , E = Portd.2 , Rs = Portd.0
    
    
       Deflcdchar 1 , 14 , 17 , 17 , 14 , 32 , 32 , 32 , 32     ' definicja znaki stopnia
    Config 1wire = Portd.5                                      ' konfiguracja portu PD.5 jako wescia magistrali 1-wire
    
    Dim Odczyt(2) As Byte , A As Byte , Licznik As Byte , T As Integer , T1 As Single , Napis As String * 5 , NowaTemp As Integer
    'Deklaracja wszystkich zmiennych potrzebnych do pracy programu
    
    Nowatemp = 401                                         ' !!!ZMIANA!!!
    Print Bin(nowatemp)                                         ' !!!ZMIANA !!!!printuje 0000 0001 1001 0001
    
    
    
    
    Do
    '  1wreset                                                   'reset
    '  1wwrite &HCC                                              'jedna kostka, więc wykorzystujemy rozkaz SKIP ROM
    '  1wwrite &H44                                              'dokonaj konwersji
    ' Waitms 750                                                 'przeczekaj czas konwersji
    '  1wreset                                                   'reset
    '  1wwrite &HCC                                              'rozkaz adresowy SKIP ROM
    '  1wwrite &HBE                                              'rozkaz funkcyjny - polecenie odczytu DS18x20
      Odczyt(1) = Nowatemp                                      '!!! ZMIANA !!!odczytaj dwa pierwsze bajty
      T = Odczyt(2)                                             'przepisz starszy bajt do zmiennej typu Integer
      Shift T , Left , 8                                        'przesuń ten bajt w lewo na wyższe pozycje
      T = T + Odczyt(1)                                         'przepisz - dodaj młodszy bajt
    
      T1 = T * 0.0625                                           'wyraz w stopniach Celsjusza, wynik wpisz do zmiennej Single
    
    Napis = Fusing(t1 , "#.#")
      Cls : Cursor Off : Lcd "* Temperatura *"
      Lowerline
      Lcd "Wynik: " ; Napis ; " " ; Chr(1) ; "C"
    
    
     Print Napis                                             '!!!! ZMIANA !!!!wyswietl temperature  9,1 CZEMU?
    
    
      Loop : End
    
    


    Teraz wyjaśnię moje zmiany w kodzie :
    Oryginalnie do zmiennej Odczyt(1) szedł kod z czujnika BCD18B20,
    Natomiast ja podałem mu tam wartość 401, czyli w kodzie binarnym dokładnie:
    0000 0001 1001 0001, z tabelki można odczytać, że to powinno wynieść +25.0625C,
    Po przeleceniu kodu na końcu mamy PRINT NAPIS: czyli printowanie naszej temperatury.
    Niestety zamiast spodziewanego 25.625 dostaję wynik 9.1
    Mógłby ktoś mi wyjaśnić dlaczego tak jest?
  • REKLAMA
  • #2 8810312
    Wojtek75
    Poziom 24  
    Jak wciskasz zmienną Integer(NowaTemp) w zmienną typu Byte(Odczyt) to jak myślisz co się z tą zmienną dzieje?
  • REKLAMA
  • #3 8810412
    xamrex
    Poziom 28  
    No, ale jeśli temperatura (z czujnika) jest przesyłana zmienną byte, to w jaki sposób ona się tam mieści?
    Zmienna typu byte ma MAKSYMALNIE 8 bajtów,
    a kod odczytywany z czujnika ma ich 16.
    Tak więc w jaki sposób kod odczytywany z czujnika mieści się w tej zmiennej?
  • #5 8810462
    xamrex
    Poziom 28  
    mam 16 bitów.
  • REKLAMA
  • #6 8810472
    galusz
    Poziom 15  
    Odczyt(1) = 1wread(2)
    Komęda 1wread(2) czyta 2 bajty i zapisuje je do kolejnych pozycji w tablicy, to taki wyjątek gdzie bascom sam inkrementuje tablicę (coś jak wskaźnik w C :D)

    Jeśli chcesz zapisać ręcznie to musisz to podzielić na 2 bajty czyli (401 = &H0191):

    
    Odczyt(1) = &h01
    Odczyt(2) = &h91
  • #8 8810520
    xamrex
    Poziom 28  
    Czyli rozumiem, że Odczytuje się z czujnika temperatura (załóżmy te 10.125C )
    Czyli: 0000 0000 1010 0010

    I do zmiennej Odczyt(1) leci 0000 0000
    a do zmiennej Odczyt(2) leci 1010 0010

    Mam rację?

    Dodano po 36 [minuty]:

    No to zmieniłem swój kod:
    Do
    '  1wreset                                                   'reset
    '  1wwrite &HCC                                              'jedna kostka, więc wykorzystujemy rozkaz SKIP ROM
    '  1wwrite &H44                                              'dokonaj konwersji
    ' Waitms 750                                                 'przeczekaj czas konwersji
    '  1wreset                                                   'reset
    '  1wwrite &HCC                                              'rozkaz adresowy SKIP ROM
    '  1wwrite &HBE                                              'rozkaz funkcyjny - polecenie odczytu DS18x20
    
    Odczyt(1) = 0                                               '!!! ZMIANA !!!odczytaj dwa pierwsze bajty
    Odczyt(2) = 162
    
      T = Odczyt(2)                                             'przepisz starszy bajt do zmiennej typu Integer
      Shift T , Left , 8                                        'przesuń ten bajt w lewo na wyższe pozycje
      T = T + Odczyt(1)                                         'przepisz - dodaj młodszy bajt
    
      T1 = T * 0.0625                                           'wyraz w stopniach Celsjusza, wynik wpisz do zmiennej Single
    
    Napis = Fusing(t1 , "#.#")
      Cls : Cursor Off : Lcd "* Temperatura *"
      Lowerline
      Lcd "Wynik: " ; Napis ; " " ; Chr(1) ; "C"
    
    
     Print Napis                                             '!!!! ZMIANA !!!!wyswietl temperature  9,1 CZEMU?
    
    
      Loop : End
    



    Odczyt(1) = 0
    Odczyt(2) = 162


    Odczyt(1) ustawiłem na 0, gdyż to jest 0000 0000
    a odczyt(2) przypisałem 162, gdyż jest to 1010 0010

    Niestety na samym końcu programu otrzymuję -1504.0 kto mi wyjaśni dlaczego? (powinienem otrzymać 10,125
  • #9 8810756
    zumek
    Poziom 39  
    xamrex napisał:
    ...
    I do zmiennej Odczyt(1) leci 0000 0000
    a do zmiennej Odczyt(2) leci 1010 0010

    Mam rację?


    Nie masz racji i zamiast pytać na forum, zajrzyj do dokumentacji DS-a
    Poza tym , jeśli rozumiesz swój(?) kod z 1-go postu, to pomyśl nad tym fragmentem:
    
      Odczyt(1) = 1wread(2)                                     'odczytaj dwa pierwsze bajty
      T = Odczyt(2)                                             'przepisz starszy bajt do zmiennej typu Integer
      Shift T , Left , 8                                        'przesuń ten bajt w lewo na wyższe pozycje
      T = T + Odczyt(1)                                         'przepisz - dodaj młodszy bajt
    
  • #10 8810814
    xamrex
    Poziom 28  
    galusz napisał:
    Komęda 1wread(2) czyta 2 bajty i zapisuje je do kolejnych pozycji w tablicy, to taki wyjątek gdzie bascom sam inkrementuje tablicę (coś jak wskaźnik w C :D)

    Więc myślałem, że:
    do zmiennej Odczyt(1) leci 0000 0000
    a do zmiennej Odczyt(2) leci 1010 0010

    Jak widać, jest to błędne myślenie i chyba nie tylko ja się tutaj pomyliłem (chyba, że źle zrozumiałem kolegę galusz)

    Kod nie jest mój tylko znaleziony..

    Gdyby ktoś mi mógł tak łopatologiczne wyjaśnić co się dzieje z tym kodem który zostaje odczytany z czujnika, z pewnością ułatwiłoby mi to zrozumienie tego kodu:

    Załóżmy, że mamy temperaturę 10.125C
    czyli (0000 0000 1010 0010)Bin

    Co dalej dzieje się z tymi 16 bitami?

    Jakie bity trafiają do
    Odczyt(1), a jakie do Odczyt(2)
  • REKLAMA
  • #12 8810906
    xamrex
    Poziom 28  
    Wielkie dzięki, xury.
    Nie wiem co bym bez ciepie zrobił :)
    Teraz (chyba) opanowałem ten kod :P
  • #14 8813142
    xamrex
    Poziom 28  
    Jeszcze tylko jedno pytanie.
    Zrobiłem sobie taką symulację:
    
    Odczyt(1) = 145
    Odczyt(2) = 1
    Print Bin(odczyt(1))                                        '10010001
    Print Bin(odczyt(2))                                        '00000001
    T = Odczyt(2)
    Print Bin(t)                                                '0000000000000001
    Shift T , Left , 8
    Print Bin(t)                                                '0000000100000000
    T = T + Odczyt(1)
    Print Bin(t)                                                '0000000110010001
    T1 = T * 0.0625
    Print Bin(t1)                                               '01000001110010001000000000000000
    Print T1                                                     '25,0625          
    



    Przecież taki kod (01000001110010001000000000000000)BIN (chyba)nie daje (25.0625)DEC.
    Więc w jaki sposób wynik to 25.0625
  • Pomocny post
    #15 8813331
    zumek
    Poziom 39  
    xamrex napisał:
    Jeszcze tylko jedno pytanie.


    Co Ci nie pasuje w tym ... równaniu ?
    (1*256+145)*0.0625 = 25.0625

    Podstawą programowania mikrokontrolerów(i nie tylko) jest znajomość arytmetyki i to nie tylko na liczbach dziesiętnych ale również na liczbach binarnych i hexadecymalnych(szesnastkowych).
    Bez tego, ani rusz kolego :D

    napisał:
    Przecież taki kod (01000001110010001000000000000000)BIN

    To jest zapis binarny liczby typu FLOAT SINGLE PRECISION - do sprawdzenia na popularnej Wikipedii
  • #16 8813494
    xamrex
    Poziom 28  
    [Bascom] Termoetr - dlaczego nie mogę podać własnej wartości

    Wartość liczby zmiennoprzecinkowej jest obliczana wg wzoru
    [Bascom] Termoetr - dlaczego nie mogę podać własnej wartości


    gdzie:

    * S (ang. sign) – znak liczby, 1 lub -1
    * M (ang. mantissa) – znormalizowana mantysa, liczba ułamkowa
    * B (ang. base) – podstawa systemu liczbowego (2 dla systemów komputerowych)
    * E (ang. exponent) – wykładnik, liczba całkowita

    S przyjmuje wartości 1 lub -1, a u mnie jest to "0"
    01000001110010001000000000000000
    więc coś mi się tu nie zgadza
  • Pomocny post
    #17 8813542
    Wojtek75
    Poziom 24  
    To w takim razie teraz cytat z helpa Bascom'a:
    Rozdział: Podstawy języka BASCOM BASIC
    Cytat:
    Eksponent jest zapisany jako liczba 8 bitowa ze znakiem w kodzie U2. Jeśli najbardziej znaczący bit jest ustawiony (eksponent > 128) to eksponent jest traktowany jako ujemny. Bit znaku określa znak liczby przechowywanej w zmiennej. Wartość 0 oznacza liczbę dodatnią, 1 zaś ujemną. Mantysa jest przechowywana w znormalizowanym formacie “ukrytego bitu”, dzięki czemu 24 bitowa precyzja może zostać osiągnięta.

    (c) Zbigniew Gibek, 2002-2005 (c) MCS Electronics, 1999-2005
  • #18 8814558
    xamrex
    Poziom 28  
    Chyba została mi jeszcze ostatnia rzecz do ogarnięcia.

    Zostało tam zastosowane mnożenie * 0,0625 (czyli przesunięcie w prawo o 4)

    Mamy teraz taką liczbę:
    0000000110010001 - Typu integer
    zmieniamy ją na typ single i wychodzi nam :
    01000011110010001000000000000000 Skąd się wzięły te dwie jedynki?

    I potem
    01000011110010001000000000000000 mnożymy razy 0,0625 (przesuwamy w prawo)
    i otrzymujemy:
    01000001110010001000000000000000

    Wg. mnie dziwne jest to przesunięcie, bo mi się zawsze wydawało,
    że się po prostu przesuwa w prawo, a tu nie wiadomo skąd i jak zamieniła się jedynka w zero.
    Bardzo bym prosił o wytłumaczenie tego zjawiska :)
    Pozdrawiam i dziękuje za cierpliwość:D
REKLAMA