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

DS18B20 z ATmega8 i LCD - dlaczego pokazuje temperaturę 0.0?

Mat_91 15 Lut 2008 19:01 5184 31
REKLAMA
  • #1 4808356
    Mat_91
    Poziom 25  
    Posty: 908
    Pomógł: 77
    Ocena: 16
    Witam!!

    Od razu chce napisać iż wiem, że temat ds'a na elektrodzie pojawiał się już N-razy ale mimo iż od kilku dni przeszukuje forum, nie udało mi się rozwiązać problemu.

    Mianowicie chodzi o to, że z rożnych tematów na elektrodzie i rad innych udało mi sie sklecić programik do obsługi ds'a + atmega8 + lcd. Czujnik odpowiada po resecie, czasy w symulacji wychodzą dobrze. Procedury zapisu i odczytu bitu/bajtu wziąłem z tego tematu. Wzorowałem sie na programie który umieścił "rsikon". Czasy są chyba dobre, procedury też chyba dobre, mimo to na lcd otrzymuje temperaturę 0.0 :| nie wiem, może jakiś błąd w programie, lub jednak te czasy na 1wire są nie takie jak powinny?? Układ taktuje 8MHz, i w symulacji (AVRstudio) opóźnienia są praktycznie idealne... :/ Jednak układ ani drgnie... :( cały czas tylko to 0.0

    W załączniku podaje kod, będę naprawdę wdzięczny jeżeli ktoś zerknie na to i wskaże gdzie jest błąd.
    Załączniki:
    • lcdm8.rar (1.87 KB) Musisz być zalogowany, aby pobrać ten załącznik.
  • REKLAMA
  • #2 4808641
    don diego
    Poziom 32  
    Posty: 1557
    Pomógł: 165
    Ocena: 63
    Nie znam zbytnio C. Sprawdzałeś z innym czujnikiem?
  • REKLAMA
  • #3 4808817
    Mat_91
    Poziom 25  
    Posty: 908
    Pomógł: 77
    Ocena: 16
    Tak sprawdzałem na 2 sztukach, taki sam efekt --> odpowiada na reset ale dalej już nic:/
  • #4 4809363
    MarasK
    Poziom 18  
    Posty: 231
    Pomógł: 19
    Ocena: 4
    mm nie widzę deklaracji DDR - kierunków działania portów. Domyślnie są one ustawiane jako wejścia, a ustawianie ich za pomocą PORTB = 1 i PORTB = 0 to włączanie i wyłączanie Pullupa (który już de facto masz na magistrali).

    Poza tym nie wiem jak chciałbyś w ten sposób zapisać 0 :)

    Niżej masz wycinki mojego programu: (ATMEGA8)
    #define OW_IN DDRB &= 0b01111111		//makra do obslugi linii 1wire
    #define OW_OUT DDRB |= 0b10000000
    #define OW_CLR PORTB &= 0b01111111
    #define OW_SET PORTB |= 0b10000000
    #define OW_PIN	PINB
    #define OW_PORT	PORTB
    
    #define SKIP_ROM  			0xCC		//pominiecie rom
    #define CONVERT_T 			0x44		//konwersja temp
    #define READ_SCRATCHPAD 	0xBE		//odczyt pamieci termometru
    
    char OW_RESET(void)		//reset magistrali
    {
    char wynik;
    
    	OW_CLR;				//wyzerowanie pinu
    	OW_IN;				//pin jako wejscie -> pin=1
    
    	OW_OUT;				//pin jako wyjscie -> pin=0
    	_delay_us(800);		//odczekaj 500us(min480us)
    	OW_IN;				//pin jako wejscie -> pin=1
    
    	_delay_us(100);		//odczekaj 70us (min60us)
    	wynik = (OW_PIN & 0x80)>>7;	//wystaw odpowiedz
    
    	_delay_us(250);
    	return(wynik);
    }
    
    void OW_WBIT(char bit)		//zapis jednego bitu na magistrale
    {
    	OW_CLR;					//wyzerowanie pinu
    	OW_IN;					//pin jako wejscie -> pin=1
    	if (bit==0)				//jezeli mamy zapisac zero (argument f-ji)
    	{
    		OW_OUT;				//pin=0
    		_delay_us(90);		//na 70us(min60us)
    		OW_IN;				//pin=1
    		_delay_us(15);		//na 15us
    	}
    	else					//jezeli mamy zapisac jedynke
    	{
    	OW_OUT;					//pin=0
    	_delay_us(5);			//czekaj 5us
    	OW_IN;					//pin=1
    	_delay_us(60);			//czekaj 70us (wypelnienie slotu)
    	}
    }
    
    char OW_RBIT(void)			//procedura odczytu bitu z szyny
    {
    	char wynik;
    	OW_CLR;					//wyzerowanie pinu
    	OW_IN;					//ustawienie portu jako wejscie (1 na wyj)
    
    	OW_OUT;					//ustawienie portu jako wyjscie (0 na wyj, bo ow_clr)
    	_delay_us(6);			//czekac 6us
    
    	OW_IN;					//ustawienie pinu jako wejscie - pull-up
    	_delay_us(10);			//odczekac 10us
    
    	wynik = (OW_PIN & 0x80)>>7;
    	_delay_us(60);			//60us
    
    	return wynik;
    }
    
    void OW_SEND(char byte)		//procedura zapisu bajtu na szyne
    {
    char i;
    for(i=0;i<8;i++)			//osmiokrotne wywolanie zapisu bitu na szyne
    {
    	OW_WBIT(byte & 0x01);	//wystawienie na szyne LSB
    	byte >>=1;				//i przesuniecie do nastepnego bitu.
    }
    }
    
    char OW_READ(void)			//procedura odczytu bajtu z szyny
    {
    char i,byte=0;
    for(i=0;i<8;i++)			//osmiokrotne wywolanie odczytu bitu
    {
    	byte |= (OW_RBIT()<< (i));	//za pomoca |= tworzymy wyjsciowy bajt
    
    }
    return byte;
    }
    
    void OW_CONVTEMP()			//procedura rozkazu konwersji temperatury
    {
    	cli();
    	OW_RESET();				//reset magistrali
    	OW_SEND(SKIP_ROM);		//pominiencie sprawdzania ROM
    	OW_SEND(CONVERT_T);		//rozkaz konwersji temp
    	sei();
    }
    
    char OW_READTEMP(void)		//procedura odczytu temperatury
    {
    	cli();
    	unsigned char scratchpad[9];	//deklaracja 'mapy pamieci'
    	unsigned char i;				//zmienna pomocnicza
    	for (i=0; i<9;i++) scratchpad[i]=0;		//zerowanie mapy pamieci
    	OW_RESET();								//reset magistrali
    	OW_SEND(SKIP_ROM);						//pominiecie sprawdzania ROM
    	OW_SEND(READ_SCRATCHPAD);				//odczyt pamieci termometru
    	for (i=0; i<9;i++) scratchpad[i] = OW_READ();
    
    //	return  ((scratchpad[1] << 4) | (scratchpad[0] >> 4));	//obliczanie dla DS18B20
    	return ((scratchpad[0]>>1)&0b01111111); // obliczanie dla DS1820 (nie B!!)
    	sei();
    
    }
    
    void OW_RESOLUTION()	//procedura ustawiajaca rozdzielczosc na 9bit
    {
    	cli();
    	OW_RESET();				//reset magistrali
    	OW_SEND(SKIP_ROM);		//pominiecie sprawdzania ROM
    	OW_SEND(0x4E);			//zapis do pamieci termometru
    	OW_SEND(0);				//(nie uzywamy TH i TL)
    	OW_SEND(0);
    
    	//mozliwe ze zbedne dla ds1820 (nie B!)
    	OW_SEND(0b00011111);			//ustaw rozdzielczosc na 9bit 0_R1_R0_11111
    	sei();
    }
    

    Jest słaby, bo nie ma np wykrywania "presence pulse", ale działa na 100%.
    Kwarc używany - 1MHz wewnętrzny
  • #5 4810177
    Mat_91
    Poziom 25  
    Posty: 908
    Pomógł: 77
    Ocena: 16
    Hmmm... :) Tylko że na DDRB też nie działało :| ale zaraz to zmienie i sprawdze jeszcze raz, albo wykorzystam twoj kod.
  • #6 4810286
    Hamster_71
    Poziom 13  
    Posty: 130
    Pomógł: 2
    Ocena: 1
    
    unsigned char odbierz1w(void) // READ_BYTE  
    { 
       unsigned char i; 
       unsigned char value = 0; 
       for (i=0;i<8;i++) 
       { 
          if(odbierz()) 
          value|=0x01<<i;
       } 
       delay_us(119);
       return(value); 
    } 
    
    void zapisz1w(char val) // WRITE_BYTE 
    { 
       unsigned char i; 
       unsigned char temp; 
       for (i=0; i<8; i++)  
       { 
          temp = val>>i; 
          temp &= 0x01; 
          wyslij(temp); 
       }
          delay_us(119);
    } 
    
    void wyslij(char bit) //WRITE_BIT 
    {    
       	PORTB |= _BV(1); //DQ = 0; 
      	if(bit==0) 
                  {
                  delay_us(103); // (wedlug symulatora 103,3uS)
    	PORTB &= ~_BV(1); //DQ =1;
                  }
       	PORTB &= ~_BV(1);//DQ = 1;
                  delay_us(103); // (wedlug symulatora 103,3uS) 
    } 
    


    Spróbuj tak, poza tym przy zapisie bitu masz dać 0 na linie przez czas większy niż 1 us, możesz dać mu spokojnie 2 us, a uciąc z tych 13 kawałek.

    Na początek nie wysyłaj komendy dotyczącej konwersji temp. tylko skip rom i odczytaj 2 pierwsze bajty. temp. powinna wynosić 85*C jeśli tak będzie, to zoanczać będzie ,że odczyt i zapis do DS'a jest prawidłowy.
  • #7 4810400
    Mat_91
    Poziom 25  
    Posty: 908
    Pomógł: 77
    Ocena: 16
    A więc tak, pozamianie z PORTB na DDRB czujnik wogóle przestał reagować na reset i nic nie działa. Zmieniłem kod tak jak powiedział Hamster_71 i pierwszy odczyt z czujnika wynosi -63,9*C nastepny 0.0. Spróbuje teraz z konwersja.

    EDIT:

    I dalej nic... po wysłaniu komendy skip rom odczytana temp= -63,9, taki sam efekt jest jak wyśle również komende Convert temp. Zawsze pierwszy odczyt -63,9 a nastepny 0,0... Spróbuje jeszcze pozmieniać czasy.
  • #8 4810898
    MarasK
    Poziom 18  
    Posty: 231
    Pomógł: 19
    Ocena: 4
    błąd w procedurze odczytu - jak pisał przedmówca. Próbowałeś mój kod uruchomić?
  • REKLAMA
  • #9 4811044
    Hamster_71
    Poziom 13  
    Posty: 130
    Pomógł: 2
    Ocena: 1
    
    #define OUT DDRB|=0x02;
    #define IN DDRB&=~0x02;
    
    char odbierz1w(void) // READ_BYTE  
    { 
       unsigned char i; 
       unsigned char value = 0; 
       for (i=0;i<8;i++) 
       { 
          if(odbierz()) 
          value|=0x01<<i; 
       } 
       delay_us(150); 
       return(value); 
    } 
    
    void zapisz1w(char val) // WRITE_BYTE 
    { 
       unsigned char i; 
       unsigned char temp; 
       for (i=0; i<8; i++)  
       { 
          temp = val>>i; 
          temp &= 0x01; 
          wyslij(temp); 
       } 
          delay_us(150); 
    } 
    
    void wyslij(char bit) //WRITE_BIT 
    {    
        OUT; 
        if(bit==0) 
       { 
       delay_us(100);
       IN; 
       } 
       IN; 
       delay_us(100); 
    }
    
    char odbierz(void) 
    { 
       	unsigned char presence=0; 
       	OUT; 
       	delay_us(2);
       	IN;
      	delay_us(13); 
       	if(bit_is_clear(PINB,PB1)) 
    	presence=0; 
       	if(bit_is_set(PINB,PB1)) 
    	presence=1; 
       	return(presence); 
    } 
    
    void reset1w(void)
    	{
    	stan = 0;
    	OUT;
    	delay_us(480);
    	IN;
    	delay_us(70);
    	if bit_is_clear(PINB,PB1)
    	stan = 1;
    	delay_us(400);
    	}
    


    Działac musi, jeśli nie będzie działać, to masz złą funkcję opóźniającą.
  • #10 4811135
    Mat_91
    Poziom 25  
    Posty: 908
    Pomógł: 77
    Ocena: 16
    Teraz to ja już nic nie rozumię... :( Jak zmieniłem te funkcje tak jak piszesz to czujnik przestał odpowiadac...

    Jak:
    
    #define OUT DDRB|=0x02; 
    #define IN DDRB&=~0x02;
    

    zmienie na:
    
    #define OUT PORTB|=0x02; 
    #define IN PORTB&=~0x02;
    


    to czujnik reaguje- jak jest podpiety to na lcd mam komunikat "ok" jak go odlacze "nie ok" czyli tak jak powinno byc. Nie rozumie dla czego po zamianie PORTB na DDRB nie działa ;(
  • #11 4813015
    MarasK
    Poziom 18  
    Posty: 231
    Pomógł: 19
    Ocena: 4
    moim zdaniem, to że masz "OK" na lcd to błędna interpretacja.

    A IN/OUT ==> WEJŚCIE/WYJŚCIE. Właśnie za zmianę tych funkcji odpowiada DDRX, a nie PORTX. Jeśli użyjesz PORT, to nie pozwalasz układowi ściągnąć napięcia do masy (czyli nie zachodzi komunikacja, po prostu).
  • #12 4814109
    Mat_91
    Poziom 25  
    Posty: 908
    Pomógł: 77
    Ocena: 16
    Teraz już mniej więcej to rozumię, musze jeszcze nad tym kodem popracować... Może uda mi sie zmusić ten czujnik chociarz do tego zeby sie odezwał po resecie... :/ przetestuje też funkcje innych, może na którejś zadziała.

    EDIT:

    udalo mi sie uruchomic czujnik ale teraz mam duzy problem z konwersja tempratury...
    Mianowicie chodzi o to ze temp przeliczona w ten sposob:
    
    ds.nds[0]=OneWire_read_byte();
       		ds.nds[1]=OneWire_read_byte();
       		itoa(ds.tds/2,buf,10);//temper. całkowita
    		write_text(buf);
    		write_text(".\0");
       		itoa(abs((ds.tds*10/16)%10),buf,10);	//części dziesiętne
       		write_text(buf);
    		write_text(" C");
    

    pokazuje mi temperature rządu 192*C i rośnie do ponad 210 jak przytrzymam czujnik ręką. jak puszcze czujnik temp spada znowu do okolo 192*C... jakieś pomysły??
  • REKLAMA
  • #13 4815703
    BearBeer
    Poziom 11  
    Posty: 18
    Witam,
    Ja tylko chciałem się podpiąc pod tego posta i o coś zapytac jeśli można.
    Mianowicie mój DS działał dobrze, mierzoną temperaturę wyświetlałem sobie na terminalu przez RS. Ponieważ miałem małe skoki temperatury, chcąc zobaczyc większą jej zmianę podgrzałem go zapalniczką :D i teraz pokazuje tylko 0 stopni. Czy to znaczy, że juz odmówił posługi na wieki(czyt.jest do wyrzucenia) :cry: ??
    zestaw: Atmega8, 12MHz
    Pozdrawiam,
    BB
  • #14 4815858
    mattb
    Poziom 11  
    Posty: 28
    Pomógł: 1
    spróbuj tak:
    
    unsigned char round2(double d1)
    {
        return (d1 - floor(d1) >= 0.5) ? ((unsigned char)ceil(d1)) :((unsigned char)floor(d1));
    }
    
    
        unsigned char wynik1 = ds.nds[0];
        unsigned char wynik2 = ds.nds[1];
        unsigned char TemperaturaH;
        unsigned char TemperaturaL;
        unsigned char TemperaturaZnak;
        TemperaturaH = wynik2 << 5;//przesuniecie w prawo, aby uciac 5 bitow znaku temp.
        TemperaturaH += wynik1 >> 3;//dodanie mlodszych bitow temp.
        TemperaturaH >>= 1;//powrot na odp. miejsce
    
        TemperaturaL = wynik1 << 4;//przesuniecie o 4 bity w prawo aby uciac 4 MSB
        TemperaturaL >>= 4;//powrot na miejsce tamtych 4. bitow
        TemperaturaL = round2((double)TemperaturaL*(double)0.625);
    
        if(wynik2 >= 0x80)//gdy temperatura ujemna
        {
            TemperaturaZnak = '-';
            TemperaturaH ^= (1 << 6) | (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1) | (1 << 0);
            TemperaturaL = 10 - TemperaturaL;
            if(TemperaturaL > 9)
            {
                TemperaturaL %= 10;
                TemperaturaH++;
            }
        }
        else TemperaturaZnak = '+';
    
        write_text(TemperaturaZnak);
        itoa(TemperaturaH,buf,10);
        write_text(buf);
        write_text(".\0"); 
        itoa(TemperaturaL,buf,10);
        write_text(buf);
    

    jak też będzie źle wskazywało to może masz opóźnienia złe - podaj jakie wartości mają zmienne ds.nds[0] i ds.nds[1]
  • #15 4815877
    MarasK
    Poziom 18  
    Posty: 231
    Pomógł: 19
    Ocena: 4
    BearBeer - prawdopodobnie tak

    MAT_91:
    zamień:
             itoa(ds.tds/2,buf,10);//temper. całkowita
          write_text(buf);
          write_text(".\0");
             itoa(abs((ds.tds*10/16)%10),buf,10);   //części dziesiętne 
    


    na:
    
    itoa((ds.nds[1] << 4) | (ds.nds[0] >> 4),buf,10);
          write_text(buf);
    


    Stracisz miejsca po przecinku, ale część całkowitą powinno wyświetlać poprawnie. Błąd bierze się z różnicy w interpretacji 2bajtów z DS1820 - wersja B, od wersji nie-B.
  • #16 4816266
    elektryk
    Poziom 42  
    Posty: 11029
    Pomógł: 439
    Ocena: 241
    BearBeer napisał:
    WPonieważ miałem małe skoki temperatury, chcąc zobaczyc większą jej zmianę podgrzałem go zapalniczką :D i teraz pokazuje tylko 0 stopni. Czy to znaczy, że juz odmówił posługi na wieki(czyt.jest do wyrzucenia) :cry: ??
    Dziwne że jest zero, wg mnie powinien pokazywać odrobinę poniżej zera, sprawdź dla pewności czy odpowiada RESET->RESPONSE. A na przyszłość to wystarczy go macać palcem.
  • #17 4817647
    BearBeer
    Poziom 11  
    Posty: 18
    Witam,
    Mam sprawdzany warunek na RESET, cały czas!. Jak pisałem programu nie zmieniałem wogóle, ponieważ DS chodził dobrze, tylko ze zmiana temperatury była za wolna (po 1 stopniu na sekundę przy podgrzewaniu trzymając palcem) i dlatego chciałem go troszkę podgrzac mocniej, zeby skok był większy. No i temperatura rosła rosła, 35, 50 , 70 stopni itd.(także czujnik chodził dobrze), aż doszła podejrzewam do 125 i potem spadła na zero i tak została. Nawet nie zauważyłem kiedy temperatura doszła do max.125 :D , bo to jest chwila z zapalniczką
    Idę dzisiaj kupic ten czujnik, mam nadzieje, że nie jest drogi :cry: i sprawdzę czy działa i się odezwę.

    Pozdrawiam,
    BB

    PS: Program napisalem tak, ze biorę sobie tylko 7bitów wewnętrzych z tych 2 bajtów co leci(cześc całkowita), także nie rozróżniam czy jest dodatnia czy ujemna temperatura, ale to nic nie zmienia dla działania, grunt że nie ma zmiany wartości temperatury i to mnie martwi

    Dodano po 4 [godziny] 59 [minuty]:

    Witam,
    Kupiłem nowego DS (8zł :cry:) i wszystko chodzi ale dalej nie wiem czy tamten stary jest zepsuty, no ale to juz nie ważne.
    Te wymagania czasowe na 1-wire dają czasem popalic. :D
    Pozdrawiam,
    BB
  • #18 4819631
    Mat_91
    Poziom 25  
    Posty: 908
    Pomógł: 77
    Ocena: 16
    A więc tak:) Konwersja działa można powiedzieć prawie idealnie. Chodzi mi o ten sposób:
    
    unsigned char round2(double d1) 
    { 
        return (d1 - floor(d1) >= 0.5) ? ((unsigned char)ceil(d1)) :((unsigned char)floor(d1)); 
    } 
    
    
        unsigned char wynik1 = ds.nds[0]; 
        unsigned char wynik2 = ds.nds[1]; 
        unsigned char TemperaturaH; 
        unsigned char TemperaturaL; 
        unsigned char TemperaturaZnak; 
        TemperaturaH = wynik2 << 5;//przesuniecie w prawo, aby uciac 5 bitow znaku temp. 
        TemperaturaH += wynik1 >> 3;//dodanie mlodszych bitow temp. 
        TemperaturaH >>= 1;//powrot na odp. miejsce 
    
        TemperaturaL = wynik1 << 4;//przesuniecie o 4 bity w prawo aby uciac 4 MSB 
        TemperaturaL >>= 4;//powrot na miejsce tamtych 4. bitow 
        TemperaturaL = round2((double)TemperaturaL*(double)0.625); 
    
        if(wynik2 >= 0x80)//gdy temperatura ujemna 
        { 
            TemperaturaZnak = '-'; 
            TemperaturaH ^= (1 << 6) | (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1) | (1 << 0); 
            TemperaturaL = 10 - TemperaturaL; 
            if(TemperaturaL > 9) 
            { 
                TemperaturaL %= 10; 
                TemperaturaH++; 
            } 
        } 
        else TemperaturaZnak = '+'; 
    
        write_text(TemperaturaZnak); 
        itoa(TemperaturaH,buf,10); 
        write_text(buf); 
        write_text(".\0"); 
        itoa(TemperaturaL,buf,10); 
        write_text(buf);
    


    temp wskazana pokazuje mi teraz 21,3*C czyli mniej więcej tyle ile mam w pokuju. Jak przytrzymam palcem czujnik temp rośnie co 3-4*C do góry i dla mnie to ok. Ale gorzej jest jak temperatura ma spadac...:( Spada o 0,1*C (nie mniej, nie wiecej) przez kilka minut... Jak wylozyłem czujnik na pole to z temperatury pokojowej 21*C schodził w dół o 0,1*C przez 10 minut i zatrzymał sie na 1,7*C mimo że na polu jest teraz -5*C. I teraz nie wiem czy to wina czujnika czy tej konwersji. Gdyby nie to to zostawiłbym tak jak jest po efekty są coraz bardziej zadowalające. No i minusem tego sposobu jest to że bardzo dużo zajmuje:( Aż 4,5kb... :(

    A jeżeli chodzi o to:
    
    itoa((ds.nds[1] << 4) | (ds.nds[0] >> 4),buf,10); 
          write_text(buf);
    


    to działa... Ale tylko dla temp 16-26*C. Powyzej pokazuje -7,0 lub -8,0 a poniżej -1,0 lub -6,0. :/

    Co do tego wcześniejszego to spróbuje jeszcze sprawdzić na innym czujniku. Ten pomoich torturach może być już uwalony...:/

    Pozdrawiam i dziękuje za pomoc!!
  • #19 4819926
    mattb
    Poziom 11  
    Posty: 28
    Pomógł: 1
    żeby zajmował dużo mniej zrób to:
    - includuj bibliotekę math.h
    #include <math.h>

    - dodaj flagę -lm przy kompilacji
    przykładowo:
    avr-gcc -mmcu=atmega88 -I. -g -O2 -Wall -pedantic -std=gnu99 "main.c" -o "main.o" -lm

    i dodatkowo mogłbyś wywalić te zmienne wynik1, wynik2 i używać bezpośrednio ds.nds[0] i ds.nds[1]

    co do niskich temperatur to najłatwiej będzie sprawdzić jak podasz wartości liczbowe zmiennych ds.nds[0] i ds.nds[1] - wtedy będzie można przekonwertować to "ręcznie"
  • #20 4820045
    Mat_91
    Poziom 25  
    Posty: 908
    Pomógł: 77
    Ocena: 16
    dodanie tej biblioteki i tego -lm nic nie dalo:( kod zajmuje ciągle tyle samo.

    A co do wartosci ds.nds[0] i ds.nds[1] to dla temp 24,4*C (ech gorąca teraz mam w pokoju xD) :

    ds.nds[0] = 134
    ds.nds[1] = 1

    Edit:

    Uszkodzenie czujnika mogę wykluczyć... Podpiołem nowy i efekt ten sam wskazuje dobra temp ale bardzo wolno schodzi w dół i nie chce zejsc poniżej 0*C... Znaczy może i zejdzie ale im bliżej jest 0*C tym temp wolniej spada... doszedlem do okolo 0,7*C po okolo 15 minutach i dlużej nie czekałem bo bateria zmarzła i nie widziałem co jest na lcd :|
  • Pomocny post
    #21 4820623
    mattb
    Poziom 11  
    Posty: 28
    Pomógł: 1
    ee no musiało pomóc, sprawdzałem u siebie i kod się zmniejszał o kilka kB
    pokaż jakim poleceniem ze wszystkimi flagami jakie używasz kompilujesz kod

    dla tych zmiennych równych 134 i 1:
    LS Byte: 10000110
    MS Byte: 00000001
    w MS Byte pięć najważniejszych bitów wskazuje na znak - zera to dodatnia, a jedynki to ujemna
    trzy najmłodsze bity z MS Byte i cztery najstarsze z LS Byte dają siedmiobitową liczbę będącą częścią całkowitą z temperatury w *C
    w tym przykładzie co dałeś to ta liczba siodmiobitowa to: 0011000 czyli 24
    cztery najmłodsze bity z LS Byte dają część ułamkową (0110 = 6; 6*0.0625 = 0.375, czyli w przybliżeniu 0.4) więc 24.4*C to poprawna konwersja
    to jest opisane z przykładami w datasheetcie tego czujnika http://acquerra.com.au/astro/equipment/temp-logger/ds18b20.pdf (strona 3.)

    wstawiając wartości tych bitów z przykładów z tego pdfa otrzymuję dobre wartości, nawet przy ujemnej temperaturze, więc może po prostu czujnik potrzebuje więcej czasu
    jutro włożę go do zamrażarki to się przekonam ile mu zajęło przejście w temp. ujemne
  • #22 4822726
    Mat_91
    Poziom 25  
    Posty: 908
    Pomógł: 77
    Ocena: 16
    Używam AVRstudio i kompiluje program z takim parametrami:
    
    avr-gcc.exe  -mmcu=atmega8 -Wall -gdwarf-2          -lm       -DF_CPU=8000000UL -O2 -fsigned-char -MD -MP -MT lcdm8.o -MF dep/lcdm8.o.d  -c  ../lcdm8.c
    


    -lm dodałem ale nic nie pomogło. Biblioteka math.h na poczatku programu też dodana. kod dalej zajmuje 4,6kb...:/

    co do czasu konwersji spróbuje je jeszcze pozmieniać na wiekszę, jak nie pomorze to zostawie tak jak jest bo i tak czujnik będzie pracował w pokoju.

    EDIT:

    Problem z objetością kodu rozwiązany. Podziekowania dla wszystkich wypowiadajacyh się w tym temacie za udzieloną pomoc, szczególnie dla użytkownika mattb.

    poniżej działający kod do obsługi 1wire:
    
    void OneWire_init(void)
    {
        PORTB &= ~(1 << DQ);
        DDRB&=~_BV(PB1);
        
    }
    
    
    void OneWire_dlus(unsigned char x)
    {
    char q;
        if(x > 5) OCR2 = x-5; else return;
        TCCR2 = 0x01;
        for(q = 0; q < 4; q++)
        {
            TCNT2 = 0;
    	    while(TCNT2 < OCR2);
        }
        TCCR2 = 0;
    }
    
    
    
    char OneWire_reset(void)//reset lini OneWire (1 - ok, 0 - brak)
    {
        char q = 1;
        OneWire_dlus(35);
        CLR_DQ;//pull DQ line
        /*OneWire_dlus(250);
        OneWire_dlus(250);
    	OneWire_dlus(250);
        OneWire_dlus(250);//450 us*/
    	delayus(480);
        SET_DQ;//powrót lini 1w do trybu wejscia
        /*OneWire_dlus(70);
    	OneWire_dlus(70);//31,88 us - czekamy na ustab. lini*/
    	delayus(70);
        if(IN_DQ) q = 1;  else q = 0;//odczytujemy co wystawil na linie DS1820
        /*OneWire_dlus(200);
        OneWire_dlus(200);
    	OneWire_dlus(200);
        OneWire_dlus(200);*/
    	delayus(410);
        if(IN_DQ && q == 0) return 1; else return 0;
    }
    
    
    unsigned char OneWire_read_bit(void)
    {
        //char x;
        CLR_DQ;//pull DQ low to start timeslot
        /*for(x = 0; x < 10; x++);
        asm ("nop");*/
    	delayus(2);
        SET_DQ;//then return high
        //OneWire_dlus(10);//delay 15us from start of timeslot
    	delayus(10);
        if(IN_DQ) return 1; else return 0;//return value of DQ line
    }
    
    
    void OneWire_write_bit(char bitval)
    {
        CLR_DQ;//pull DQ low to start timeslot
        //char x;
        /*for(x = 0;x < 10; x++);
        asm ("nop");*/
    	delayus(2);
        if(bitval == 1) SET_DQ;//return DQ high if write 1
        //OneWire_dlus(100);//old value for remainder of timeslot - delay 104us
    	delayus(104);
        SET_DQ;
    }
    
    
    unsigned char OneWire_read_byte(void)
    {
        unsigned char i;
        unsigned char val = 0;
        for (i = 0; i < 8; i++)
        {
            if(OneWire_read_bit()) val |= 0x01 << i;//reads byte in, one byte at a time and then
            //OneWire_dlus(70);// ??shifts it left wait for rest of timeslot 120us
    		delayus(119);
        }
        return val;
    }
    
    
    void OneWire_write_byte(unsigned char val)
    {
        unsigned char i;
        unsigned char temp;
        for (i = 0; i < 8; i++)// writes byte, one bit at a time
        {
            temp = val >> i;//shifts val right 'i' spaces
            temp &= 0x01;//copy that bit to temp
            OneWire_write_bit(temp);//write bit in temp into
        }
        //OneWire_dlus(50);
    	delayus(119);
    }
    

    oczywiście czasy użyte w funkcjach są dla procedury opoźniającej znajdującej sie w pliku daley.c w załaczniku w pierwsyzm posćie.

    Jeszcze raz dzięki wszystkim za pomoc!!
  • #23 4845191
    kolanopan
    Poziom 12  
    Posty: 82
    Pomógł: 5
    Mat_91 sam szukałeś na forum jak oprogramować DS-a, ja aktualnie stanąłem przed tym samym problemem, tylko ze ostatni kod jaki podałeś w swoim poście nijak pasuje do wcześniejszych programów z pierwszego postu, pokrywa się z daley.c tylko, ale brak procedur przeliczania odczytu na temperaturę i deklaracji. Dlatego proszę abyś zamieścił cały projekt z działającym odczytem, sam szukałeś na forum a jak juz znasz odpowiedz to zostań tą osobą (naszym bohaterem) która pozostawi coś pomocnego dla kolejnych czytelników, bo do momentu gdy na forum nie znajdzie sie całkiem dobrze działający projekt to temat z "DS18b20" będzie sie jeszcze wiele razy pojawiać...

    pozdrawiam
  • #24 4845354
    adass
    Poziom 25  
    Posty: 1232
    Pomógł: 6
    Ocena: 119
    Nakupiłem czujników DS18B20 i wszystkie zawyżają temp o około 2stC.
    Pytam czy to jest wina czujników czy kodu?
  • #25 4845385
    don diego
    Poziom 32  
    Posty: 1557
    Pomógł: 165
    Ocena: 63
    To może przedstaw kod:) Czujniki masz podłączone przewodami, czy bezpośrednio na płytce? U mnie czujnik wlutowany na płytce nagrzewa się od reszty elektroniki i też zawyża temperaturę. Inna sprawa, to z czym porównujesz zmierzoną temperaturę?
    Pozdrawiam
    Adam
  • #26 4845443
    adass
    Poziom 25  
    Posty: 1232
    Pomógł: 6
    Ocena: 119
    Czujniki mam na przewodach 3żyłowych na zewnątrz i na wewnątrz i do płytki też lutowałem efekt taki sam . Temperature porównuje na trzech różnych termometrach i wszystkie trzy wskazują równo a DS18B20 między nimi wskazuje 1,7stC więcej na ujemnej też jest ta sama różnica. Tylko to jest na atmega16L.
  • #27 4845472
    don diego
    Poziom 32  
    Posty: 1557
    Pomógł: 165
    Ocena: 63
    Może to banalny sposób, ale czy sprawdzałeś temperaturę pod pachą? :)) To dość dobry wzorzec.
  • #28 4845956
    adass
    Poziom 25  
    Posty: 1232
    Pomógł: 6
    Ocena: 119
    Próbowałem już wszystkiego DS-y zawyżają temperature na 100% lub błędy w kodzie.(3 miesiące z tym walcze) zamówiłem kolejne dwa DS-y.
  • #29 4845995
    don diego
    Poziom 32  
    Posty: 1557
    Pomógł: 165
    Ocena: 63
    Proponuję więc przedstawić kod do wglądu na elektrodzie.

Podsumowanie tematu

✨ Dyskusja dotyczy problemu z wyświetlaniem temperatury 0.0 na LCD podczas odczytu z czujnika DS18B20 podłączonego do mikrokontrolera ATmega8. Użytkownik stworzył program bazujący na kodzie z forum, jednak pomimo poprawnej odpowiedzi czujnika na reset i symulacji w AVRstudio, odczyty temperatury są nieprawidłowe. Wskazywano na błędy w konfiguracji portów mikrokontrolera, szczególnie w ustawianiu kierunków pinów (DDR vs PORT), co wpływa na komunikację 1-Wire. Zaproponowano poprawki w makrach i funkcjach do odczytu i zapisu bitów oraz bajtów na magistrali 1-Wire, z uwzględnieniem odpowiednich opóźnień i konfiguracji pinów jako wejścia/wyjścia. Po poprawkach czujnik zaczął odpowiadać, ale pojawiły się problemy z konwersją odczytanych danych na temperaturę, gdzie wyniki były zawyżone lub nieprawidłowe (np. 192°C). Omówiono szczegółowo interpretację dwóch bajtów danych z DS18B20 zgodnie z dokumentacją, wskazując na konieczność prawidłowego przesunięcia bitów i uwzględnienia znaku temperatury. Zaproponowano implementację funkcji zaokrąglającej oraz użycie biblioteki math.h z flagą -lm podczas kompilacji. Poruszono także kwestie czasu konwersji temperatury i konieczności odczekania odpowiedniego czasu po wysłaniu komendy konwersji. W dyskusji pojawiły się także pytania o trwałość czujnika po przegrzaniu oraz problemy z kalibracją i różnicami temperatury wskazywanymi przez DS18B20 w porównaniu do innych termometrów. Ostatecznie autor potwierdził działający kod do obsługi magistrali 1-Wire i odczytu temperatury, podkreślając znaczenie prawidłowej konfiguracji portów i czasu konwersji.
Wygenerowane przez model językowy.
REKLAMA