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.

Termostat ATMEGA8 Bascom - problem z histerezą

Marek_RADOM 20 Dec 2007 01:35 9465 14
  • #1
    Marek_RADOM
    Level 18  
    Witam mam zamiar zrobić termostat na ATMEGA8 + LCD 2x16 (testowo mam 2x24) i DS18B20. Napisałem program, wgrałem go dla sprawdzenia do mojego zegarka z budzikiem i zamiast przekaźnika załącza mi buzzer. Jedyne 2 problemy jakie napotkałem to problem ze zrobieniem histerezy, tak aby nie włączało mi co chwilę przekaźnika. Chcę aby histereza wynosiła 0,5°C. Jeśli chodzi o histerezę to na pisałem tak:

    Code:
    Dim Temp As Integer
    
    Dim Tzad As Integer
    Dim Hist As Integer

    Hist = Temp + 5

    'Głowna pętla z odczytem i wyświetleniem temperatury
       If Tzad > Hist Then
        Set Pk
       End If

       If Tzad <= Temp Then
        Reset Pk
       End If

    'Koniec


    Problem w tym, że histereza jakby jest nieaktywna, po prostu gdy temperatura jest ustawiona przykładowo na 21.0°C to jeśli spadnie na 20.9°C to buzzer jest już załączany.

    Jak temu zaradzić ?

    Jeśli chodzi o drugi problem to nie wiem jak zrobić w ustawieniach kropkę w temperaturze ustawianej, bo mam teraz np. 200 odpowiadające 20,0°C.

    Cały program wygląda tak:
    Code:
    'Termostat pokojowy do Pieca C.O.
    

    $regfile = "m8def.DAT"
    $crystal = 8000000

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

    Config Portb = Output
    Config Pinc.0 = Output
    Config Pind.1 = Input
    Config Pind.2 = Input
    Config 1wire = Portd.5

    Dim Temp As Integer , Ss As String * 6
    Dim Tzad As Integer
    Dim Dsid As Byte
    Dim Hist As Integer


    Deflcdchar 0 , 8 , 20 , 11 , 4 , 4 , 4 , 3 , 32             'znak stopnia Celcjusza

    Portd.1 = 1 : K1 Alias Pind.1                               'Podciągnięcie portów do 1 dla obsługi klawitury
    Portd.2 = 1 : K2 Alias Pind.2

    Pk Alias Portc.0

    Hist = Temp + 5
    Tzad = 200

    Writeeeprom Tzad , 0

    Cursor Off
    Cls

    Lcd " Termostat do pieca C.O."
    Wait 2
    Cls


    Pomiar:

    Do



       1wreset
       1wwrite &H55
       1wverify Dsid
       1wwrite &HBE
       Temp = 1wread(2)

       1wreset
       1wwrite &HCC
       1wwrite &H44

    Wait 2

       Temp = Temp * 10
       Temp = Temp / 16
       Ss = Str(temp)
       Ss = Format(ss , "0.0")

       Cls

       Locate 1 , 1

       Lcd "Temperatura:"

       Locate 1 , 14

       Lcd ; Ss ; Chr(0) ;

       If K1 = 0 Then
        Wait 2
        If K1 = 0 Then
         Readeeprom Tzad , 0
         Goto Ustaw_t
        End If
       End If

       Readeeprom Tzad , 0

       If Tzad > Hist Then
        Set Pk
       End If

       If Tzad <= Temp Then
        Reset Pk
       End If




    Loop                                                        'Pętla (koniec programu)



    Ustaw_t:

       Cls
       Locate 1 , 1
       Lcd " Ustawienie temperatury "

       Locate 2 , 2
       Lcd "zadanej"

       Locate 2 , 10

       Lcd Tzad ; Chr(0)


       Waitms 300
       If K2 = 0 Then
       Tzad = Tzad + 5
        If Tzad = 400 Then
         Tzad = 0
        End If
       End If

       Waitms 300
       If K1 = 0 Then
       Writeeeprom Tzad , 0
       Goto Pomiar
       End If

    Goto Ustaw_t
  • #2
    dawid512
    Level 32  
    Witam masz tutaj programik do histerezy moze Ci pomorze :D

    Code:

    $regfile = "m32def.dat"
    $crystal = 8000000

    Config Lcdbus = 4
    Config Lcd = 16 * 2
    Config Lcdpin = Pin , Db4 = Pb.4 , Db5 = Pb.5 , Db6 = Pb.6 , Db7 = Pb.7 , E = Pb.3 , Rs = Pb.2

    Config 1wire = Portb.0
    Config Portd.0 = Output

    Declare Sub Odcz_temp
    Dim Temperatura(2) As Byte

    Deflcdchar 0 , 7 , 5 , 7 , 32 , 32 , 32 , 32 , 32

    Dim Temp As Byte
    Dim A1 As Byte
    Dim A2 As Byte
    Dim B As Bit
    Dim H As Byte
    Dim T1 As Byte


    T1 = 35                                                     'Temperatura ktora ma byc utrzymywana w zbiorniku dzieki zalaczaniu i wylaczaniu grzalki


    Portd.0 = 1                               'port grzalki


    Do


    Temp = Temperatura(1)


    Cursor Off
    Call Odcz_temp

    Cls

    If Temperatura(2) = 0 Then

    Lcd "Temp: " ; Temperatura(1) ; Chr(0) ; "C"

    Else

    Lcd "Temp: -" ; Temperatura(1) ; Chr(0) ; "C"

    End If

    H = 2                                                       'Histereza
    Waitms 100


    H = H / 2
    A1 = T1 - H
    A2 = T1 + H


    If Temp <= A1 Then
    Portd.0 = 0
    End If

    If Temp >= A2 Then
    Portd.0 = 1


    End If






    Loop

    End

    Sub Odcz_temp

    1wreset
    1wwrite &HCC
    1wwrite &H44

    Waitms 750

    1wreset
    1wwrite &HCC
    1wwrite &HBE

    Temperatura(1) = 1wread(2)

    1wreset

    If Err = 1 Then

    Cls
    Lcd "Brak ukladu"

    Do

    Loop

    End If

    If Temperatura(2) > 0 Then

    Temperatura(1) = 256 - Temperatura(1)

    End If

    Temperatura(1) = Temperatura(1) / 2

    End Sub

































  • Helpful post
    #3
    jacobsek
    Level 22  
    Witam.
    Problem z histerezą polega na tym że histerezę ustalasz w liniach wykonywanych tylko raz po starcie procka, dlatego ona zawsze będzie wynosić 0+5 (zmienna przechowująca temperaturę zmierzoną po starcie programu będzie 0).
    zmienną histerezy musisz umieścić w pętli aby byłą aktualizowana cały czas wraz ze zmianą temperatury.

    Pozdrawiam
  • #4
    Marek_RADOM
    Level 18  
    jacobsek wrote:
    Witam.
    Problem z histerezą polega na tym że histerezę ustalasz w liniach wykonywanych tylko raz po starcie procka, dlatego ona zawsze będzie wynosić 0+5 (zmienna przechowująca temperaturę zmierzoną po starcie programu będzie 0).
    zmienną histerezy musisz umieścić w pętli aby byłą aktualizowana cały czas wraz ze zmianą temperatury.

    Pozdrawiam


    Dzięki za rozwiązanie tego problemu, już działa poprawnie, tylko co z podprogramem (ustawieniem temperatury zadanej) nie wiem w jaki sposób umieścić kropkę między cyfry.
  • #5
    jacobsek
    Level 22  
    Poszperaj w pliku pomocy do bascoma (1.11.7.4), zwróć uwagę na funkcję fusing(), format()
    Pozdrawiam.
  • #6
    Marek_RADOM
    Level 18  
    Zrobiłem wczoraj sam, wzorowałem się na wyświetlaniu temperatury odczytanej z czujnika. Nie zamykam tematu, bo może się komuś przydać.
  • #7
    j4rek
    Level 19  
    To może wrzuć gotowy działający kod, niejednemu pewnie się przyda ;)
  • #8
    Marek_RADOM
    Level 18  
    j4rek wrote:
    To może wrzuć gotowy działający kod, niejednemu pewnie się przyda ;)


    Niema problemu, gdyby ktoś oprócz mnie go testował i miał jakieś pomysły na zmiany to pisać. Aha program póki co ma obsługę tylko 2 przycisków i niema jeszcze opcji zmniejszana temperatury, ale zrobię to jak już wykonam płytkę i polutuje wszystko.

    Code:

    'Termostat pokojowy do Pieca C.O.

    $regfile = "m8def.DAT"
    $crystal = 8000000

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

    Config Portb = Output
    Config Pinc.0 = Output
    Config Pind.1 = Input
    Config Pind.2 = Input
    Config 1wire = Portd.5

    Dim Temp As Integer , Ss As String * 6
    Dim Tzad As Integer , Tzadana As String * 6
    Dim Dsid As Byte
    Dim Hist As Integer


    Deflcdchar 0 , 8 , 20 , 11 , 4 , 4 , 4 , 3 , 32             'znak stopnia Celcjusza
    Deflcdchar 1 , 28 , 8 , 8 , 8 , 5 , 5 , 5 , 7               'ikonka ustawionej temperatury

    Portd.1 = 1 : K1 Alias Pind.1                               'Podciągnięcie portów do 1 dla obsługi klawitury
    Portd.2 = 1 : K2 Alias Pind.2

    Pk Alias Portc.0

    Tzad = 200

    Writeeeprom Tzad , 0

    Cursor Off
    Cls

    Lcd "   Termostat    "
    Lowerline
    Lcd "  do pieca C.O. "
    Wait 2
    Cls


    Pomiar:

    Do

    Hist = Temp + 5

       1wreset
       1wwrite &H55
       1wverify Dsid
       1wwrite &HBE
       Temp = 1wread(2)

       1wreset
       1wwrite &HCC
       1wwrite &H44

    Wait 2

       Temp = Temp * 10
       Temp = Temp / 16
       Ss = Str(temp)
       Ss = Format(ss , "0.0")

       Tzadana = Str(tzad)
       Tzadana = Format(tzadana , "0.0")

       Readeeprom Tzad , 0

       Cls

       Locate 1 , 1

       Lcd "Temperatura:"

       Locate 1 , 14

       Lcd ; Ss ; Chr(0) ;

       Locate 2 , 11

       Lcd ; Chr(1) ; ":"
       Locate 2 , 14
       Lcd ; Tzadana ; Chr(0)

       If K1 = 0 Then
        Wait 2
        If K1 = 0 Then
         Readeeprom Tzad , 0
         Reset Pk
         Goto Ustaw_t
        End If
       End If

       Readeeprom Tzad , 0

       If Tzad > Hist Then
        Set Pk
        Locate 2 , 1
        Lcd "Grzanie"
       End If

       If Tzad <= Temp Then
        Reset Pk
       End If




    Loop                                                        'Pętla (koniec programu)



    Ustaw_t:

       Cls
       Locate 1 , 1
       Lcd " Ustawienie temperatury "

       Locate 2 , 2
       Lcd "zadanej"


       Tzadana = Str(tzad)
       Tzadana = Format(tzadana , "0.0")

       Locate 2 , 10

       Lcd Tzadana ; Chr(0)


       Waitms 300
       If K2 = 0 Then
       Tzad = Tzad + 5
        If Tzad = 400 Then
         Tzad = 0
        End If
       End If

       Waitms 300
       If K1 = 0 Then
       Writeeeprom Tzad , 0
       Goto Pomiar
       End If

    Goto Ustaw_t
  • #9
    jacobsek
    Level 22  
    Witam.

    Czasami komórka pamięci o adresie 0 może zostać nadpisana przy rozbudowie programu, lepiej używaj pierwszego adresu o nr.1 do eepromu.
    W sprawdzaniu stanu przycisku dałeś wait2 (2s), to nie za długi czas?, standardowo aby wyeliminować drgania zestyków wystarczy czas 20-30 mS.
    Jeszcze jedna uwaga, pisząc bardziej rozbudowane programy unikaj polecenia goto, stosuj zawsze gosub, lub wywołaj procedurę poleceniem call, to unikniesz trudnych do wyłapania błędów w działaniu bardziej rozbudowanych kodów, sądzę że powinieneś już na tym etapie oduczyć się polecenia goto.
    Pozdrawiam
  • #10
    Marek_RADOM
    Level 18  
    jacobsek wrote:
    Witam.

    Czasami komórka pamięci o adresie 0 może zostać nadpisana przy rozbudowie programu, lepiej używaj pierwszego adresu o nr.1 do eepromu.
    W sprawdzaniu stanu przycisku dałeś wait2 (2s), to nie za długi czas?, standardowo aby wyeliminować drgania zestyków wystarczy czas 20-30 mS.
    Jeszcze jedna uwaga, pisząc bardziej rozbudowane programy unikaj polecenia goto, stosuj zawsze gosub, lub wywołaj procedurę poleceniem call, to unikniesz trudnych do wyłapania błędów w działaniu bardziej rozbudowanych kodów, sądzę że powinieneś już na tym etapie oduczyć się polecenia goto.
    Pozdrawiam


    Dzięki za rade, zmienię tą komórkę pamięci jak będe juz robił układ, a co do tego czasu 2s to dałem celowo to, tylko do wejścia .w ustawienie temperatury, ale zastanawiam się nad skróceniem tego czasu.


    Dziś już zrobiłem testy na LCD 2x16 i mam jeszcze jeden problem z wyświetlaniem stanu przekaźnika i napisu "Grzanie". Jeśli chodzi o sam napis to przy ustawionej przykładowo temperaturze 25,5°C i histerezie 0,5
    °C gdy temperatura przekroczy 25°C to napis Grzanie znika, a przekaźnik nadal jest załączony i działa poprawnie, nie rozumiem dlaczego tak się dzieję skoro "set Pk" i Lcd "grzanie" są w jednej pętli. A jeśli chodzi o wyświetlanie stanu przekaźnika to ikonka przekaźnika jeszcze inaczej się pokazuje. Wrzucam program na razie z samym napisem "Grzanie", bo taki aktualnie mam wgrany.
    Code:

    'Termostat pokojowy do Pieca C.O.

    $regfile = "m8def.DAT"
    $crystal = 8000000

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

    Config Portb = Output
    Config Portc = &B1000011
    Config 1wire = Portc.5

    Dim Temp As Integer , Ss As String * 6
    Dim Tzad As Integer , Tzadana As String * 6
    Dim Dsid As Byte
    Dim Hist As Integer


    Declare Sub Pomiar
    Declare Sub Ustaw_t


    Deflcdchar 0 , 8 , 20 , 11 , 4 , 4 , 4 , 3 , 32             'znak stopnia Celcjusza
    Deflcdchar 1 , 28 , 8 , 8 , 8 , 5 , 5 , 5 , 7               'ikonka ustawionej temperatury
    Deflcdchar 2 , 32 , 32 , 32 , 32 , 32 , 32 , 31 , 32        ' część ikonki przekaźnika


    Portc.2 = 1 : K1 Alias Pinc.2                               'Podciągnięcie portów do 1 dla obsługi klawitury
    Portc.3 = 1 : K2 Alias Pinc.3
    Portc.4 = 1 : K3 Alias Pinc.4

    Podswietlanie Alias Portc.1

    Pk Alias Portc.0


    Tzad = 200

    Writeeeprom Tzad , 1


    Cursor Off
    Cls

    Lcd "   Termostat    "
    Lowerline
    Lcd "  do pieca C.O. "

    Set Podswietlanie
    Waitms 200
    Reset Podswietlanie
    Waitms 500
    Set Podswietlanie
    Waitms 200
    Reset Podswietlanie
    Waitms 500
    Set Podswietlanie

    Wait 2
    Cls


    Pomiar:

    Do

    Set Podswietlanie

    Hist = Temp + 5

       1wreset
       1wwrite &H55
       1wverify Dsid
       1wwrite &HBE
       Temp = 1wread(2)

       1wreset
       1wwrite &HCC
       1wwrite &H44

    Wait 2

       Temp = Temp * 10
       Temp = Temp / 16
       Ss = Str(temp)
       Ss = Format(ss , "0.0")

       Tzadana = Str(tzad)
       Tzadana = Format(tzadana , "0.0")

       Readeeprom Tzad , 1

       Podswietlanie = 1

       Cls

       Readeeprom Tzad , 1

       If Tzad >= Hist Then
        Set Pk
        Locate 2 , 10
        Lcd "Grzanie"
       End If


       If Tzad < Temp Then
        Reset Pk
       End If

       Locate 1 , 1

       Lcd "T:"

       Locate 1 , 4

       Lcd ; Ss ; Chr(0) ;

       Locate 2 , 1

       Lcd ; Chr(1) ; ":"
       Locate 2 , 4
       Lcd ; Tzadana ; Chr(0)

       Wait 2
       If K1 = 0 Then
        Waitms 30
        If K1 = 0 Then
         Readeeprom Tzad , 1
         Reset Pk
         Call Ustaw_t
        End If
       End If



    Loop                                                        'Pętla (koniec programu)



    Ustaw_t:

       Waitms 150
       Cls
       Locate 1 , 1
       Lcd "Ustawienie temp."

       Locate 2 , 1
       Lcd "zadanej"


       Tzadana = Str(tzad)
       Tzadana = Format(tzadana , "0.0")

       Locate 2 , 9

       Lcd Tzadana ; Chr(0)

       If K2 = 0 Then
        Waitms 150
        If K2 = 0 Then
        Tzad = Tzad + 5
         If Tzad = 500 Then
          Tzad = 0
         End If
        End If
       End If

       If K3 = 0 Then
        Waitms 150
        If K3 = 0 Then
        Tzad = Tzad - 5
         If Tzad = 0 Then
          Tzad = 500
         End If
        End If
       End If

       If K1 = 0 Then
        Waitms 500
        If K1 = 0 Then
        Writeeeprom Tzad , 1
        Reset Podswietlanie
        Waitms 200
        Set Podswietlanie
        Cls
        Locate 1 , 1
        Lcd "Temperatura"
        Locate 2 , 1
        Lcd "ustawiona"
        Wait 1
        Call Pomiar
        End If
       End If

    Goto Ustaw_t
  • #11
    christoo
    Level 10  
    Czy można prosić o schemat do tego termostatu.
  • #12
    slawo1
    Level 14  
    Przetestowałem ten regulatorek działa, jednak ma jeden slaby punkt.
    W punkcie ustalenia wyłaczenia i z powrotem właczania po dojsciu do temperatury zadanej zróżnicowanej histerezą nie ma zdecydowanego przejścia w stan 0 lub 1. Robi się generator klekotanie przekażnikiem jest 01010101. Przy szybkiej zmianie temperatur i małej histerezie np.1 efektu nie ma, wystepuje przy wolnym narastaniu i przy wiekszej histerezie np.2. Może jest osoba która coś doradzi. Zastosowałem histerezę z poniższego kodu.

    Code:

    H = 2                                                       'Histereza
    Waitms 100


    H = H / 2
    A1 = T1 - H
    A2 = T1 + H


    If Temp <= A1 Then
    Portd.0 = 0
    End If

    If Temp >= A2 Then
    Portd.0 = 1


    End If

  • #13
    mloody99
    Level 11  
    Nie wiem czy temat jeszcze aktualny, jeżeli tak to takie rozwiązanie powinno pomóc:


    Temp_hist = Temperatura_dmuchawy - Histereza

    If T >= Temperatura_dmuchawy Then
    Dmuchawa=1 'wyłączona
    Elseif T <= Temp_hist Then
    Dmuchawa=0 'załączona
    End If

    Pozdrawiam
  • #14
    PiotrPitucha
    Level 33  
    Witam
    Przeczytałem o tym klekotaniu i myślę że problem jest w niestabilności odczytu temperatury, ponieważ wszystkie procesy fizyczne są bardzo wolnozmienne w stosunku do szybkości procesora to proponuję czytać np. 64 próbki i usredniać, jeśl ilość próbek będzie potęgą liczby 2 to wystaczy przesunąć wynik w prawo o wartość potęgi i mamy dużo stabilniejszy odczyt temperatury, stosuję to w swoich miernikach temperatury i naocznie widać jakie to przynosi efekty.
    Piotr
  • #15
    patomaniek
    Level 10  
    Witam kolegów, wgrałem sobie ten program od Marek_RADOM do termostatu i mam problem: gdy ustawiam wartość temperatury zadanej to gdy zbliżam się do granicy zakresu ATmega8 zawiesza się, wgrywałem na 3 nowych uP więc o uszkodzeniu nie mam mowy. Przy wartości 49,5 i 1 na wyświetlaczu pojawiają się pomniejszone duże litery H, co to może być?