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

Atmega8+ds18b20+LCD problem z timer0

03 Mar 2009 12:25 2216 9
  • Poziom 12  
    Zbudowałem układ, który mierzy temp. z trzech ds18b20 i wyświetla na lcd.
    Problem zaczyna się gdy włączę przerwania od timera0 (który tylko w tle odmierza sobie odcinki czasu po 8ms), a mianowicie mierzona temperatura jest nie prawidłowa a później zaczyna się krzaczyć lcd. Ma to być sterownik pieca CO więc potrzebuję odliczać krótkie odcinki czasu na pracę nadmuchu.
    Jak rozwiązać ten problem??

    Code:


    $regfile = "m8def.dat"
    $crystal = 1000000



    Config Pind.7 = Output                                      'przekaznik elektrozaworu
    Config Pind.6 = Output                                      'przekaznik pompy
    Config Pind.5 = Output                                      'przekaznik wentylatora
    Config Pinb.1 = Input                                       'przycisk "w górę"
    Config Pinb.2 = Input                                       'przycisk "w dół"
    Config Pinb.7 = Input                                       'przycisk "ok"
    Config Pinb.6 = Input                                       'przycisk "menu"
    Config Debounce = 25                                        'czas ponownego sprawdzenia przycisku, eliminacja drgań
    Config 1wire = Portb.0                                      ' konfiguracja portu PB.0 jako wejścia magistrali 1-wire

    Config Lcd = 16 * 2
    Config Lcdpin = Pin , Db4 = Portc.2 , Db5 = Portc.3 , Db6 = Portc.4 , Db7 = Portc.5 , E = Portc.1 , Rs = Portc.0

    Elektrozawor Alias Portd.7                                  'przypisanie nazw do wyjść i wejść
    Nadmuch Alias Portd.5
    Pompa Alias Portd.6

    P_gora Alias Pinb.1
    P_dol Alias Pinb.2
    P_ok Alias Pinb.7
    P_menu Alias Pinb.6

    Set P_gora                                                  'włączenie rezystorów podciągających na wejściach
    Set P_dol
    Set P_ok
    Set P_menu

    Deflcdchar 0 , 28 , 20 , 28 , 32 , 7 , 4 , 4 , 7            'definicja znaku stopnia z małem znaczkiem celcjusza
    Deflcdchar 1 , 31 , 27 , 21 , 21 , 21 , 21 , 27 , 31        ' "O" na czarnym tle
    Deflcdchar 2 , 31 , 23 , 22 , 21 , 19 , 21 , 22 , 31        ' "K" na czarnym tle
    Deflcdchar 3 , 4 , 14 , 31 , 32 , 32 , 31 , 14 , 4          'strzałeczki

    Declare Sub Konfiguracja_czujnikow                          'procedura odczytuje id czujnika
    Declare Sub Odczyt_temperatury(byval Konfig As Byte)
    Declare Sub Dalej
    Declare Sub Dalej1                                          'procedura wysyła id do czujnika
    Declare Sub Dalej2

    Dim Id(9)as Byte                                            'zmienna przechowująca id układu ds18b20,9-ty element informuje
                                                                 'o umiejscowieniu czujnika: 1=piec,2=wymiennik ciepła,3=na zewnątrz

    Dim I As Byte                                               'zmienna licznikowa
    Dim J As Byte                                               'zmienna licznikowa

    Dim Temp_pieca As Single                                    'zmienne przechowujące poszczególne temperatury
    Dim Temp_wymiennika As Single
    Dim Temp_zewnetrzna As Single

    Dim Wyjscie As Bit                                          'zmienna do wyjścia z procedur


    Config Timer0 = Timer , Prescale = 64
    Enable Interrupts
    Enable Timer0
    Load Timer0 , 125
    On Timer0 Odmierz_1s
    Dim Licz_8ms As Byte



    Cls






    Cursor Off
    Do
       
       Debounce P_gora , 0 , Konfiguracja_czujnikow , Sub

    Call Odczyt_temperatury(0)



                 Locate 1 , 1
                Lcd "P:" ; Fusing(temp_pieca , "#.#") ; Chr(0) ; " "

                Lcd "W:" ; Fusing(temp_wymiennika , "#.#") ; Chr(0) ; " "

                Locate 2 , 1
                Lcd "Z:" ; Fusing(temp_zewnetrzna , "#.#") ; Chr(0) ; " "








    Loop
    End







    Sub Konfiguracja_czujnikow                                  'ciało procedury odczytującej id czujników,zapis do eeprom
                                                                'oraz przypisanie umiejscowienia czujników


                                                                'zawiera ilość układów podłączonych do 1-wire
    Local Ilosc_czujnikow As Byte
    Dim Flaga(2) As Byte
    Local Indeks As Byte

    Ilosc_czujnikow = 1wirecount()                              'odczyt ilości czujnikow podłączonych do 1-wire


    Cls

    Id(1) = 1wsearchfirst()                                     'odczyt id pierwszego czujnika
       Id(9) = 1

       Lcd "czujnik " ; 1
       Lowerline
       For I = 1 To 9
       Writeeeprom Id(i) , I


       Lcd Id(i)
       Next I

       Wait 1
     Cls

    Id(1) = 1wsearchnext()
       Id(9) = 2

       Lcd "czujnik " ; 2
       Lowerline
       J = 1
       For I = 10 To 18
       Writeeeprom Id(j) , I


       Lcd Id(j)
       Incr J
       Next I

       Wait 1
     Cls

    Id(1) = 1wsearchnext()
       Id(9) = 3

       Lcd "czujnik " ; 3
       Lowerline
       J = 1
       For I = 19 To 27
       Writeeeprom Id(j) , I


       Lcd Id(j)
       Incr J
       Next I

       Wait 1
     Cls

    Lcd "wykryto: " ; Ilosc_czujnikow ;
    Lowerline
    Lcd " czujnik(i)"
    Locate 2 , 15
    Lcd Chr(1) ; Chr(2)

    Bitwait P_ok , Reset
    Waitms 25
    Bitwait P_ok , Set
    Cls

    Lcd "zaprog. czujniki"
    Locate 2 , 15
    Lcd Chr(1) ; Chr(2)

    Bitwait P_ok , Reset
    Waitms 25
    Bitwait P_ok , Set
    Cls
    Flaga(1) = 0
    Flaga(2) = 1




       Do

       Call Odczyt_temperatury(1)
       Locate 1 , 1
       Lcd "czujnik1: " ; Fusing(temp_pieca , "#.#") ; Chr(0) ; " "


       If P_gora = 0 Then
          Waitms 25

             If P_gora = 0 Then
                Flaga(2) = Flaga(2) + 1
                   If Flaga(2) = 4 Then
                      Flaga(2) = 1
                   End If
                'Bitwait P_ok , Set
             End If
        End If


       If P_dol = 0 Then
          Waitms 25

             If P_dol = 0 Then
                Flaga(2) = Flaga(2) - 1
                   If Flaga(2) = 0 Then
                      Flaga(2) = 3
                   End If
                'Bitwait P_ok , Set
             End If
        End If
    Indeks = Flaga(2) - 1
    Locate 2 , 1
    Lcd Lookupstr(indeks , Sdata) ; Chr(3)
    Locate 2 , 15
    Lcd Chr(1) ; Chr(2)


       If P_ok = 0 Then
          Waitms 25

             If P_ok = 0 Then
                Wyjscie = 1
                Bitwait P_ok , Set
             End If


       End If

       Loop Until Wyjscie = 1
       Id(9) = Flaga(2)
       Writeeeprom Id(9) , 9
       Flaga(1).flaga(2) = 1
       Wyjscie = 0

       Do

       Call Odczyt_temperatury(2)
       Locate 1 , 1
       Lcd "czujnik2: " ; Fusing(temp_pieca , "#.#") ; Chr(0) ; " "


       If P_gora = 0 Then
          Waitms 25

             If P_gora = 0 Then
                Flaga(2) = Flaga(2) + 1
                   If Flaga(2) = 4 Then
                      Flaga(2) = 1
                   End If
                'Bitwait P_ok , Set
             End If
        End If


       If P_dol = 0 Then
          Waitms 25

             If P_dol = 0 Then
                Flaga(2) = Flaga(2) - 1
                   If Flaga(2) = 0 Then
                      Flaga(2) = 3
                   End If
                'Bitwait P_ok , Set
             End If
        End If

        If Flaga(1).flaga(2) = 1 Then
           Flaga(2) = Flaga(2) + 1
        End If

        If Flaga(2) = 4 Then
           Flaga(2) = 1
        End If

    Indeks = Flaga(2) - 1
    Locate 2 , 1
    Lcd Lookupstr(indeks , Sdata) ; Chr(3)
    Locate 2 , 15
    Lcd Chr(1) ; Chr(2)



       If P_ok = 0 Then
          Waitms 25

             If P_ok = 0 Then
                Wyjscie = 1
                Bitwait P_ok , Set
             End If


       End If

       Loop Until Wyjscie = 1

       Id(9) = Flaga(2)
       Writeeeprom Id(9) , 18
       Wyjscie = 0
       Flaga(1).flaga(2) = 1

     For Indeks = 1 To 3
       If Flaga(1).indeks = 0 Then
       Flaga(2) = Indeks
       End If
    Next Indeks

    Cls
       Do


       Call Odczyt_temperatury(3)
       Locate 1 , 1
       Lcd "czujnik3: " ; Fusing(temp_pieca , "#.#") ; Chr(0) ; " "

       Indeks = Flaga(2) - 1
       Locate 2 , 1
    Lcd Lookupstr(indeks , Sdata)
    Locate 2 , 15
    Lcd Chr(1) ; Chr(2)


       If P_ok = 0 Then
          Waitms 25

             If P_ok = 0 Then
                Wyjscie = 1
                Bitwait P_ok , Set
             End If
       End If

       Loop Until Wyjscie = 1

       Id(9) = Flaga(2)
       Writeeeprom Id(9) , 27
       Wyjscie = 0
       Cls
    End Sub


    Sub Odczyt_temperatury(byref Konfig As Byte)                'jeśli parametr =0 odzytuje wszystkie czujniki, jeśli 1 to
                                                                 'pierwszy czujnik jeśli 2 to drugi itd.
    Dim Odczyt(2) As Byte
    Local T As Integer
    Dim Temp As Single
    Local L As Byte
       '1wverify Id(1)

       1wreset                                                  'wybranie czujnika poprzez zapis do niego jego nr id
       1wwrite &HCC                                             'start pomiaru przez układ dla wszystkich czyjnikow
       1wwrite &H44

       Waitms 750                                               'opóźnienie na czas pomiaru


       For L = 1 To 3


                 If Konfig = 1 Then                             'dla potrzeb konfiguracji, odczyt tylko z wybranego czujnika
                  L = 1
                    End If


                 If Konfig = 2 Then
                  L = 2
                    End If


                 If Konfig = 3 Then
                  L = 3
                    End If


    Select Case L

       Case 1:
                For I = 1 To 9
                Readeeprom Id(i) , I
                Next I

       Case 2:
                J = 1
                For I = 10 To 18
                Readeeprom Id(j) , I
                Incr J
                Next I

       Case 3:
                J = 1
                For I = 19 To 27
                Readeeprom Id(j) , I
                Incr J
                Next I

       End Select

                                                                 'reset magistrali 1-wire
       1wreset
       1wwrite &H55
       1wverify Id(1)                                           'wybranie czujnika poprzez zapis do niego jego nr id

       1wwrite &HBE                                             'komenda odczytu układu

       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

       Temp = T * 0.0625

             If Konfig = 0 Then

    Select Case Id(9)
       Case 1:
              Temp_pieca = Temp
       Case 2:
              Temp_wymiennika = Temp
       Case 3:
              Temp_zewnetrzna = Temp


      Case Else:
                 Cls
                 Lcd "Skonfiguruj"
                 Lowerline
                 Lcd "czujniki"
                 Locate 2 , 15
                 Lcd Chr(1) ; Chr(2)

                 Bitwait P_ok , Reset
                 Waitms 25
                 Bitwait P_ok , Set

                 Gosub Konfiguracja_czujnikow

    End Select
            Else

              L = 3                                             'gdy parametr różny od zera, dla potrzeb konfiguracji czujnikó
              Temp_pieca = Temp
                                                                'wszystkie odczyty zapisuje pod zmienną Temp_pieca
            End If



          Next L



    End Sub








    Odmierz_1s:

    Load Timer0 , 125
    Incr Licz_8ms

    If Licz_8ms = 125 Then
    'Incr Sekundy

    Licz_8ms = 0

     End If
     Return


    Sdata:
    Data "PIEC       " , "WYMIENNIK  " , "ZEWNETRZNY "


    Po wyłączeniu przerwań wszystko działa prawidłowo
  • Poziom 14  
    Bez listingu kodu i schematu nikt się nie domyśli co jest nie tak :) No, chyba że etatowe wróżki zaglądają na forum.
  • Poziom 29  
    Na czas komunikacji 1wire musisz wyłączaś przerwania od timer0 (albo go zatrzymywać) bo właśnie to jest przyczyną.
    Code:

    Sub Odczyt_temperatury(byref Konfig As Byte)                'jeśli parametr =0 odzytuje wszystkie czujniki, jeśli 1 to
                                                                 'pierwszy czujnik jeśli 2 to drugi itd.
    Dim Odczyt(2) As Byte
    Local T As Integer
    Dim Temp As Single
    Local L As Byte
       '1wverify Id(1)
     
    disable timer0

       1wreset                                                  'wybranie czujnika poprzez zapis do niego jego nr id
       1wwrite &HCC                                             'start pomiaru przez układ dla wszystkich czyjnikow
       1wwrite &H44

    enable timer0

       Waitms 750                                               'opóźnienie na czas pomiaru


       For L = 1 To 3


                 If Konfig = 1 Then                             'dla potrzeb konfiguracji, odczyt tylko z wybranego czujnika
                  L = 1
                    End If


                 If Konfig = 2 Then
                  L = 2
                    End If


                 If Konfig = 3 Then
                  L = 3
                    End If


    Select Case L

       Case 1:
                For I = 1 To 9
                Readeeprom Id(i) , I
                Next I

       Case 2:
                J = 1
                For I = 10 To 18
                Readeeprom Id(j) , I
                Incr J
                Next I

       Case 3:
                J = 1
                For I = 19 To 27
                Readeeprom Id(j) , I
                Incr J
                Next I

       End Select


    disable timer0
                                                                 'reset magistrali 1-wire
       1wreset
       1wwrite &H55
       1wverify Id(1)                                           'wybranie czujnika poprzez zapis do niego jego nr id

       1wwrite &HBE                                             'komenda odczytu układu

    enable timer0

       Odczyt(1) = 1wread(2)                                    'odczytaj dwa pierwsze bajty
  • Poziom 12  
    Niestety nie pomaga, jeśli tylko fragment procedury przechodzi z włączonym przerwaniem już się dzieją cuda,a wszystko wraca do normy gdy wyłączę przerwanie na czas wykonania całej procedury.Ale co mi z takiego timera gdzie większość czasu będzie wyłączony
  • Poziom 32  
    A kto powiedział że musisz go wyłączać? Istnieje lepszy sposób: robisz sobie flagę którą resetujesz w pzrerwaniu od timera. Potem wystarczy dodać coś takiego:
    Code:
    Set Flaga : While Flaga = 1 : Wend  
    Takie coś wstawiasz tam gdzie wcześniej musialeś wyłączać przerwania. Działa to tak że uc czeka aż wykona się przerwanie i dzięki temu wiemy że miało ono miejsce a co za tym idzie mamy jeszce czas do kolejnego.

  • Poziom 28  
    Miałem podobny kłopot którego przyczyną było włączenie optymalizacji kodu wynikowego.

    Sugerowałbym spojrzeć na taka możliwośc jeszcze.

    pozdrawiam
    Marek
  • Poziom 12  
    dziękuję bardzo za zainteresowanie, jednak problemu w żaden sposób rozwiązać nie mogę. Przy zastosowaniu pomysły z pętlą przed przerwaniem i wyłączeniu optymalizacji program zachowuje się stabilnie jednak temperatury nie pokazuje. Dziwi mnie rzecz, że po włączeniu przerwań funkcja 1wirecount() zawsze zwraca 0(mimo zastosowania bezpośrednio przed nią pętli), odczyt id działa poprawnie i nie odczytuje poprawnie temp.
    Muszę przyznać że ręce mi już opadają. Może posiada, ktoś podobny działający program który mógłbym sprawdzić w moim układzie.
    Pozdrawiam

    Przy okazji zapytam jeszcze czy mały brzęczyk piezo mogę podłączyć bezpośrednio do uC czy muszę przez tranzystor( nie chcę mi się lutować bo miejsca na płytce mało)
  • Poziom 14  
    witam. dziś także juz nerwa złapałem z tym timer0 i wierzyłem ze na elektrodzie będzie jakieś rozwiązanie, ale z tego co czytam nie tylko ja tak mam;/ .wracając do tematu:

    1.próbowałeś zmienić port dla 1-wire?

    2.jesli problemem jest już zamiana pinów to być może załączenie timer1 pomoże i na nim odliczanie sekundy,przykładowe uruchomienie:
    Code:
    Config Timer1 = Timer , Prescale = 1024                     'Prescale = 1 | 8 | 64 | 256 | 1024
    

    On Timer1 Label                                             'po przepełnieniu licznik skoczy do etykiety LABEL

    Load Timer1 , 15625                                         'załadowanie liczby 100 do TIMER1, po zliczeniu której licznik się przepełni

    Enable Timer1                                               'włączamy przerwania licznika
    Enable Interrupts                                           'włączamy globalny system przerwań

    Dim J As Byte


    Cls

    'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX GŁÓWNY PROGRAM XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    Do

    Locate 1 , 1
    Lcd "    J = " ; J ; "    "

    'Locate 2 , 1
    'Lcd "   TNCT1 = " ; Tcnt1 ; "   "

    Loop

    End

    Label:
    Load Timer1
    Incr J
    Return

    ja wykorzystałem timer1 już w innym celu wiec musze inaczej kombinować. mam nadzieje ze to choć trochę pomoże.

    pozdrawiam
  • Poziom 12  
    pin już próbowałem zmieniać, ale nie pomogło, z timerem1 też próbowałem i również kicha, ale spróbuję jeszcze raz
  • Poziom 27  
    kolego moge tylko zyczyc uporu i zmyslu analitycznego niestety za ceibie nikt tego nie zrobi a na forum znajdziesz napeno sciezki ktorymi podazac to takze jest pomoc. osobiscie radze zakupic jtag-a zminic procka na taki ktory on obsluguje a analiza bledow bedzie zdecydowanie latwiejsza. brzeczyk bym jednak podlaczyl przez tranzystor bo to zawsze odciaczy koncowke od niepotrzebnych amperow;)