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

[Atmega8][gcc] dwa ds18b20 na jednej linii

y0yster 15 Maj 2009 14:42 2350 4
REKLAMA
  • #1 6533134
    y0yster
    Poziom 19  
    Witam,

    Zacznę od tego, że przeszukałem forum, w prawdzie znalazłem interesujące mnie rzeczy lecz u mnie coś nie działa.

    Zacznijmy od początku. Mam dwa ds18b20 na jednej linii w Atmega8. Chciałbym z nich odczytać numery seryjne. Tutaj zaczynają się schody.

    Oto kawałek kodu, za pomocą, którego odczytuję dane z linii onewire:

    
    //jesli jakies urzadzenie jest podlaczone to bedziemy mogli wyslac komende
    	if( onewire_reset())
    	{
    
    		//wysylami komende Search ROM
    		onewire_write( 0xF0);
    
    		_delay_us( 210);
    
    		for( int i = 0; i < 64; i++)
    		{
    
    			bit = 0;
    			//odczyt bitu
    			bit = onewire_readbit();
    
    			//_delay_us( 3);
    
    			//odczyt negacji bitu
    			bit |= onewire_readbit() << 1;
    
    
    			//dostalismy 0 i 0
    			//znaczy to, ze sa przynajmniej 2 rozne urzadzenia
    			//tzn. jedno ma 1, drugie 0
    			if( bit == 0)
    			{
    				//bedziemy wybierac zawsze 0
    				bit = 1;
    			}
    			//dostalismy 1 i 0
    			//wszystkie urzadzenia (moze byc jedno) maja taki sam bit (1)
    			else if( bit == 2)
    			{
    				//bit = 2;
    			}
    			//dostalismy 0 i 1
    			//wszystkie urzadzenia (moze byc jedno) maja taki sam bit (0)
    			else if( bit == 1)
    			{
    				//bedziemy wybierac zawsze 0
    				//dlatego wartosc zmiennych w pierwszym przypadku i tym (trzecim)
    				//jest taka sama
    
    				//bit = 1;
    			}
    			//dostalismy 1 i 1
    			//error
    			else if( bit == 3)
    			{
    				//sbi( PORTD, PD2);
    				send_text( tekst, 2);
    				bit = 0;
    				//uciekamy
    				break;
    			}
    			
    			//wybieramy odpowiedni bit
    			if( bit == 1)
    			{
    				onewire_write_0();
    				//zapisujemy numery				
    				tablica[i/8] |= 0 << i%8;
    			}
    			else
    			{
    				onewire_write_1();
    				//zapisujemy numery				
    				tablica[i/8] |= 1 << i%8;
    			}
    
    			_delay_us( 30);
    
    		}
    


    Na pierwszy rzut oka powinno wszystko chodzić, ale :/. Zapisuje sobie odczytane dane do eepromu w atmedze i mam tam tylko 01 00 00 00 00 00 00 00.

    Co jest tutaj nie tak?

    Pozdrawiam.
  • REKLAMA
  • #2 6534468
    zdebel
    Poziom 15  
    Nie mam za bardzo sił i chęci analizować Twój kod (wybacz :D) ale coś zasugeruję. Maxim na swojej stronce ma w pdf-ie kod referencyjny jak poprawnie obsłużyć Search ROM. Poszukaj sobie i porównaj :)
    ------------
    o tu: http://www.maxim-ic.com/appnotes.cfm/an_pk/187
    Sam to stosowałem, trochę sobie to inaczej zakodziłem, ale działało na tej samej zasadzie i działa jak ta lala, także jest to doskonały punkt wyjścia do własnej implementacji :)
  • REKLAMA
  • #3 6535738
    y0yster
    Poziom 19  
    Tak, oczywiście korzystałem z tego. Ale co to zmienia jak dalej nie działa?

    Mój kod został uproszczony na tyle, że chcę tylko wykonać polecenie Search ROM, a nie skanować całą sieć w poszukiwaniu wszystkich urządzeń. U mnie są tylko 2 i taki kod mi wystarcza.

    Ktoś ma jakieś sugestie co jest nie tak?

    Pozdrawiam.
  • REKLAMA
  • #4 6536063
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Premature optimization is the root of all evil.

    Proponuję uruchomić jednak funkcję referencyjną i jak będzie działąć, to krok po kroczku wywalać to co niepotrzebne - gdy w pewnym momencie przestanie działać, to będziesz wiedział dlaczego i co jednak jest nie-zbędne.

    Argument o tym, że "tobie wystarcza" jest lekko lewy, skoro wystarcza ci niedziałająca funkcja ... <:

    4\/3!!
  • #5 6536097
    y0yster
    Poziom 19  
    To nie jest żadna przedwczesna optymizacja.
    Jest to kod dostosowany do moich potrzeb.

    Algorytm odczytywania wziąłem ze strony maxim-dallas, więc powinno wszystko, grać a jednak tak nie jest.

    Sprawdzam to z jednym urządzeniem i dwoma, cały czas mam sytuację, że odczytuje mi pierwszy bit, a następnie zamiera mi wszystko kiedy odczytuję 1 i 1 jako drugi bit.

    Co do kodu, który jest udostępniony na stronie producenta to jest on identyczny do kodu napisanego przez mnie, tylko, że jest pozbawiony zbędnego przeszukiwania (w moim przypadku).

    Może jeszcze ktoś się będzie upierał, że mogę mieć złe procedury do odczytu/zapisu ds18b20. Są one w porządku, ponieważ poprawnie mam odczytywaną temperaturę z tego termometru.

    Pozdrawiam.

    --edit

    Problem rozwiązany. Oto poprawiony kod:

    
    //jesli jakies urzadzenie jest podlaczone to bedziemy mogli wyslac komende
    	if( onewire_reset())
    	{
    
    		//wysylami komende Search ROM
    		onewire_write( 0xF0);
    
    		for( int i = 0; i < 64; i++)
    		{
    
    			bit = 0;
    			//odczyt bitu
    			bit = onewire_readbit();
    
    			//odczyt negacji bitu
    			bit |= onewire_readbit() << 1;
    
    			//dostalismy 0 i 0
    			//znaczy to, ze sa przynajmniej 2 rozne urzadzenia
    			//tzn. jedno ma 1, drugie 0
    			if( bit == 0)
    			{
    				//bedziemy wybierac zawsze 0
    				bit = 2;
    			}
    			//dostalismy 1 i 0
    			//wszystkie urzadzenia (moze byc jedno) maja taki sam bit (0)
    			/*
    			else if( bit == 2)
    			{
    				//bedziemy wybierac zawsze 0
    				//dlatego wartosc zmiennych w pierwszym przypadku i tym (drugim)
    				//jest taka sama
    
    				//bit = 2;
    			}
    			*/
    			//dostalismy 0 i 1
    			//wszystkie urzadzenia (moze byc jedno) maja taki sam bit (1)
    			/*
    			else if( bit == 1)
    			{
    
    				//bit = 1;
    			}
    			*/
    			//dostalismy 1 i 1
    			//error
    			else if( bit == 3)
    			{
    				bit = 0;
    				//uciekamy
    				break;
    			}
    			
    			//wybieramy odpowiedni bit
    			if( bit == 2)
    			{
    				onewire_write_0();
    				//zapisujemy numery				
    				tablica[i/8] |= 0 << i%8;
    			}
    			else
    			{
    				onewire_write_1();
    				//zapisujemy numery				
    				tablica[i/8] |= 1 << i%8;
    			}
    
    		}
    }
    


    Jak widać zmieniłem tylko warunki podczas rozpoznawania, czy mam zero, czy jeden. Wcześniej uwzględniałem bit negacji, który wysyła jako drugi ds18b20. Teraz uwzględniam pierwszy. Zwykła pomyłka :P a taki bałagan.
REKLAMA