logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[ATMega8][ASM] Dziwny odczyt z czujnika DS18B20

Bartoneczek 16 Paź 2011 17:57 2793 17
  • #1 10034014
    Bartoneczek
    Poziom 10  
    Witam,

    Mam dziwny problem z odczytem temperatury z czujnika DS18B20. Układ podpiąłem metodą zasilania pasożytniczego, czyli linia zasilania zwarta do masy a do linii DQ podpięte zasilanie 5V z użyciem rezystora podciągającego 4,7 kohm. MCU zaprogramowane tym programem:

    Kod: text
    Zaloguj się, aby zobaczyć kod


    'Debugująca' dioda wskazuje odebranie sygnału Presence od układu slave. Pomijam kod odczytujący ROM funkcją SKIPROM. Obojętnie czy czujnik jest podpięty czy nie, wyświetlacz pokazuje -00, -02 lub -03. Raz tak, raz tak. Niezależnie od panującej temperatury ani innych czynników. Kombinowałem z timingami ale nic to nie zmienia. Funkcje wyświetlające i konwertujące bajty do postaci dla wyświetlacza są sprawdzone i na pewno działają poprawnie. Co może być przyczyną bezwzględnego wyświetlania -00, -02 lub -03?
  • #2 10036124
    asembler
    Poziom 32  
    Zupełnie bez pojęcia. Za dużo reti i sei w ogóle niepotrzebne chyba.
  • #3 10036307
    Ch.M.
    Poziom 27  
    asembler napisał:
    Zupełnie bez pojęcia. Za dużo reti i sei w ogóle niepotrzebne chyba.

    To pierwsze co rzuciło mi się w oczy. Po co te powroty z przerwań, których nigdzie nie ustawiasz :) Po co "SEI", skoro nigdzie nie ma inicjalizacji, których i tak nie obsługujesz wstawiając reti na wektorach przerwań.

    No dobra, może to kod wyczyszczony z pewnych elementów w celi rozjaśnienia kodu :)

    Przejrzyj jeszcze raz procedury odczytu z czujnika. Na bank tam siedzi błąd. Sprawdź sam kontroler czy przypadkiem nie zaprogramowałeś jakiegoś dodatkowego bitu np. div8 (nie pamiętam czy M8 go ma).

    Czemu inicjalizujesz wskaźnik stosu na koniec -3 ??

    Zaraz przejrzę kod dokładniej i może coś znajdę :)

    To co rzuca się w oczy... z jaką częstotliwością pracuje uK? Oscylator RC 1MHz kilka % dokładności może być mało.

    Zmieniasz wejście/wyjście D7 a czy masz zewnętrzny pull up ? Czy ta procedura wogóle jest poprawna:

    SENDBYTE2:
    	ldi r21, 0
     
    	powtorzSendByte2:
    		mov r19, r18
    		lsr r18
    		cbr r19, 0b11111110
     
    		sbi DDRD, 7
     
    		nop
    		nop
    		nop
    		nop
    		nop
     
    		sbrc r19, 0
    		cbi DDRD, 7
     
    		; ============================= 
    		;    delay loop generator 
    		;     80 cycles:
    		; ----------------------------- 
    		; delaying 78 cycles:
    				  ldi  R16, $1A
    		WGLOOP16:  dec  R16
    				  brne WGLOOP16
    		; ----------------------------- 
    		; delaying 2 cycles:
    				  nop
    				  nop
    		; ============================= 
     
     
    		cbi DDRD, 7
     
    		inc r21
    		cpi r21, 8
    		brne powtorzSendByte2
     
    ret

    Wygląda na to, że czekasz 80cykli pomiędzy kolejnymi cbi DDR, 7... troszkę to bez sensu.
    Liczba komentarzy zbyt mała :(
    Nie rozumiem obsługi wszystkich urządzeń, a Ty też kiedyś zapomnisz, przydałby się krótki opis przy procedurkach by wiedzieć jak to ma wyglądać.

    Schemat by się przydał.
  • #4 10036350
    asembler
    Poziom 32  
    Wszystkie "delaje" nalezy uzależniać od częstotliwości kwarzu a z doświadczenia wiem że odczyt DS18b20 mozna uzyskać prawie na dowolnym F oscylatora.
  • #5 10036351
    Bartoneczek
    Poziom 10  
    Tak jak wspomniałeś sei i powroty z przerwań to pozostałości po poprzednim programie. Wyizolowałem tylko to co dotyczy temperatury i sei jakoś tak zostało.

    Nie programowałem żadnych dodatkowych bitów. ;)

    Wskaźnik stosu inicjalizuję na -3 ponieważ RAMEND-2, RAMEND-1 i RAMEND przeznaczam na przechowywanie wartości temperatury, a nie chciałbym żeby stos mi je nadpisał.

    uC pracuje na wbudowanym oscylatorze z częstotliwością 1MHz.

    Swoją drogą zaczynam mieć wątpliwości odnośnie ustawiania portu. Wymuszone 0 na porcie realizuję ustawiając bit DDR na 1 i PORT na 0. W jaki sposób mam realizować podciągnięcie magistrali 1-wire do logicznej 1 przez rezystor zewnętrzny? Wystarczy ustawić port w stan nieustalony (DDR 0, PORT 0)?

    EDIT:

    Odnośnie procedury SENDBYTE2:

    Kod: text
    Zaloguj się, aby zobaczyć kod
  • #6 10036354
    asembler
    Poziom 32  
    Bartoneczek napisał:

    Wskaźnik stosu inicjalizuję na -3 ponieważ RAMEND-2, RAMEND-1 i RAMEND przeznaczam na przechowywanie wartości temperatury, a nie chciałbym żeby stos mi je nadpisał.


    Zapobiegliwość bez sensu.
    Przecież w druga stronę też mozna nadpisać jak juz ktoś taki zdolny.
  • #7 10036371
    Bartoneczek
    Poziom 10  
    asembler napisał:
    Wszystkie "delaje" nalezy uzależniać od częstotliwości kwarzu a z doświadczenia wiem że odczyt DS18b20 mozna uzyskać prawie na dowolnym F oscylatora.


    Jeśli mC jest ustawiony fabrycznie i pracuje z F = 1Mhz to 1 takt = 1 us, więc myślę że opóźnienia akurat pracują tak jak powinny.
  • #8 10036374
    Ch.M.
    Poziom 27  
    No ale gdzie realizujesz tę zmianę zewnętrznym rezystorem i o jakiej wartości??
    Nie widzę nigdzie byś stosował wewnętrzny pull up, nie sterujesz PORTD nigdzie...
    Jaka jest odległość uK od czujnika i jaka pojemność przy czujniku lub uK?
    Schematu brak.....
    Tak jak kolega zauważył nie stosujesz push ani pop więc jak masz nadpisać/nienadpisać stos?
    Jakie wymagane minimalne czasy opóźniej są wg. dokumentacji DS? Dodaj zapas 10% przy opóźnieniach.
    Nadal uważam, że instrukcje send są złe.... zerujesz DDR(czyli ustawiasz 1kę która w zasadzie jest cały czas) czekasz 80ms i dalej ją zerujesz... równie dobrze możesz nie czekać... coś tu jest kiepsko :)
    Nie programowałeś bitów więc spraw czy są takie jakich oczekujesz.
  • #9 10036407
    Bartoneczek
    Poziom 10  
    Ch.M. napisał:
    No ale gdzie realizujesz tę zmianę zewnętrznym rezystorem i o jakiej wartości??


    Wydawało mi się właśnie że realizuję ją przełączając port w stan nieustalony (rezystor 4,7 kohm). Właśnie ciężko jest mi to zrozumieć. Będę wdzięczny za wytłumaczenie jak mam to robić. Starałem się przerabiać kod z C z tego opracowania: Link.


    Załączam schemat:

    [ATMega8][ASM] Dziwny odczyt z czujnika DS18B20
  • #10 10036444
    Ch.M.
    Poziom 27  
    Nie przełączasz w stan nieustalony tylko przy przełączeniu portu jako wejście jest stan wysokiej impedancji (HiZ). Przy przełączeniu portu na wyjście w stanie niskim na PD7 masz logiczne 0(Low), czyli około 0V (kilkadziesiąt mV w rzeczywistości).
    Rezystor 4k7 powinien być wystarczający dla 1xDS18. Ale czy przypadkiem, nie wydawało Ci się że jest on w uK? Jeśli tak, to niestety nie... można uaktywnić wewnętrzny pull-up ale nie ma on takowej wartości tylko zbyt dużą by DS zadziałał a w dodatku go nie ustawiłeś.

    Przy opisie procedury masz zapis czekam 5ms... a obok stoi nop?

    Popraw link do dokumentacji. Link nadal zły.
  • #11 10036486
    Bartoneczek
    Poziom 10  
    Link poprawiony. Czekam 5 us - odnosiło się do 5 nop - czyli do 5 taktów = 5 us. ;)

    Zgłupiałem totalnie. Czyli, krótkomówiąc w jaki sposób mam:

    - ustawić stan niski (wysyłanie sygnału reset)? DDR=1, PORT=0?
    - zwolnić magistralę tak aby zewnętrzny rezystor mógł podciągnąć linię do stanu wysokiego?
    - w jakim stanie powinien być port (DDR, PORT) tak aby mógł odebrać sygnał presence, czyli w jakim stanie ma być żeby DS mógł ustawić port w stan niski?

    Wszystko odnośnie tego schematu.
  • #12 10036501
    Ch.M.
    Poziom 27  
    Link nadal zły.
    Wysłanie 0 przez uK to komenda sbi DDRD, 7 Wtedy zasilanie czujniku zanika i żywi się on energią z jego wewnętrznego kondensatorka... więc nie za długo.
    Zwolnienie magistrali to komenda cbi DDRD, 7 czyli stan wysoki danych oraz załączenie zasilania +5V poprzez zewnętrzny rezystor 4k7.
    Logicznym więc jest, że sygnał presence odbierzesz tylko wtedy, gdy DDRD, 7 jest ustawiony jako wejście (cbi DDRD, 7).
  • #13 10036575
    asembler
    Poziom 32  
    To że procesor ustawiony jest na 1MHz wewn, domyslnie nie oznacza że ma taka akurat oscyalacje zapewnioną. Dodatkowo nalezy odczytać za pomocą programatora lub programowo wartość/wartości CALIBRATE i ewentualnie wprowadzić poprawkę do rejestru.OSCCAL. Oczywiście to wszystko bzdury bo poprawnie napisany program !-Wire zapewnei odczyt w granicach +-50% wartości oscylatora.
    Rezystor nie jest niezbędny ale nie przeszkadza.
  • #14 10036583
    Bartoneczek
    Poziom 10  
    Ch.M.: czyli przy obsłudze DS'a w ogóle nie korzystam z wewnętrznego podciągnięcia a bit PORTD,7 przez cały czas jest ustawiony na 0?
  • #15 10036615
    Ch.M.
    Poziom 27  
    Ale Ci namieszałem... przeczytaj jeszcze raz moją poprzednią odpowiedź.
  • #16 10037296
    Bartoneczek
    Poziom 10  
    Napisałem nową wersję programu całkowicie od nowa.

    Kod: text
    Zaloguj się, aby zobaczyć kod


    Pominąłem mniej ważne funkcje które na pewno działają lub/oraz nie dotyczą czujnika w celu poprawienia przejrzystości kodu. Teraz wyświetlacz cały czas pokazuje 00. Lepsze to niż losowe wartości. Z tym że wolałbym jednak żeby wyświetlacz pokazywał temperaturę. ;) Bardzo proszę kogoś kto miał styczność z DS18B20 o sprawdzenie tych kilku funkcji i stwierdzenie czy czujnik jest uszkodzony czy coś jest nie tak w kodzie. Schemat podłączenia zamieściłem wyżej. Fosc = 1 MHz z wewnętrznego oscylatora.
  • #18 10038258
    Bartoneczek
    Poziom 10  
    asembler: mój program pokazuje 00, a po zwarciu pinu do zasilania: -16. Wygląda to tak jakby otrzymywał bajty mniej więcej: XXXX1001 i 0000XXXX. Po drobnych przeróbkach zgodnie z Twoim programem jest na odwrót: na wolno jest -16, po zwarciu do masy 00.

    Odpowiedzią na moje pytanie może być odpowiedź na pytanie: co może powodować że pomimo zwarcia pinu do napięcia (co daje cały czas stan wysoki), tylko niektóre bity zapisują się jako 1? Funkcję readbyte analizowałem kilka razy, porównywałem z innymi funkcjami znalezionymi w internecie i jest czysta jak łza. Przyczyna musi leżeć gdzieś głębiej. Ma ktoś jakiś pomysł? Podglądowo:

    Kod: text
    Zaloguj się, aby zobaczyć kod


    EDIT: ok, problem wyświetlania -16 został rozwiązany (funkcja lsl przesuwała o jeden raz za dużo). ;) Teraz muszę sobie poradzić z wyświetlaniem 00. :)
REKLAMA