czujnik DS18B20

Jul 17, 2004 2 Replies

Witam!



Zle odczyty z czujnika DS18B20.



Zastosowalem do pomiaru temperatury czujniki temperatury DS18B20. Stosuje je do dlugotrwalego monitorowania temperatury. Co 5 sek. wykonuje cykl pomiarowy. Cykl pomiaru temperatury zaczynam od rozkazu Start Conversion. Potem odczekujê oko³o 1 sek. (z dokumentacji wynika, ze konwersja sie dokona po 750msek.) i dokonuje odczytu wyniku. Przy pisaniu kodu skorzysta³em z noty aplikacyjnej Application Note 162 "1-Wire Temperature Sensor in Micro-Controller Environment". Sensor ma zasilanie podpiête do VDD, pin DQ do P3.4 w AT89C52 - z podci±gaj±cym 5.1k oraz masa do GND. Zmiany w kodzie z AN162 polagaly na dokladnym dobraniu opoznien sygnalow i wstawieniu blokad przerwan EA=0;, EA=1; (zeby nie byly naruszone rezimy czasowe zapisu i odczytu bitow przez procedury obslugi przerwan).



Co paredziesiat odczytow sensor podaje bledny wynik - co w systemie monitorowania wywoluje alarm. Czy cos zrobilem zle?



Prosze o pomoc i rade



Przemyslaw oto kod:



#pragma CODE #pragma NOAREGS // tworz kod niezalezny od banku rejestrow



#include <at89x52.h>



#include <intrins.h>


#define DQ P3_4



data int temp_int; // tutaj znajdzie siê temperatura bit presence=0;



/*------------------------------------------------------------------ DELAY - with 11.059 MHz Calling the routine takes about 24 us yeach count takes another 16 us.



-------------------------------------- dla 24 MHZ wywo³anie zabiera 7.5 us ka¿dy obieg pêtli zabiera dodatkowo 6 us



------------------------------------------------------------------*/ void delay(unsigned int useconds) { unsigned int s; for(s=0;s<useconds; s++) ; } /*----------------------------------------------------------------- OW_RESET - performs a reset on the one-wire bus and returns the presence detect. Reset is 480 us, so delay value is (480-24)/16=28.5 - we use 29. Presence checked another 70 us later, so delay is (70-24)/16 = 2.875 - we use 3



--------------------------------------------------------------- dla 24MHz (480-7.5)/6=472.5/6=78.75 u¿ywam 79. Sprawdzenie obecno¶ci nastêpne 70 us, dlatego opó¼nienie jest: (70-7.5)/6=62.5/6=10.41(6) - u¿ywam 10 do koñca szczeliny czasowej=410 us (410-7.5)/6=67



------------------------------------------------------------------*/ unsigned char ow_reset(void) { unsigned char presence; EA=0; // !!! DQ=0; // pull DQ line low delay(79); // leave it low for 480us DQ=1; // allow line to return high delay(10); // wait for presence presence=DQ; // get presence signal EA=1; // !!! delay(67); // wait for end of timeslot return(presence); // presence signal returned 0=presence, 1 no part } /*------------------------------------------------------------------ READ_BIT -reads a bit from the one-wire bus. The delay required for a read is 15us so the DELAY routine won't work. We put our own delay function in this routine in the form of a for() loop.



------------------------------------------------------------------*/ unsigned char read_bit(void) { unsigned char i; DQ=0; // pull DQ line low to start timeslot _nop_(); _nop_(); DQ=1; // then return high for(i=0; i<8; i++); // delay 15 us from start of timeslot ; return(DQ); // return value of DQ line } /*------------------------------------------------------------------ WRITE_BIT - writes a bit to the one-wire bus, passed in bitval.



------------------------------------------------------------------*/ void write_bit(char bitval) { DQ=0; // pull DQ line low to start timeslot if(bitval==1) // DQ=1; // return DQ 1 if write 1 delay(15) ; // hold value for remainder of timeslot =(7.5us +



15*6 us)=100us DQ=1; } /*------------------------------------------------------------------ READ_BYTE - reads a byte from the one-wire bus.

------------------------------------------------------------------*/ unsigned char read_byte(void) { unsigned char i; unsigned char value=0; EA=0; for(i=0;i<8;i++) { if(read_bit()) value |= (0x01<<i); // reads byte in, one byte at a time and then shifts it left delay(7); } EA=1; return(value); } /*------------------------------------------------------------------ WRITE_BYTE - writes a byte to to the one-wire bus



------------------------------------------------------------------*/ void write_byte(char val) { unsigned char i; unsigned char temp; EA=0; for(i=0; i<8; i++) // writes byt, one bit a time { temp=(val>>i); // shifts val right 'i' spaces temp &= 0x01; // copy that bit to temp write_bit(temp); // write bit in tmp into } delay(15); // 100 us 92/6 EA=1; } /*------------------------------------------------------------------



------------------------------------------------------------------*/ void Read_Temperature_step1(void) { presence=ow_reset(); if(presence==1) return; write_byte(0xCC); // Skip ROM write_byte(0x44); // Start Conversion delay(15); // 100 us



return; } /*------------------------------------------------------------------



------------------------------------------------------------------*/ void Read_Temperature_step2(void) { char get[10]; unsigned char k;



ow_reset(); write_byte(0xCC); // Skip ROM write_byte(0xBE); // Read Scratch Pad



for(k=0; k<9; k++) { get[k]=read_byte(); } ((char *)(&temp_int))[0]=get[1]; // High dla KEIL'a ((char *)(&temp_int))[1]=get[0]; // Low



return; }


Przemyslaw Kranz napisał(a):

zla temperatura to jaka? duzo sie rozni od standardowej? moze masz bledy transmisji na linii jesli temperatura zmienia sie bardzo wolno, to moze dodaj blok w programie, ktory bedzie odrzucal temperatury, ktore zmienily sie o wiecej niz np 3 stopnie od poprzednij odczytanej... ale gorzej jak za pierwszym razem zle odczyta:))) no i jeszcze gorzej, jak bedziesz mial 10 bledow pod rzad i w tym czasie temperatura zmieni sie wlasnie o te

3-4 stopnie

w przypadku gdy masz kilkadziesiat odczytow to moze warto usredniac te temp?

A sprawdzasz CRC po odczycie? No i radzilbym stosowac przynajmniej dwustopniowe zatwierdzanie temperatury - odczyt temeperatury, po pewnym czasie drugi i dopiero gdy sie zgadzaja - uznajemy ta wartosc za pewna. Jesli nie - pomiar odrzucamy. DS1820 ma co jakis czas wyskok temperaturowy, ale z reguly tylko na jeden pomiar - dajac dwu lub wiecej stopniowe zatwierdzanie eliminujemy takie pojedyncze wyskoki. To rozwiazanie ma ta wade, ze nie moze byc stosowane dla szybko zmieniajacej sie temeperatury - ale dla pomiaru temperatury powietrza - w pomieszczeniu lub na zewnatrz nadaje sie.

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required