Elektroda.pl
Elektroda.pl
X
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

[Atmega8][Bascom] 2xDS18b20 3x2Wyś.7seg.LED odbiór danych

siwekyhy 05 Jan 2012 02:10 2990 11
  • #1
    siwekyhy
    Level 14  
    Witam

    Testuje termometr na dwóch Ds18b20 i żeby wynik wyświetlany był trzech wyświetlaczach 7seg. LED. Ma działać tak że najpierw pokazuje na 3 sekundy 1 temperaturę a po tym czasie na kolejne 3 sekundy pokazuje 2 temperaturę. Linie 1 wire podciągnąłem z rezystorem 3,3K do +5V. Wszystko działa temperatury się zmieniają i wyświetlają ale co jakiś czas pokazuje mi same 0 0 0 na wyświetlaczach w czym może być problem ? Wprowadziłem także czas przynajmniej 760ms i nawet więcej na przetwarzanie danych. Załączam kod programu w bascom, fragmenty programu pochodzą z forum lub książki.




    Code: vbnet
    Log in, to see the code


    Może coś w głównej pętli jest coś nie tak ?

    pozdrawiam
  • #2
    techno-mp3
    Level 12  
    Tak na szybko, to powinieneś dorzucić do przerwania jakąś zmienną którą możnaby inkrementować i obliczyć ile takich inkrementacji jest potrzebne dla konwersji danych dla ds18b20. Potrzebujesz 750ms o ile się nie mylę, więc lepiej to dorzucić do przerwania niż stosować WAIT 1. Zlicz ilość przerwań aby Ci wyszło >750ms i daj IF'a dla odczytu DS'a. Z Wait zawsze miałem problemy. Pozdrowionka!
  • #3
    siwekyhy
    Level 14  
    Nie do końca wiem o co Ci chodzi , hm mógłbyś jakiś przykład dać? Myślałem jeszcze o użyciu pamięci EEPRom tylko pewnie na długo by nie wystarczyła zapis/odczyt przy codziennym użytkowaniu
  • #4
    emarcus
    Level 38  
    siwekyhy wrote:

    Nie do końca wiem o co Ci chodzi , hm mógłbyś jakiś przykład dać? Myślałem jeszcze o użyciu pamięci EEPRom tylko pewnie na długo by nie wystarczyła zapis/odczyt przy codziennym użytkowaniu


    Chodzi mu o to abyś nie blokował processora liczeniem czasu (te Waitms 750 czy 780 ms). AVR jest 'single task' processor i nie może wykonywać więcej niż 1 czynności jednocześnie. Więc albo obsługuje sekwencje programu, albo liczy te twoje "Waitms". W sekwencji programu masz komunikacje z czujnikami temperatury, interpretacje odczytów, obsługe display oraz 'pomoc' dla timera0 liczyć te 4ms w postaci: - kazdorazowo 'preload timer0'.
    Wyjście z sytuacji jest proste: Uwarunkuj komunikacje z czujnikami DS stawianiem jakiejs flagi, którą po wykorzystaniu będziesz zerował, a stawiana byłaby po osiągnięciu pewnej wartości dodatkowj zmienej incrementowanej w subrutynie Ovf0.
    Praktycznie: Jeżeli Ovf0 wystepuje co 4 ms to do zmienej tej potrzebujesz zliczyć 250 przepełnień (będzie to 1 sec), (if...then) postaw flagę i wyzeruj zmienną aby zacząc liczyć następną sekundę. W międzyczasie czujniki temperatury są gotowe z wynikami.

    e marcus
  • #5
    siwekyhy
    Level 14  
    Hmm dalej nie kumam do końca o co chodzi jestem początkujący ... Znalazłem taki program w książce do odmierzania 1 s tylko jak to do mojego programu dołączyć


    Code: vbnet
    Log in, to see the code
  • #6
    arktik1
    Level 27  
    Robisz np. tak:

    Code: vbnet
    Log in, to see the code

    Takim sposobem będziesz miał odczyt co 800ms, w zupełności wystarczy.
    Dlatego że czekajnads =8 X 100ms = 800ms.
    Możesz zmniejszyć jeszcze WAITMS w pętli do 10ms, ale wtedy musisz zwiększyć czekajnads do 80.
  • #7
    techno-mp3
    Level 12  
    A pozatym z mojego doświadczenia wynika, że instrukcji dla przerwania powinno być minimum z minimum. Tak jak kolega podpowiada, radziłbym stosować flagi. Czyli ustawiasz inkrementujesz lub ustawiasz zmienne w kodzie przerwania, a resztę robisz w pętli do-loop. Po co marnować cenny czas na robienie niczego (wait). Skoro jestes "świerzak" ( nie obraź się , każdy był, ja też), to kup sobię książkę Marcina Wiązani, Programowanie AVR w BASCOM. Ja kupiłem i dużo mi to dało, wiele można się nauczyć. Miłego długiego weekendu!!!!
  • #8
    Flaman11
    Level 17  
    Przy dołączonych peryferiach 1wire jest pewna przeszkoda w komunikacji. Należy na czas komunikacji z układem wyłączyć timer( czyli zatrzymać odmierzanie czasu, sam sprawdź na czas komunikacji zrób disable timer0, a po zakończeniu komunikacji enable timer0). Dlatego do odmierzania czasu powinieneś wykorzystać timer w trybie asynchronicznym, np.:
    Config Timer2 = Timer , Async = On , Prescale = 128
    Nie wszystkie mikrokontrolery posiadają ten tryb. Należy również w zależności od użytego mikrokontrolera podłączyć dodatkowy kwarc lub przełączyć uC na wewnętrzny rezonator.

    Wykorzystujesz Mega8, więc konfiguracja timer'a powyżej, przełączasz mega na domyślny rezonator( wewnętrzny 1MHz), a na miejscu kwarcu 8MHz wkładasz 32kHz(zegarkowy).
  • #9
    siwekyhy
    Level 14  
    Widzę że nie ja jeden mam problem z odbiorem danych z ds-ów a wszyscy je polecają hm w zamian można dać jakieś np. Lm35 tylko nie wszystkie mają ujemną temperaturę i są droższe. Będę miał jutro czas to posiedzę jeszcze nad tym programem mam nadzieje że dam rade, w razie czego tu jeszcze napisze.

    Mam książkę M.Wiązania bardzo fajna właśnie fragmenty programów pochodzą z niej. Niedawno kupiłem jeszcze książkę autorstwa M.Kardaś tylko że to jest w języku C jak na razie czarna magia dla mnie ...

    pozdrawiam , dziękuje za odpowiedzi
  • #10
    Flaman11
    Level 17  
    siwekyhy wrote:
    Widzę że nie ja jeden mam problem z odbiorem danych z ds-ów a wszyscy je polecają hm w zamian można dać jakieś np. Lm35 tylko nie wszystkie mają ujemną temperaturę i są droższe. Będę miał jutro czas to posiedzę jeszcze nad tym programem mam nadzieje że dam rade, w razie czego tu jeszcze napisze.

    Mam książkę M.Wiązania bardzo fajna właśnie fragmenty programów pochodzą z niej. Niedawno kupiłem jeszcze książkę autorstwa M.Kardaś tylko że to jest w języku C jak na razie czarna magia dla mnie ...

    pozdrawiam , dziękuje za odpowiedzi


    LM35 mierzy dodatnie jak i ujemne temperatury, w podstawowej wersji przy zasilaniu + zakres wynosi od +2stC do w zależności od modelu 150stC. Natomiast by mierzył temperatury ujemne wymaga napięcia symetrycznego. LM35 jest właśnie tańszy. DS'y są łatwe w obsłudze i omawiane w wielu podręcznikach pewnie dlatego są tak popularne. Poniżej fragment kodu obsługi czujników temperatury i odmierzania 1s:
    Code: vbnet
    Log in, to see the code


    Zwróć uwagę, że w przerwaniu występuje flaga "B", która w pętli głównej programu zezwala na konwersję temperatury dopiero po wyjściu z przerwania TIMER2. By odmierzanie czasu wynosiło 1s należy podłączyć rezonator o wartości 32kHz(zegarkowy), a mikrokontroler przestawić na wewnętrzny rezonator o wartości 1MHz.

    Fragment kodu przedstawia jedynie jak odmierzać czas nie zaburzając komunikacji na szynie 1Wire. Program będzie działał z małym błędem. Pomija sprawdzania nr ID czujników przed konwersją.
  • #11
    emarcus
    Level 38  
    Flaman11 wrote:
    ]

    Poniżej fragment kodu obsługi czujników temperatury i odmierzania 1s:



    Do
    If B = 0 Then
    'Call Pomiar_temp
    A = 1wirecount()

    1wreset
    1wwrite &H55
    1wverify Dsid1(1) 'wysyłamy adres pierwszego czujnika
    1wwrite &HBE
    'Waitms 10
    I1(1) = 1wread(2)

    Loop : End 'end program

    Odmierz_1s:
    Set B
    'JAKIEŚ INSTRUKCJE
    Reset B
    Return



    Źle mu podpowiadasz. Uzależniłeś odczyt temperatury od flagi B=0 (!) Nie byłoby w tym nic złego, bo stan flagi '0' lub '1' może być umowny, ale ten aktualny stan w tym przypadku zerowy będzie sie utrzymywał przez dośc długi czas (prawdopodobnie blisko 1sec. bo coś może trwać pod "jakieś instrukcje") co pozwoli na wielokrotne 'przewijanie" pętli a w niej kazdorazowo realizowanie instrukcji warunkowej "Call pomiar temp" bo warunek "IF..." zostaje spełniony. Jemu potrzeba odczytać temperatury tylko jeden raz, i tylko wtedy gdy są gotowe po conversji.
    Inna usterka to nie ma potrzeby odczytu w Do... Loop wartości:
    "A = 1wirecount()
    nigdzie tego nie wykorzystujesz(!)
    inna:
    1wwrite &H55
    1wverify Dsid1(1) 'wysyłamy adres pierwszego czujnika

    - podwójnie ta sama commenda: '1wverify.....' zawiera w sobie tą powyżej.

    Pod koniec bloku "IF...." masz dla wszystkich DS commendę "ConvertT" -co jest OK; ale ponieważ pozwalasz na ciągły odczyt temperatury, to prawidłowy pomiar będzie tylko ten pierwszy, który bardzo szybko zostanie nadpisany błędami.

    Poza tym rozwiazanie z Timerem2 i ten przykład, nawet poporawnie napisany nie eliminuje ewentualności wystąpienia interruptu od Timera0 podczas komunikacji z DS. Timer0 obsługuje multiplexing 3x7 segm. LED display.

    e marcus
  • #12
    Flaman11
    Level 17  
    emarcus wrote:


    Źle mu podpowiadasz. Uzależniłeś odczyt temperatury od flagi B=0 (!) Nie byłoby w tym nic złego, bo stan flagi '0' lub '1' może być umowny, ale ten aktualny stan w tym przypadku zerowy będzie sie utrzymywał przez dośc długi czas (prawdopodobnie blisko 1sec. bo coś może trwać pod "jakieś instrukcje") co pozwoli na wielokrotne 'przewijanie" pętli a w niej kazdorazowo realizowanie instrukcji warunkowej "Call pomiar temp" bo warunek "IF..." zostaje spełniony. Jemu potrzeba odczytać temperatury tylko jeden raz, i tylko wtedy gdy są gotowe po conversji.
    Inna usterka to nie ma potrzeby odczytu w Do... Loop wartości:
    "A = 1wirecount()
    nigdzie tego nie wykorzystujesz(!)
    inna:
    1wwrite &H55
    1wverify Dsid1(1) 'wysyłamy adres pierwszego czujnika

    - podwójnie ta sama commenda: '1wverify.....' zawiera w sobie tą powyżej.

    Pod koniec bloku "IF...." masz dla wszystkich DS commendę "ConvertT" -co jest OK; ale ponieważ pozwalasz na ciągły odczyt temperatury, to prawidłowy pomiar będzie tylko ten pierwszy, który bardzo szybko zostanie nadpisany błędami.

    Poza tym rozwiazanie z Timerem2 i ten przykład, nawet poporawnie napisany nie eliminuje ewentualności wystąpienia interruptu od Timera0 podczas komunikacji z DS. Timer0 obsługuje multiplexing 3x7 segm. LED display.

    e marcus


    Stan zerowy jak i stan 1 zmiennej B będzie się utrzymywał przez dokładnie jedną sekundę( To jest czas na konwersję). Masz rację, że przeliczenie temp. można podciągnąć do konwersji, ale też nie ma znowu takiego przymusu. Co z tego, że temperatura jest przeliczana częściej niż konwersja? TIMER2 jest zamiast TIMER0 i on przejmie pracę multipleksera i odmierzania 3 sekund(TIMER0 należy usunąć z programu). Co do czasu odświeżania, wystarczy, że wpiszemy wartość licznika 255, więc przerwanie będzie wynosiło około 3ms, więc o 1ms krócej niż autor zrealizował na TIMER0.

    Proszę Cię czytaj posty w całości. Przecież napisałem, że wystąpi błąd w wyświetlaniu prawidłowej temperatury z jednego z czujników przez brak weryfikacji nr ID.

    "A = 1wirecount()
    Kod jest fragmentem jedynie jakiegoś większego programu, usunąłem to co było niepotrzebne, tej funkcji nie zauważyłem i dlatego tu jest.