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

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

siwekyhy 05 Sty 2012 02:10 2744 11
  • #1 05 Sty 2012 02:10
    siwekyhy
    Poziom 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.




    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


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

    pozdrawiam

    0 11
  • Arrow Multisolution Day
  • #2 05 Sty 2012 13:32
    techno-mp3
    Poziom 11  

    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!

    0
  • Arrow Multisolution Day
  • #3 05 Sty 2012 19:22
    siwekyhy
    Poziom 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

    0
  • #4 05 Sty 2012 20:24
    emarcus
    Poziom 35  

    siwekyhy napisał:

    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

    0
  • #5 05 Sty 2012 22:07
    siwekyhy
    Poziom 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ć


    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod

    0
  • #6 05 Sty 2012 23:05
    arktik1
    Poziom 27  

    Robisz np. tak:

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod

    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.

    0
  • #7 06 Sty 2012 00:07
    techno-mp3
    Poziom 11  

    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!!!!

    0
  • #8 06 Sty 2012 18:59
    Flaman11
    Poziom 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).

    0
  • #9 08 Sty 2012 22:48
    siwekyhy
    Poziom 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

    0
  • #10 09 Sty 2012 00:30
    Flaman11
    Poziom 17  

    siwekyhy napisał:
    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:
    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    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ą.

    0
  • #11 09 Sty 2012 05:31
    emarcus
    Poziom 35  

    Flaman11 napisał:
    ]

    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

    0
  • #12 09 Sty 2012 09:54
    Flaman11
    Poziom 17  

    emarcus napisał:


    Ź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.

    0