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

[AVR][C] 1Wire zczytywanie rom

Żbik 26 Paź 2011 01:28 2700 19
REKLAMA
  • #1 10066706
    Żbik
    Poziom 12  
    Mam 2 układy 1wire: 18B20 i 2405 i chcę odczytać ich id.

    Pojedynczo sobie radzę, ale z oboma na raz mam problem.

    To moje pierwsze kroki z C i męczę się z tym już drugi wieczór.

    Chcę skorzystać z "onewire.c" dołączonej do książki kol. Mirka, funkcja zwie się "ow_rom_search" :

    uint8_t ow_rom_search( uint8_t diff, uint8_t *id )
    {
    	uint8_t i, j, next_diff;
    	uint8_t b;
    
    	if( ow_reset() ) return OW_PRESENCE_ERR;	// error, no device found
    
    	ow_byte_wr( OW_SEARCH_ROM );			// ROM search command
    	next_diff = OW_LAST_DEVICE;			// unchanged on last device
    
    	i = OW_ROMCODE_SIZE * 8;					// 8 bytes
    
    	do {
    		j = 8;					// 8 bits
    		do {
    			b = ow_bit_io( 1 );			// read bit
    			if( ow_bit_io( 1 ) ) {			// read complement bit
    				if( b )					// 11
    				return OW_DATA_ERR;			// data error
    			}
    			else {
    				if( !b ) {				// 00 = 2 devices
    					if( diff > i || ((*id & 1) && diff != i) ) {
    					b = 1;				// now 1
    					next_diff = i;			// next pass 0
    					}
    				}
    			}
    			ow_bit_io( b );     			// write bit
    			*id >>= 1;
    			if( b ) *id |= 0x80;			// store bit
    
    			i--;
    
    		} while( --j );
    
    		id++;					// next byte
    	} while( i );
    
    	return next_diff;				// to continue search
    }
    


    Tworzę sobie tablicę 2 wymiarową "tablica[2][8]" i przekazuję ją jako id. Jako diff przekazuję zmienną ustawioną na ilość układów czyli 2.

    W tablicy ląduje tylko id układu o wyższym id.

    Jak wywołać tą funkcję żeby wypełniła tablicę i drugim id?
  • REKLAMA
  • #2 10066788
    mirekk36
    Poziom 42  
    A może by tak przyjrzeć się już gotowej funkcji do wyszukiwania czujników temperatury

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    ????

    Która jest przecież na płycie DVD dołączonej do książki. Po co się męczyć tyle dni i nocy? skoro tam jest pokazane jak na dłoni jak korzystać z funkcji:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • REKLAMA
  • #3 10070143
    Żbik
    Poziom 12  
    No nie chce mi to zatrybić:/

    Z wykorzystaniem tych funkcji od ds18x20, taki sam efekt.

    Podłączę 2405, widzę jego id. Dołączę 18b20, pojawia się nowe i czy dołączę 2405 czy nie, widzi tylko 18b20. Wyjmę 18b20, widzi 2405...

    pętla w main:
    while(1)
    		{
    
    		for (i = 0; i < 2; i++) {
    			for (j = 0; j < OW_ROMCODE_SIZE; j++) {
    				gSensorIDs[i][j]=0;
    			}
    		}
    
    		devicenr=search_sensors();
    
    		lcd_locate(0,0);
    
    		for (i = 0; i < 2; i++) {
    			for (j = 0; j < 6; j++) {
    				lcd_int(gSensorIDs[i][j]);
    				lcd_str(" ");
    			}
    			lcd_locate(1,0);
    		}
    
    		lcd_locate(2,0);
    		lcd_int(devicenr);
    ...
    ...
    ...


    funkcje z onewire.c:
    uint8_t ow_rom_search( uint8_t diff, uint8_t *id )
    {
    	uint8_t i, j, next_diff;
    	uint8_t b;
    
    	if( ow_reset() ) return OW_PRESENCE_ERR;	// error, no device found
    
    	ow_byte_wr( OW_SEARCH_ROM );			// ROM search command
    	next_diff = OW_LAST_DEVICE;			// unchanged on last device
    
    	i = OW_ROMCODE_SIZE * 8;					// 8 bytes
    
    	do {
    		j = 8;					// 8 bits
    		do {
    			b = ow_bit_io( 1 );			// read bit
    			if( ow_bit_io( 1 ) ) {			// read complement bit
    				if( b )					// 11
    				return OW_DATA_ERR;			// data error
    			}
    			else {
    				if( !b ) {				// 00 = 2 devices
    					if( diff > i || ((*id & 1) && diff != i) ) {
    					b = 1;				// now 1
    					next_diff = i;			// next pass 0
    					}
    				}
    			}
    			ow_bit_io( b );     			// write bit
    			*id >>= 1;
    			if( b ) *id |= 0x80;			// store bit
    
    			i--;
    
    		} while( --j );
    
    		id++;					// next byte
    	} while( i );
    
    	return next_diff;				// to continue search
    }
    
    
    void DS18X20_find_sensor(uint8_t *diff, uint8_t id[])
    {
    	for (;;) {
    		*diff = ow_rom_search( *diff, &id[0] );
    		if ( *diff==OW_PRESENCE_ERR || *diff==OW_DATA_ERR ||
    		  *diff == OW_LAST_DEVICE ) return;
    		//if ( id[0] == DS18B20_ID || id[0] == DS18S20_ID ) return;
    	}
    }
    
    
    
    uint8_t search_sensors(void)
    {
    	uint8_t i;
    	uint8_t id[OW_ROMCODE_SIZE];
    	uint8_t diff, nSensors;
    
    	nSensors = 0;
    
    	for( diff = OW_SEARCH_FIRST;
    		diff != OW_LAST_DEVICE && nSensors < MAXSENSORS ; )
    	{
    		DS18X20_find_sensor( &diff, &id[0] );
    
    		if( diff == OW_PRESENCE_ERR ) {
    			break;
    		}
    
    		if( diff == OW_DATA_ERR ) {
    			break;
    		}
    
    		for (i=0;i<OW_ROMCODE_SIZE;i++) gSensorIDs[nSensors][i]=id[i];
    
    		nSensors++;
    	}
    
    	return nSensors;
    }


    Jakaś podpowiedź?
  • #5 10071011
    Żbik
    Poziom 12  
    Nie widzi tzn. że search_sensors zwraca 0 jak nie ma podłączonego żadnego układu, 1 jak podłączam jeden i 1 jak podłączam oba.
    Nie wypełnia też "gSensorIDs" więcej niż jednym id.
  • REKLAMA
  • #7 10071041
    Żbik
    Poziom 12  
    No właśnie problem w tym, że nie mam dwóch takich samych układów.
  • #8 10071046
    mirekk36
    Poziom 42  
    aaa, i pokaż jak to w swoim kodzie sprawdzasz ???

    Dodano po 1 [minuty]:

    Jakie stosujesz podciąganie linii DQ do VCC ? jakiej wartości rezystor ?

    czy testujesz to na krótkich kablach/połączeniach czy od razu na jakichś kilometrach skrętki ?
  • #9 10071098
    Żbik
    Poziom 12  
    Sprawdzam w pętli jak podałem wyżej.
    Dalej jest w niej jeszcze:
    lcd_locate(3,0);
    lcd_str("odczyt nr: ");
    lcd_int(z);
    z++;
    _delay_ms(500);
    


    Rezystor podciącający 3.3k. Układy wpinane bezpośrednio w gniazdo na płytce ZL2AVR. W obu trybach zasilania to samo.
  • #10 10071138
    mirekk36
    Poziom 42  
    Nie za bardzo rozumiem co ty robisz w tej całej pętli.

    Weź przed wejściem do tej pętli zrób tak:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    I powiedz jaka ci się liczba wyświetla. Poza tym postarałbym się na twoim miejscu o dowolny inny czujnik albo ten DS18xxx albo ten twój drugi układ.
  • #11 10071191
    Żbik
    Poziom 12  
    Ten sam efekt. Zwraca max 1.
    Cytat:
    Nie za bardzo rozumiem co ty robisz w tej całej pętli.

    Pierwsza zagnieżdżona for czyści zawartość gSensorIDs.

    Druga wyświetla pierwsze sześć bajtów z "obu wymiarów"
  • #12 10071239
    mirekk36
    Poziom 42  
    No dobra to teraz sprawdź jaki masz *diff - bo być może funkcja zwraca błąd - trzeba stwierdzić jaki ?

    Dodano po 1 [minuty]:

    Możesz też ją zdebugować ;) ale bez żadnego tam debugera - po prostu wepnij się w nią i skorzystaj z LCD. SPrawdź ile obiegów robi pętla for(;;) itp
  • #13 10071312
    Żbik
    Poziom 12  
    Bez układów 255. Z jednym i oboma 0.
    Sprawdzam w search_sensors zaraz po DS18X20_find_sensor:
    DS18X20_find_sensor( &diff, &id[0] );
    diffchecker = diff;
  • #14 10071389
    mirekk36
    Poziom 42  
    Nie no zaraz coś tu się nam kręci ;) tzn albo tobie albo może mi ;)

    Jeszcze przed chwilą pisałeś, że gdy podłączasz układy pojedynczo to wykrywane są poprawnie czyli wartość zwracana powinna być = 1

    A teraz piszesz, "że z jednym lub z oboma jest = 0"

    To ja już nic nie rozumiem i coś mi się zdaje że gdzieś popełniasz jakiś duży błąd.

    Może zapytam inaczej - gdy podłączysz normalnie jeden czujnik temperatury to uzyskujesz prawidłowy pomiar tej temperatury czy też nie ? bo jeśli nie - to pies jest całkiem gdzie indziej pogrzebany.

    Najlepiej, żeby można było szybciej pomóc to przydałby się dokładny schemat jak to podłączasz, może jakaś fotka tego no i cały twój testowy program main.c , albo cały projekt.

    Zresztą na płycie DVD dołączonej do książki masz przykładowy kod który obsługuje naraz dwa czujniki temperatury. A jeśli włoży się tylko jeden to na LCD zobaczysz error z jednego nieobecnego czujnika oraz prawidłową temperaturę z tego właściwego podpiętego.

    Zrób więc taki test najpierw i zobacz na tym programie który na 100000000000% działa czy i u ciebie to śmiga? Bo jeśli nie - to szukaj błędu w połączeniach itp niestety :(

    albo jeszcze hmmm w ustawieniach projektu .... no właśnie! ;) w czym to piszesz ? może w kocim AVR Studio 5 ????? jeśli tak to weź spluń przez lewe ramię i wyrzuć to na śmietnik a w zamian weź ECLIPSE , które też masz dostarczone na DVD do książki i zrób to dokładnie tak jak masz pokazane w lekcjach VIDEO.

    przeczytaj też to:

    http://forum.atnel.pl/topic17.html
  • #15 10071511
    Żbik
    Poziom 12  
    No błąd na pewno gdzieś popełniam :)
    search_sensors zwraca 1, po zakończeniu DS18X20_find_sensor diff = 0, jeśli układ/y jest/są podłączone.
    Używam eclipse.
    Schemat całej płytki jest tu:
    http://www.btc.pl/pdf/zl2avr.pdf
    Punkt "1Wire" podłączam prosto do nogi procka.

    Wieczorem zrobię porządek z kodem i wkleję jak odczytuję temperaturę ( nie używałem ds18x20.c ) i steruję tym 2405. W sumie to nie sprawdzałem jeszcze czy oba działają na raz.
  • REKLAMA
  • Pomocny post
    #16 10071566
    mirekk36
    Poziom 42  
    No dokładnie - to nie ma co pisać w ciemno - tylko przysiąść, zrobić porządek - i na spokojnie bez nerwów podziałać. Musi się udać ;) .... jak coś to czekam na poprawiony kod - o ile jeszcze problem będzie występował ?
  • #17 10073090
    Żbik
    Poziom 12  
    Oba układy działają na raz, bez problemu.
    Odczytane id zapisałem w tablicach:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Ale nie chcą się skubańce odczytać "automatycznie" :)

    main z komentarzami:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    hmm. Błąd / przyczyna będzie chyba gdzieś w search_sensors, DS18X20_find_sensor lub ow_rom_search.

    ps. jak wstawić kod C żeby był pokolorowany?
    dzięki dondu :)
  • #19 10091359
    Żbik
    Poziom 12  
    Znalazłem przyczynę w "DS18X20_find_sensor".
    Pętla wykonywała się, aż znajdzie ostatni układ lub czujnik, a że mój DS2405 ma "niższe ID" i nie jest czujnikiem to był pomijany.

    Tylko że, ta pętla, w takiej postaci to już nie jest pętlą.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Dobrze rozumuję, że mogę całą tą funkcję pominąć, bo służy tylko do znajdowania czujników temperatury?
  • Pomocny post
    #20 10091524
    mirekk36
    Poziom 42  
    Zauważ że ta funkcja jest w plikach które zawierają w nazwie DS18X20.*

    Jak myślisz po co one są ? Masz tu po prostu przykład użycia funkcji nadrzędnych w magistrali 1wire do obsługi właśnie tych czujników.

    Zamiast więc pomijać tę czy inną funkcję dodaj kilka stałych do pliku *.h oraz lekko przerób te funkcje do wyszukiwania również twoich urządzeń na magistrali 1wire.

    Przecież w tej funkcji, którą tu przytoczyłeś masz w tej pętli for(;;) pod koniec IF'a który sprawdza sygnaturki czujników temperatury. Dodaj więc sygnaturki swoich układów, zdaje się że to będzie 0x05 (sprawdź w nocie PDF) i będziesz miał za chwilę ładną i gotową bibliotekę do obsługi tego układziku - tzn możesz dodać pewne dla niego charakterystyczne funkcje no bo przecież nie skorzystasz z tych dla DS'ów ;) zabardzo, poza tym ew wyszukiwaniem na magistrali.
REKLAMA