Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

[Bascom]2xDS18B20+Atmega8 -jak wykryć brak jednego czujnika?

wojtek2812 16 Jan 2011 15:22 2501 17
  • #1
    wojtek2812
    Level 22  
    Witam! Jako że zaczynam dopiero z bascomem mam mały problem z napisaniem sensownego kodu do termometru. Na tą chwilę z materiałów znalezionych w internecie udało mi się zlepić coś takiego:
    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.5 , Db5 = Portb.4 , Db6 = Portb.3 , Db7 = Portb.2 , E = Portc.4 , Rs = Portc.5

    Config Lcd = 16 * 2                                         'ustawiamy typ wyświetlacza
    '*************************************WAŻNE**********************************************

    Config 1wire = Portd.7                                      'deklaracja portu na którym będą podpięte DS18b20

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


    Dim Dsid1(8) As Byte
    Dim Dsid2(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 , 2 , 5 , 2 , 32 , 32 , 32 , 32 , 32
               'znak stopnia Celsjusza
    Deflcdchar 1 , 16 , 16 , 20 , 24 , 16 , 16 , 30 , 32        ' Ł
    Cursor Off                                                  'Wyłącza kursor
    Cls                                                         'Funkcja CLS czyści ekran
    Lcd "     MI" ; Chr(1) ; "EGO     " ;                       'ekran startowy (pojawia się tylko podczas włączania urządzenia)
    Lowerline
    Lcd "      DNIA      "
    Wait 2
    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










    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 &HCC
       1wwrite &H44
    Waitms 750



       I1 = I1 * 10
       I1 = I1 / 16
       'If I1 > 0 Then Cls                                       '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 "Temp.wew:" ; Ss ; Chr(0) ; "C"

       I2 = I2 * 10
       I2 = I2 / 16
       'If I2 > 0 Then Cls
       Ss = Str(i2)
       Ss = Format(ss , " 0.0")
       Locate 2 , 1
       Lcd "Temp.zew:" ; Ss ; Chr(0) ; "C"



    Loop

    Na tą chwilę oba czujniki podłączone są do portu PD7, odłączenie jednego z czujników powoduje to, że "przepisywane" jest wskazanie z drugiego czujnika i wyświetlane temperatury wewnętrzna i zewnętrzna są takie same. Chciałbym,aby w przypadku odłączenia jednego czujnika, przykładowo temperatury wewnętrznej na wyświetlaczu pojawiał sie komunikat w stylu temp.wew:brak. Jak to zrobić? Proszę o pomoc.
  • #2
    hotdog
    Level 26  
    problemem nie jest bascom, tylko Twoje podejście.

    Jeżeli w momencie włączenie programu masz podłączony tylko jeden czujnik, to do buforów Dsid1 i Dsid2 trafią te same adresy czujników. Dalej program już będzie po prostu odczytywał za każdym razem dane z jednego czujnika, tyle że 2 razy.

    Rozwiązać problem można na co najmniej 2 sposoby, ale ponieważ się uczysz to ich Tobie na talerzu nie podam (czyt. pogłówkuj i jak nie wpadniesz na nic to napisz). Pozdrawiam
  • #3
    wojtek2812
    Level 22  
    Czytałem coś o wpisywaniu na stałe ID czujnika do programu i identyfikacja go na tej podstawie. Dobry trop?
  • #5
    hotdog
    Level 26  
    wg mnie poprawne sposoby na zrobienie tego to:
    1. Podłączenie czujnika do oddzielnych portów uC. Czujnik jest identyfikowany na podstawie pinu uC.
    Zalety:
    - prosty program
    - mało zajmuje na uC (brak konieczności dodawania funkcji 1wireSearch)
    - zawsze wiadomo który czujnik jest który
    Wady:
    - kiepska skalowalność (na każdy czujnik potrzebny jest dodatkowy port)
    2. Zapisanie ID czujników w eeprom:
    Zalety:
    - można podłączyć wiele czujników
    Wady:
    - Bardziej rozbudowany program
    - Konieczność dodania mechanizmu do identyfikacji czujników (funkcja w menu itd)
    - zajmuje więcej pamięci na uC

    @xury
    Porównanie ID nie rozwiązuje problemu, bo itak nie wiadomo który czujnik się zepsuł/został usunięty, a który jest sprawny.
    Sprawdzenie obecności czujnika jest niemożliwe do zrealizowania. Jedynie można sprawdzić czy jakikolwiek czujnik na magistrali istnieje (w trakcie komendy RESET). Jeżeli na magistrali nie ma już czujnika (zepsuł się, został wypięty), to przy odczycie po ID dostaniesz same stany wysokie (0xFF). Nie wiem czy bascom pozwala na sprawdzanie CRC czujnika (pewnie tak). Warto to zaimplementować. Czasami czujniki też potrafią się uszkodzić w sposób taki, że zawsze pokazują tą samą temperaturę (np. 85*C)

    Summarum ja bym dla 2 czujników podłączył każdy do innego pinu uC.

    Pozdrawiam
  • #6
    mirekk36
    Level 42  
    hotdog wrote:
    Sprawdzenie obecności czujnika jest niemożliwe do zrealizowania. Jedynie można sprawdzić czy jakikolwiek czujnik na magistrali istnieje (w trakcie komendy RESET).


    Eeeeeh no panie kolego hotdog, ależ to jest do zrealizowania i to nawet w Bascomie - zresztą w dowolnym języku bo to nie jest zależne ani od języka ani od magistrali 1wire tylko od pomysłu.

    Mniej więcej tak jak pisał kolega wyżej, tworzysz sobie kilka slotów na czujniki, przypisujesz sobie do nich odpowiednie ID każdego z czujników i proszę bardzo. To wszystko. Gdy jeden się zepsuje, zostanie wypięty, uszkodzony itp to po prostu nie będzie odpowiadał na polecenia i już można zasygnalizować jego brak. Nie wiem na prawdę co może być trudnego w zorganizowaniu czegoś takiego? Wszystko oczywiście na JEDNEJ linii a nie na jakichś tam wielu pinach bo to jest właśnie rozwiązanie troszkę hmmmm "nieteges"
  • #7
    hotdog
    Level 26  
    mirekk36 wrote:
    Eeeeeh no panie kolego hotdog, ależ to jest do zrealizowania i to nawet w Bascomie - zresztą w dowolnym języku bo to nie jest zależne ani od języka ani od magistrali 1wire tylko od pomysłu.


    Nie zrozumiałeś mnie w tym miejscu. Miałem na myśli że nie idzie sprawdzić obecności konkretnego czujnika przy komendzie Reset. Jedynie czy jakikolwiek odbiornik na magistrali istnieje. Rozwiązanie z brakiem odpowiedzi to była oczywista oczywistość, o której nawet nie wspominałem.

    mirekk36 wrote:
    Wszystko oczywiście na JEDNEJ linii a nie na jakichś tam wielu pinach bo to jest właśnie rozwiązanie troszkę hmmmm "nieteges"

    Ze słowem "nieteges" się kategorycznie muszę nie zgodzić. Czemu nazywasz prostsze rozwiązanie w ten sposób?

    Ja dla 2 czujników bym sobie nawet głowy tym nie zawracał. Takie wykonanie, na jednej linii, ma bez wątpienia dużo większą wartość edukacyjną i jeżeli o edukacje tutaj chodzi to dobra droga. No może jeszcze więcej kabla idzie zaoszczędzić przy tym rozwiązaniu. O różnicach, wadach i zaletach pisałem wyżej więc nie będę się powtarzał.
  • #8
    mirekk36
    Level 42  
    Nie - no można sobie podłączać na większej ilości linii .... a kto zabroni ;) .... chodzi mi tylko o to, że obsługa 1wire jest na tyle prosta że jej jeszcze większe upraszczanie poprzez rozdział na kolejne linie a szczególnie przy niewielkiej ilości czujników ja uważam za hmm no niech będzie nietrafione. Ale to moje zdanie a każdy może mieć inne. Nie mówię przecież że tak należy lub nie należy robić.
  • #9
    wojtek2812
    Level 22  
    Dla kolegów którzy w tym siedzą może i jest to proste, ja z cyfrówki jestem ze tak powiem noga, z procesorów to już w ogóle. Można nieco jaśniej bo niewiele rozumiem z tego co mówicie ? :) Pozdrawiam
  • #10
    hotdog
    Level 26  
    Opcja z jedną linią 1Wire (czyt. tak jak teraz masz):
    Musisz dodać tryb konfiguracji do programu, w nim uruchamiasz procedury 1WireSearch i odczytujesz jakie są ID czujników. Następnie np podgrzewasz czujnik nr 1, program sprawdza który to numer 1 i zapisuje go w eepromie pod pozycją 1. Robisz tak dla wszystkich czujników na magistrali. W programie głównym na początku odczytujesz z eeprom ID czujników i następnie w pętli odczytujesz z nich temperaturę. Jeżeli jakiś się uszkodzi to odczytasz same 0xFF.

    Opcja z wieloma linią 1Wire:
    Podłączasz linie DQ z czujnika do innych portów procesora (każda z rezystorem). W programie głównym dla każdego czujnika wykonujesz mniej więcej takie polecenia:
    Code:


       1wreset Pinb , 0
       1wwrite &HCC, Pinb , 0
       1wwrite &H44, Pinb , 0

       Waitms 750

       1wreset Pinb , 0
       1wwrite &HCC, Pinb , 0
       1wwrite &HBE, Pinb , 0
       I2 = 1wread(2, Pinb , 0)



    Nie wiem czy czegoś ze składnią nie pokaszaniłem. W przykładzie założyłem że czujnik jest podłączony do PINB,0. Dla drugiego będzie np Pinb,1

    Jak jakiś się uszkodzi, to go po prostu wymieniasz i działa dalej.
  • #11
    wojtek2812
    Level 22  
    Witam! A co z deklaracją 1wire w przypadku czujników na osobnych portach procesora? W przypadku 2 czujników na jednej linii u mnie było po prostu
    Code:
    Config 1wire = Portd.7
    a jak będzie w przypadku który opisał kolega hotdog?
  • #12
    piotrva
    VIP Meritorious for electroda.pl
    poczytaj sobie helpa bascoma i spójrz na kod w poście nad Twoim.
    masz tam polecenia obsługi 1w na konkretnych pinach, np.
    Code:

    1wreset Pinb, 0

    powoduje wysłanie sygnału reset dla magistrali 1w na pin PB0.
    analogicznie pozostałe polecenia
  • #13
    wojtek2812
    Level 22  
    Witam ponownie. Panowie mam teraz inny problem, póki co dla mnie poważniejszy niż wykrywanie braku czujnika. Problem polega na tym, że przy zmianie wyświetlania wskazania z temperatury ujemnej na dodatnią znika znak minus, wskazanie przesuwa się w lewo ale znak C zostaje tam gdzie był przy wyświetlaniu temperatury ujemnej (jedna pozycja w prawo) i gdy termometr znów wyświetla temperaturę dodatnią na wyświetlaczu widnieją dwa znaki temperatury, coś takiego "X,X *CC". Bardzo mnie to denerwuje. Jak temu zaradzić?
  • #14
    WOBI
    Level 19  
    Masz problem bo nie pozycjonujesz prawidłowo na LCD wyświetlanej temperatury. Masz różne kombinacje wyświetlanych cyfr i tak np

    -1,0*C
    1.0*C
    -10.0*C
    10.0*C

    więc zobacz dlaczego na wyświetlaczu zostają poprzednio wpisane znaki, celowo wypisałem jedne pod drugim byś zobaczył przyczynę powstawania blędu.

    najprościej pisz jeszcze spacje po "C "


    Code:

       Locate 2 , 1
       Lcd "Temp.zew:" ; Ss ; Chr(0) ; "C "



    A co do wykrywania obecności czujnika to po kazdym użyciu rozkazy 1W masz zmienną Err która = 0 zero przy obecności czujnika czyli prawidlowemu wykonaniu danej komendy. pomyśl jak to wykorzystać.

    Code:

     Dim Zmienna_alarm as Bit ' do użycia w programie np. do sygmnalizacji, zapalenia diody itp

    Do
       1wreset
       1wwrite &H55
       1wverify Dsid1(1)                                        'wysyłamy adres pierwszego czujnika

                         Zmienna_alarm = Err   ' sprawdzamy czy jest czujnik lub czy nie jest uszkodzony

                  If Zmienna_alarm = 0 Then     ' jestli brak czujnika to skok do... else

       I1 = 1wread(2)

                  ' tu dalsze Twoje rozkazy jesli czujnik jest
    '---------------------------------
     else
                     'tu program i reakcja na brak czujnika lub puste i dalsze reakcje
                     ' w programie głównym  używając zmiennej Zmienna_alarm
    end if
  • #15
    wojtek2812
    Level 22  
    Dziękuje za pomoc. Oczywiście podpowiedź dotycząca spacji po znaku C okazała się trafna. A co do wykrywania nieobecności jednego z czujników doprecyzuję może o co mi chodzi- chciałbym aby działało to na takiej zasadzie, że układ będzie wiedział którego konkretnie czujnika brakuje. dostanę jeszcze jakąś podpowiedź?
  • #16
    WOBI
    Level 19  
    Napisałem wyżej jak to zrobić, czytaj i pomyśl, Użyj zmiennej Err i przesyłaj ją do utworzonych zmiennych bitowych później badasz warunek IF jak wyżej.
    Masz tam gotowy przykład


    mała podpowiedź... ale tylko tyle bo na tym polega nauka by robić to samemu i uczyć się.

    Code:


    Dim Alarm_1_czujnik As Bit  ' zmienna = 0 gdy jest czujnik nr1 / =1 brak
    Dim Alarm_2_czujnik As Bit  ' zmienna = 0 gdy jest czujnik nr1 / =1 brak

    '.......
    1wreset
       1wwrite &H55
        1wverify Dsid1(1)                 'wysyłamy adres pierwszego czujnika
                                             ' 1wverify jesli nie ma czujnika o tym numerze to..

                   Alarm_1_czujnik = Err        ' jesli nie ma tego czujnika to w zmiennej biedzie jeden


    '........................ tu dalszy program lub sprawdzenie warunku IF
    '.................
    ' nastepny czujnik
    1wreset
       1wwrite &H55
       1wverify Dsid2(1)                        'wysyłamy adres drugiego czujnika i sprawdzamy

                        Alarm_2_czujnik = Err

    '................................ tu dalszy program lub IF



  • #17
    wojtek2812
    Level 22  
    Witam! Na tą chwile (brak czasu) udało mi się sklecić coś takiego:
    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.5 , Db5 = Portb.4 , Db6 = Portb.3 , Db7 = Portb.2 , E = Portc.4 , Rs = Portc.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.7                                      'deklaracja portu na którym będą podpięte DS18b20

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


    Dim Dsid1(8) As Byte
    Dim Dsid2(8) As Byte

    Dim Brak_czujnika_wew As Bit
    Dim Brak_czujnika_zew As Bit
    Dim W As Byte
    Deflcdchar 0 , 2 , 5 , 2 , 32 , 32 , 32 , 32 , 32
               'znak stopnia Celsjusza
    Deflcdchar 1 , 4 , 31 , 2 , 4 , 8 , 16 , 31 , 32            ' replace ? with number (0-7)             ' Ż
    Deflcdchar 2 , 32 , 32 , 14 , 17 , 31 , 16 , 14 , 4         ' ę
    Deflcdchar 3 , 32 , 4 , 14 , 17 , 17 , 17 , 14 , 32         ' ó
    Deflcdchar 4 , 32 , 2 , 7 , 8 , 6 , 1 , 14 , 32             ' ś
    Cursor Off                                                  'Wyłącza kursor
    Cls                                                         'Funkcja CLS czyści ekran
    Lcd "Dla mojej Anitki" ;                                    'ekran startowy (pojawia się tylko podczas włączania urządzenia)
    Lowerline
    Lcd "    kochanej    "
    Waitms 2250
    Cls
    Lcd "    z okazji    "
    Lowerline
    Lcd "   Walentynek   "
    Waitms 2250
    Cls
    Lcd "   Kocham Ci" ; Chr(2) ; "   "
    Lowerline
    Lcd "    " ; Chr(1) ; "abciu..."
    Waitms 2250
    Cls
    Lcd "...Tw" ; Chr(3) ; "j Wojtu" ; Chr(4) ; ""
    Waitms 2250
    Cls                                                         'Znajdź pierwszy czujnik podpięty do portu
    Waitms 500
    W = 1wirecount()
    Lcd "Czujnik" ; Chr(3) ; "w:"                               'Informuje ile czujników jest podpiętych do układu (pojawia się tylko podczas włączania urządzenia)
    Waitms 500
    Lcd W
    Wait 2
    1wreset
    If Brak_czujnika_wew = 1 Then
    Lcd "Temp.wew: brak"
    End If


    Dsid1(1) = 1wsearchfirst()                                  'Znajdź kolejny czujnik podpięty do portu
    Dsid2(1) = 1wsearchnext()                                   'Znajdź kolejny czujnik podpięty do portu








    Do
       1wreset
       1wwrite &H55
       1wverify Dsid1(1)

       Brak_czujnika_wew = Err
       If Brak_czujnika_wew = 0 Then
       1wwrite &HBE                                             'wysyłamy adres pierwszego czujnika
       I1 = 1wread(2)

    '---------------------------------
       Else
       End If

       1wreset
       1wwrite &HBE
       1wverify Dsid2(1)
       Brak_czujnika_zew = Err
       If Brak_czujnika_zew = 0 Then                            'wysylam adres drugiego czujnika
       1wwrite &HBE
       I2 = 1wread(2)
    '---------------------------------
        Else
        End If

       1wreset
       1wwrite &HCC
       1wwrite &H44
    Waitms 750

    '***************************************************************************************************************************************

       I1 = I1 * 10
       I1 = I1 / 16
       'If I1 > 0 Then Cls                                       '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 "Temp.wew:" ; Ss ; Chr(0) ; "C"

       I2 = I2 * 10
       I2 = I2 / 16
       'If I2 > 0 Then Cls
       Ss = Str(i2)
       Ss = Format(ss , " 0.0")
       Locate 2 , 1
       Lcd "Temp.zew:" ; Ss ; Chr(0) ; "C"



    Loop

    Oczywiście program nie działa tak jak chcę bo np po odłączeniu czujnika temp wewnętrznej wskazanie powoli maleje do 0,0*C. Wiem że namieszałem ze składnią ale próbuje i nie bardzo widać efekty a czas goni... Proszę o dalsze wskazówki. Dziękuje.
  • #18
    WOBI
    Level 19  
    a co to za kwiatek?!

    Code:
    '---------------------------------
    
       Else
       End If

       1wreset
       1wwrite &HBE   '??????????????????????????????????????????????
       1wverify Dsid2(1)
       Brak_czujnika_zew = Err
       If Brak_czujnika_zew = 0 Then                            'wysylam adres drugiego czujnika
       1wwrite &HBE
       I2 = 1wread(2)
    '---------------------------------


    przecież kroki są
    1. reset
    2. write 55hex czyli komenda dla czujnika o konkretnym adresie
    3. write (adres1 czujnika) czyli adres czujnika od teraz on odpowiada
    4. write BEhex teraz rozkaz dla konkretnego zaadresowanego czujnika
    i 5. read (2 bajty temperatury)

    i to samo dla drugiego czujnika ale Ty dajesz
    1. reset
    2. write BE niezły kwiatuszek
    3. write (adres2)
    4. write BE
    5. read (2 bajty)

    i dalej nie widzisz co piszesz? Za dużo myślisz o dziwnym amerykansk'ym święcie a za mało oprogramowaniu ;)
    Ps. Jeśli ktoś Tobie pomaga to używa się przycisku pomógł ;)