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

Atmega8, DS1820 + uart - nie działa poprawnie

04 Mar 2011 17:03 2613 8
  • Poziom 13  
    Witam!
    Mam problem z kodem w bascom do obsługi DS1820 oraz wysłaniem wyniku przez uart. Problem wygląda następująco - gdy działa obsługa DS1820 uart nie nadaje sygnału. Gdy wyłączę obsługę 1-wire uart działa.

    Code:
    $regfile = "m8def.dat"
    

    $crystal = 8000000

    Config Lcd = 16 * 2

    Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.3 , Db6 = Portd.2 , Db7 = Portb.0 , E = Portd.5 , Rs = Portd.6       'plyta
    'Config Lcdpin = Pin , Db4 = Portd.5 , Db5 = Portd.6 , Db6 = Portd.7 , Db7 = Portb.0 , E = Portd.3 , Rs = Portd.2

    $baud = 9600

    $hwstack = 32
    $swstack = 10
    $framesize = 40

    Config Serialout = Buffered , Size = 100

    Enable Interrupts

    Config 1wire = Portb.5
    'Config 1wire = Portc.0

    Deflcdchar 0 , 8 , 20 , 11 , 4 , 4 , 4 , 3 , 32

    Cursor Off

    Cls
    Lcd "Inicjalizacja..."

    Wait 5

    Cls

    Dim T1 As Byte
    Dim T1_w As String * 2

    Dim T2 As Byte
    Dim T2_w As String * 2
    Dim Wyslij As String * 5
    Dim Znak As String * 1
    Declare Sub Odczyt

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



    '-----------------------------------
    Dsid1(1) = 1wsearchfirst()
    Dsid2(1) = 1wsearchnext()

    Do

    Call Odczyt

    T1 = T1 / 2
    T2 = T2 / 2

    'T1 = 44
    'T2 = 40

    Znak = "$"
    T1_w = Str(t1)
    T2_w = Str(t2)

    Mid(wyslij , 1 , 1) = Znak
    Mid(wyslij , 2 , 2) = T1_w
    Mid(wyslij , 4 , 2) = T2_w

    Print Wyslij ; Chr(13);

    Locate 1 , 1

    Lcd "Piec:   " ; T1 ; Chr(0) ; "      "

    Locate 2 , 1

    'Lcd "Bojler: " ; T2 ; Chr(0) ; "      "
    Lcd T2 ; "  " ; Wyslij


    Loop
    End

    Odczyt:

    1wreset                                                     'reset magistrali 1-Wire
     1wwrite &HCC                                               'opuszczenie zapisu numeru ID
     1wwrite &H44                                               'start pomiaru temperatury
     Waitms 750                                                 'opóźnienie na czas pomiaru
     1wreset                                                    'reset magistrali 1-Wire
     1wwrite &HCC                                               'opuszczenie zapisu numeru ID
     1wwrite &HBE                                               'komenda odczytu zmierzonej
          'temperatury
     T1 = 1wread(2)                                             'odczyt zmierzonej temperatury
          'do tablicy Temperatura
     1wreset                                                    'reset magistrali 1-Wire



    Return


    W takiej wersji programu jak powyżej działa pomiar temperatury, ale nie działa transmisja uart. Jak wyrzucam waitms 750 z obsługi DS-a - działa uart ale nie działa odczyt z DS-a. Co można w takim wypadku zrobić. Proszę o pomoc, bo brakuje już mi pomysłów.
  • Pomocny post
    Poziom 38  
    Potrzebny jest Timer i przerwanie od timera.
    Timer ustawia flagę jak się przepełni.
    Np. co 1s.
    W petli głównej sprawdzasz czy już upłynęła 1s.
    Dopiero potem wolno Ci odczytać pomiar temperatury.
    Nie wolno stosować Waitms jeśli program ma obsługiwać więcej niż jedno urządzenia.
  • Pomocny post
    Poziom 13  
    A to niby dlaczego nie wolno stosować waitms ??? U mnie jakoś działa przy wielu czujnikach na jednej linii i co to ma wspólnego z wysyłaniem przez uarta ? W tym przypadku waitms nie zakłóca obsługi przerwań, wiec nie widzę problemu.
    Kolega namieszał trochę w procedurze "odczyt". Na początku wyszukujesz czujniki na linii 1wire, a później, w procedurze odczyt obsługujesz tylko jeden czujnik... Poza tym jakoś dziwnie deklarujesz procedurę odczyt. Jeśli dajesz declare sub, to nie kończ funkcji returnem tylko end sub. Poza tym przy wysyłaniu uartem takiej małej ilości danych możesz sobie odpuścić buforowanie.
    Jakiego używasz czujnika ds ? Ds18s20 czy ds18b20 ? Jeśli tego drugiego, to nieprawidłowo przeliczasz wartość zmiennej T1.
    Tak na szybko pokroiłem twój kod. Nie ładowałem do avr'a, ale wypróbuj go. Można tam jeszcze wiele zmienić ale powinno się udać odczytać temp z ds'a, wyświetlić to na lcd i wysłać uartem.

    Code:

    Enable Interrupts

    Config 1wire = Portb.5

    Deflcdchar 0 , 8 , 20 , 11 , 4 , 4 , 4 , 3 , 32

    Cursor Off
    Cls

    Dim T1 As Byte
    Dim T1_w As String * 2
    Dim Wyslij As String * 5
    Dim Znak As String * 1

    Do
       Gosub Odczyt
       T1 = T1 / 2

       Znak = "$"
       T1_w = Str(t1)

       Mid(wyslij , 1 , 1) = Znak
       Mid(wyslij , 2 , 2) = T1_w
       Mid(wyslij , 4 , 2) = T2_w

       Locate 1 , 1
       Lcd "Piec:   " ; T1 ; Chr(0) ; "      "
       Print Wyslij; chr(13)
    Loop
    End

    Odczyt:
       1wreset                                                  'reset magistrali 1-Wire
          1wwrite &HCC                                          'opuszczenie zapisu numeru ID
          1wwrite &H44                                          'start pomiaru temperatury
          Waitms 750                                            'opóźnienie na czas pomiaru
          1wreset                                               'reset magistrali 1-Wire
          1wwrite &HCC                                          'opuszczenie zapisu numeru ID
          1wwrite &HBE                                          'komenda odczytu zmierzonej
          'temperatury
       T1 = 1wread(2)                                           'odczyt zmierzonej temperatury
          'do tablicy Temperatura
    Return
  • Poziom 13  
    MaxX850 dzięki za podpowiedź. Wyszukiwanie czujników jest użyte gdyż docelowo są podłączone dwa - do testów ustawiłem odczyt tylko z jednego. Dziwne jest to, że mój program działa na Attiny2313, a jak przeniosłem go na Atmega przestał działać. Użyte czujniki do DS1820. Problemem na pewno jest "waitms". Gdy mam w programie "waitms" czujniki pokazują odpowiednią temperaturę, ale odbiornik otrzymuje tylko śmieci. Gdy wyrzucę "waitms" odczyt z DS-a jest ciągle na poziomie 85 stopni ale działa przesyłanie - na odbiorniku pojawia się 85 stopni. Pierwszy raz spotykam się z takim problemem. Niestety rozwiązania będę mógł przetestować dopiero w poniedziałek. Jeśli macie jeszcze jakieś sugestie chętnie skorzystam.
  • Poziom 13  
    Myślę,że na elektrodzie z 90% przykładowych kodów do obsługi ds18x20 pod bascoma korzysta z waitms. Niezależnie od ilości czujników. Sam mam urządzenie do opomiarowania kotła CO w którym jest 5 dsów, transmisja przez sprzętowy uart z sim300 i przez programowy uart z btm222. Wykorzystuję tam też dwa timery do obsługi alarmów i podświetlenia lcd, a w procedurze odczytu z czujników mam właśnie waitms. Jedyna rzecz jaka przychodzi mi jeszcze do głowy to disable interrupts na początku procedury "odczyt" i enable interrupts na jej końcu. Wyłącz przerwania na czas obsługi 1wire.

    Code:

    Odczyt:
    Disable interrupts
       1wreset                                                  'reset magistrali 1-Wire
          1wwrite &HCC                                          'opuszczenie zapisu numeru ID
          1wwrite &H44                                          'start pomiaru temperatury
          Waitms 750                                            'opóźnienie na czas pomiaru
          1wreset                                               'reset magistrali 1-Wire
          1wwrite &HCC                                          'opuszczenie zapisu numeru ID
          1wwrite &HBE                                          'komenda odczytu zmierzonej
          'temperatury
       T1 = 1wread(2)                                           'odczyt zmierzonej temperatury
          'do tablicy Temperatura
    Enable interrupts
    Return


    Ps. Masz prawidłowo ustawione fusy od oscylatora w uP ? Jaką masz szybkość transmisji ustawioną dla uarta ?
  • Poziom 13  
    Witam!
    Fusy ustawione jako HF: C9, LF: FF. Co do prędkości to testowałem na 4800bps oraz 9600bps - na obu chodzi jeśli przesyłam np. liczby wpisane na sztywno. Sprawdzę twoje podpowiedzi w poniedziałek i dam znać czy coś ruszyło.
  • Poziom 38  
    To "disable interrupt" i "enable interrupt" to masło maślane.
    Jak wchodzi w przerwanie to i tak blokuje inne.
    Zrób tak jak proponuje xury.
    A wogóle to zrób tak- ustaw sobie timer np. na 10 czy 100ms.
    W Timerze ustawiaj tylko flagi.
    A w pętli głównej zwiększaj wartość każdej flagi.
    A później tak- jeśli flaga osiągnęła jakąś wartość- to ją kasujesz i wykonujesz co trzeba.
    W if-then.
    Zwróć uwagę że jednym timerem możesz obsłużyć opóżnienie odczytu z DS, eliminować drgania styków i co tam jeszce się zmieści.
  • Poziom 13  
    Problem rozwiązany. Nie dawało mi spokoju to, że program działał na Attiny2313, a na Atmedze8 nie chce. Zmieniłem więc pin na którym odbywa się transmisja 1-wire oraz podłączyłem moje 2xDS1820 i o dziwo wszystko zaczęło dobrze działać. W czym tak naprawdę był problem - ciężko stwierdzić, najważniejsze, że program działa teraz bez "waitms 750". Dziękuje wszystkim, którzy służyli pomocą i umieszczam kod ostateczny programu na którym teraz działa mój układ.
    Code:
    $regfile = "m8def.dat"
    

    $crystal = 8000000

    Config Lcd = 16 * 2

    Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.3 , Db6 = Portd.2 , Db7 = Portb.0 , E = Portd.5 , Rs = Portd.6

    $baud = 4800

    $hwstack = 32
    $swstack = 10
    $framesize = 40

    Config Serialout = Buffered , Size = 100

    Enable Interrupts

    Config 1wire = Portb.1

    Deflcdchar 0 , 8 , 20 , 11 , 4 , 4 , 4 , 3 , 32

    Cursor Off

    Cls
    Lcd "Inicjalizacja..."

    Wait 5

    Cls

    Dim T1 As Byte
    Dim T1_w As String * 2

    Dim T2 As Byte
    Dim T2_w As String * 2
    Dim Wyslij As String * 5
    Dim Znak As String * 1

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



    '-----------------------------------
    Dsid1(1) = 1wsearchfirst()
    Dsid2(1) = 1wsearchnext()

    Do

    Gosub Odczyt

    T1 = T1 / 2
    T2 = T2 / 2

    Znak = "$"
    T1_w = Str(t1)
    T2_w = Str(t2)

    Mid(wyslij , 1 , 1) = Znak
    Mid(wyslij , 2 , 2) = T1_w
    Mid(wyslij , 4 , 2) = T2_w

    Print Wyslij ; Chr(13);

    Locate 1 , 1

    Lcd "Piec:   " ; T1 ; Chr(0) ; "      "

    Locate 2 , 1

    Lcd "Bojler: " ; T2 ; Chr(0) ; "      "

    Loop
    End

    Odczyt:

    1wreset
    1wwrite &H55
    1wverify Dsid1(1)
    1wwrite &HBE
    T1 = 1wread(2)

    1wreset
    1wwrite &H55
    1wverify Dsid2(1)
    1wwrite &HBE
    T2 = 1wread(2)

    1wreset
    1wwrite &HCC
    1wwrite &H44                                             'reset magistrali 1-Wire

    Return