Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

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

wojtek2812 16 Sty 2011 15:22 2336 17
  • #1 16 Sty 2011 15:22
    wojtek2812
    Poziom 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.

    0 17
  • #2 16 Sty 2011 16:16
    hotdog
    Poziom 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

    0
  • #3 16 Sty 2011 16:30
    wojtek2812
    Poziom 22  

    Czytałem coś o wpisywaniu na stałe ID czujnika do programu i identyfikacja go na tej podstawie. Dobry trop?

    0
  • #4 16 Sty 2011 16:37
    xury
    Poziom 38  

    Rozwiazań jest kilka np.:
    Możesz użyć porównania ID
    Możesz zapisać ID do eeprom.
    Możesz sprawdzać obecność czujnika przed poleceniem odczytu temperatury.
    itd.

    0
  • #5 16 Sty 2011 17:15
    hotdog
    Poziom 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

    0
  • #6 16 Sty 2011 17:56
    mirekk36
    Poziom 42  

    hotdog napisał:
    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"

    0
  • #7 16 Sty 2011 19:43
    hotdog
    Poziom 26  

    mirekk36 napisał:
    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 napisał:
    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ł.

    0
  • #8 16 Sty 2011 20:01
    mirekk36
    Poziom 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ć.

    0
  • #9 16 Sty 2011 21:09
    wojtek2812
    Poziom 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

    0
  • #10 16 Sty 2011 23:33
    hotdog
    Poziom 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.

    0
  • #11 17 Sty 2011 09:34
    wojtek2812
    Poziom 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?

    0
  • #13 08 Lut 2011 20:43
    wojtek2812
    Poziom 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ć?

    0
  • #14 08 Lut 2011 21:02
    WOBI
    Poziom 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

    0
  • #15 08 Lut 2011 22:44
    wojtek2812
    Poziom 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ź?

    0
  • #16 09 Lut 2011 08:33
    WOBI
    Poziom 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



    0
  • #17 11 Lut 2011 18:41
    wojtek2812
    Poziom 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.

    0
  • #18 11 Lut 2011 19:08
    WOBI
    Poziom 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ł ;)

    0
  Szukaj w 5mln produktów