4 Adet DS18B20 tek hat, ondalık hanesinde hata ?

Başlatan gtekdemir, 14 Ekim 2009, 00:51:47

gtekdemir

Herkese iyi çalışmalar, 16F877 ile tek hattan 4 adet DS18B20 sıcaklık bilgisini okumak istiyorum. Her sensörün ROM kodunu önceden okudum ve bu ROM kodlarına göre DS18B20 'ler den sıcaklık bilgisini okuyorum. Sorunum şu; nedense virgülden önceki kısım çalışırken virgülden sonrasını sağlıklı olarak okuyamıyorum. Mesela sensörü 20.3 'C sıcaklığa ayarlıyorum ama ekranda 20.0 'C görüyorum. Hesaplama kısmında bi sorun yok, tek sensör ile denediğimde  virgülden sonra dört basamak sağlıklı bi şekilde okuyabiliyorum mesela -15,0625 'C gibi. İşin garip tarafı sensörlerden gelen 16bitlik sıcaklık bilgisini binary olarak ekrana bastığımda herhangi bir problem olmazken bu 16bitlik sayıyı hesaplatıp 'C cinsinden sıcaklığı bulmayı denediğimde virgülden sonrası sapıtıyor, aşağı yada yukarı yuvarlama yapıyor. Acaba proteus saçmalıyor olabilir mi? Yakın zamanda sensörleri alıp gerçek devre ile deneyeceğim.  Program biraz karışık gibi oldu tam düzenleyemedim. 1. ve 3. sıcaklıklar Lcd'nin 1. satırında , 2. ve 4. sıcaklıklar Lcd'nin 2. satırında sırayla yazıyor. kodlar ve proteus dosyası indirebilirsiniz.

Kod:
'The 1-wire commands in Proton+ include mode switches for controlling 
'the reset pulses, and data formats for the 1-wire bus
'OREAD ve OWRITE komutlarındaki mode ifadesinin ne anlama geldiği(mode 0-7 seçilebilir)
'--------------------------------------------------------------
'Mode Bit Number	 Effect
'       0	          1 = send reset pulse before data
'       1	          1 = send reset pulse after data
'       2	          0 = byte-sized data, 1 = bit-sized data
'--------------------------------------------------------------
'Mode Bit Number	 Decimal Value	    Effect
'2 	   1	 0
'--------------        --------         ------------------------
'0	   0	 0	           0	        Byte-sized data, no reset pulse
'0	   0	 1	           1	        Send reset pulse before byte-sized data
'0	   1	 0	           2	        Send reset pulse after byte-sized data
'0	   1	 1	           3	        Send reset pulse before & after byte-sized data
'1	   0	 0	           4	        Bit-sized data, no reset pulse
'1	   0	 1	           5	        Send reset pulse before bit-sized data
'1	   1	 0	           6	        Send reset pulse after bit-sized data
'1	   1	 1	           7	        Send reset pulse before & after bit-sized data
'----------------------------------------------------------------

Device 16F877A
XTAL 4

Declare LCD_DTPIN PORTB.4	'DATA girişi PORTB'nin 4. ucundan başlayacak
Declare LCD_ENPIN PORTB.3	'LCD'nin Enable ucu
Declare LCD_RSPIN PORTB.2	'LCD'nin Register Select ucu
Declare LCD_INTERFACE 4	    'LCD veri yolu 4 bit olacak
Declare LCD_LINES 2		    'LCD 2 satırdan oluşuyor
Cls					        'Ekranı temizler ve 30 ms gecikme sağlar

Symbol termdata = PORTC.0   'portc.0 data hattı
Symbol DERECE = 223         ' ' Derece işareti
Dim mesgul As Bit           'sensör okumasını tamamladımı
Dim okunan As Word          'sensörden gelen 16 bitlik veri
Dim hesaplanan As Word      '16 bitlik verinin 'C cinsinden gösterimi için gerekli değişken
Dim isaret As Byte          'sıcaklık - yada +
Dim onda As Word            ' "," den sonrası hesaplama için değişken

Basla:
    
DelayMS 100:DelayMS 100:DelayMS 100:DelayMS 100:DelayMS 100: '500ms bekleme

'Sensör 1 okunuyor    
Temp_1:
    
OWrite termdata, 1, [$55,$28,$30,$C5,$B8,$00,$00,$00,$8E,$44]  ' 1.sensör rom kodu
    
W1: 
DelayMS 750
ORead termdata, 4, [mesgul] ' Çevrim devam ediyormu kontrol ediliyor,
                                ' mode4 ile veri alınıyor
If mesgul = 0 Then W1' musgul "0" sa hala meşgul, O zaman W1 etiketine git
    
OWrite termdata, 1,[$55,$28,$30,$C5,$B8,$00,$00,$00,$8E,$BE] '1.sensör okuduğu 
                                                             'sıcaklık değerini göndersin
    
ORead termdata, 2, [okunan.LowByte,okunan.HighByte]' iki Byte oku ve iletişimi sonlandır
GoSub slcd1
   

'Sensör 2 okunuyor    
Temp_2:
OWrite termdata, 1, [$55,$28,$31,$C5,$B8,$00,$00,$00,$B9,$44]' 2.sensör rom kodu
    
W2:
DelayMS 750
ORead termdata, 4, [mesgul] ' Çevrim devam ediyormu kontrol ediliyor,
                            ' mode4 ile veri alınıyor
If mesgul = 0 Then W2' mesgul "0" sa hala meşgul, O zaman W2 etiketine git
OWrite termdata, 1, [$55,$28,$31,$C5,$B8,$00,$00,$00,$B9,$BE]'2.sensör okuduğu 
                                                             'sıcaklık değerini göndersin
ORead termdata, 2, [okunan.LowByte,okunan.HighByte]' iki byte oku ve iletişimi sonlandır 
GoSub slcd2

Temp_3:
    
OWrite termdata, 1, [$55,$28,$32,$C5,$B8,$00,$00,$00,$E0,$44]  ' 3.sensör rom kodu
    
W3: 
DelayMS 750
ORead termdata, 4, [mesgul] ' Çevrim devam ediyormu kontrol ediliyor,
                                ' mode4 ile veri alınıyor
If mesgul = 0 Then W3' musgul "0" sa hala meşgul, O zaman W4 etiketine git
    
OWrite termdata, 1,[$55,$28,$32,$C5,$B8,$00,$00,$00,$E0,$BE] '3.sensör okuduğu 
                                                             'sıcaklık değerini göndersin
    
ORead termdata, 2, [okunan.LowByte,okunan.HighByte]' iki Byte oku ve iletişimi sonlandır
GoSub slcd3

Temp_4:
    
OWrite termdata, 1, [$55,$28,$33,$C5,$B8,$00,$00,$00,$D7,$44]  ' 4.sensör rom kodu
    
W4: 
DelayMS 750
ORead termdata, 4, [mesgul] ' Çevrim devam ediyormu kontrol ediliyor,
                                ' mode4 ile veri alınıyor
If mesgul = 0 Then W4' musgul "0" sa hala meşgul, O zaman W4 etiketine git
    
OWrite termdata, 1,[$55,$28,$33,$C5,$B8,$00,$00,$00,$D7,$BE] '4.sensör okuduğu 
                                                             'sıcaklık değerini göndersin
    
ORead termdata, 2, [okunan.LowByte,okunan.HighByte]' iki Byte oku ve iletişimi sonlandır
GoSub slcd4

GoTo Basla    

'Sıcaklık hesaplama ve ekran
slcd1:
If okunan.15=1 Then ' o zaman sıcaklık 0 ın altndadır  
    isaret="-"      ' sıcaklık negatif hesaplanıyor
    hesaplanan=($FFFF-okunan+1)
    hesaplanan=hesaplanan/16
    onda = (okunan.LowByte & %00001111)
    onda = %10000 - onda
    onda = (onda * 625) / 10
Else     
    isaret="+"      'sıcaklık + hesaplanıyor
    hesaplanan=okunan/16
    onda = (okunan.LowByte & %00001111)
    onda = (onda * 625) / 10
    EndIf  
Print At 1,1,"SIC.1= ",isaret,DEC3 hesaplanan,".",DEC2 onda,DERECE,"C               " 
Return

slcd2:
If okunan.15=1 Then ' o zaman sıcaklık 0 ın altndadır  
    isaret="-"      ' sıcaklık negatif hesaplanıyor
    hesaplanan=($FFFF-okunan+1)
    hesaplanan=hesaplanan/16
    onda = (okunan.LowByte & %00001111)
    onda = %10000 - onda
    onda = (onda * 625) / 10
Else     
    isaret="+"      'sıcaklık + hesaplanıyor
    hesaplanan=okunan/16
    onda = (okunan.LowByte & %00001111)
    onda = (onda * 625) / 10
    EndIf  
Print At 2,1,"SIC.2= ",isaret,DEC3 hesaplanan,".",DEC2 onda,DERECE,"C               " 
Return

slcd3:
If okunan.15=1 Then ' o zaman sıcaklık 0 ın altndadır  
    isaret="-"      ' sıcaklık negatif hesaplanıyor
    hesaplanan=($FFFF-okunan+1)
    hesaplanan=hesaplanan/16
    onda = (okunan.LowByte & %00001111)
    onda = %10000 - onda
    onda = (onda * 625) / 10
Else     
    isaret="+"      'sıcaklık + hesaplanıyor
    hesaplanan=okunan/16
    onda = (okunan.LowByte & %00001111)
    onda = (onda * 625) / 10
    EndIf  
Print At 1,1,"SIC.3= ",isaret,DEC3 hesaplanan,".",DEC2 onda,DERECE,"C               " 
Return

slcd4:
If okunan.15=1 Then ' o zaman sıcaklık 0 ın altndadır  
    isaret="-"      ' sıcaklık negatif hesaplanıyor
    hesaplanan=($FFFF-okunan+1)
    hesaplanan=hesaplanan/16
    onda = (okunan.LowByte & %00001111)
    onda = %10000 - onda
    onda = (onda * 625) / 10
Else     
    isaret="+"      'sıcaklık + hesaplanıyor
    hesaplanan=okunan/16
    onda = (okunan.LowByte & %00001111)
    onda = (onda * 625) / 10
    EndIf  
Print At 2,1,"SIC.4= ",isaret,DEC3 hesaplanan,".",DEC2 onda,DERECE,"C               " 
Return


End

Maxim

hesaplanan değişkenini float yapın olsun bitsin ..

Dim hesaplanan As Float  
 


ekran gösteriminide ona göre değiştirin ..
mesela

slcd1:
If okunan.15=1 Then ' o zaman sıcaklık 0 ın altndadır  
    isaret="-"      ' sıcaklık negatif hesaplanıyor
    hesaplanan=($FFFF-okunan+1)
    hesaplanan=hesaplanan/16
Else     
    isaret="+"      'sıcaklık + hesaplanıyor
    hesaplanan=okunan/16
    EndIf  
Print At 1,1,"SIC.1= ",isaret,DEC4 hesaplanan,DERECE,"C" 
Return

ete

Bana kalırsa ondalık hanesi için kullandığınız yöntem yanlış.
Bir örnekle açıklayayım.
Data sheet den aldığım bir örnek değer vereyim.
Sıcaklık=25,0625 dece iken okunan ham değer. 401 olmaktadır.
Hesaplanan=401/16=25 olarak bulunur burası doğru. Okunan ham değerin LowByte'ı=145 dir.
onda = (okunan.LowByte & %00001111)
   onda = %10000 - onda
   onda = (onda * 625) / 10
formüllerine göre;
Onda=1
Onda=16-1=15
Onda=(15*625)/10=937 çıkmaktadırki bu değer 625 çıkması gerekir idi.

Şöyle yaparsanız sonuç doğru çıkacaktır.
Onda=(okunan.LowByte & %00001111)
Onda = (onda * 625)
Onda aslında 4 bitlik bir sayıdır. Buna dikkat edin. Yani hane olarak yazarsanız 0625 gib, bir sayıdır. Ekrana yazdırırken buna dikkat etmeniz gerekir.

Yazdığınız kod da fazlalık satırlar var. Aynı işi iki defa yapıyorsunuz, mesela

If okunan.15=1 Then ' o zaman sıcaklık 0 ın altndadır 
    isaret="-"      ' sıcaklık negatif hesaplanıyor
    hesaplanan=($FFFF-okunan+1)
    hesaplanan=hesaplanan/16
    onda = (okunan.LowByte & %00001111)
    onda = %10000 - onda
    onda = (onda * 625) / 10
Else     
    isaret="+"      'sıcaklık + hesaplanıyor
    hesaplanan=okunan/16
    onda = (okunan.LowByte & %00001111)
    onda = (onda * 625) / 10
    EndIf 
Print At 1,1,"SIC.1= ",isaret,DEC3 hesaplanan,".",DEC2 onda,DERECE,"C               "


satırlarını ele alalım.
Bu satırlar şöylede yazılabilirdi;
Isaret="+"
 If okunan.15=1 Then ' o zaman sıcaklık 0 ın altndadır 
    isaret="-"      ' sıcaklık negatif hesaplanıyor
    Okunan=($FFFF-okunan+1)
Endif
    hesaplanan=okunan/16
    onda = (okunan.LowByte & %00001111)
    onda = (onda * 625) / 100
 Print At 1,1,"SIC.1= ",isaret,DEC3 hesaplanan,".",DEC2 onda,DERECE,"C               "


Ondalık kısmında ekrana yalnızca ilk iki bit yazdırdığınız için iki bitlik bir hesap yapmanız gerekir. Yukarıdaki hesapta  onda *625/100 sonucu size 2 bitlik değeri verecektir.

Ete
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

gtekdemir

@ maxiboost , öneri için sağolun ama float kullanmadan halletmem gerekiyor. Float değişkenler oldukça fazla yer işgal ediyor malum.

@ETE , Hocam tavsiyelerinizi en kısa zamanda deneyeceğim, ilginiz için teşekkürler.

gtekdemir

Sorun giderildi. Ben 10.123 gibi bir ifadenin ondalık kısmını ekrana basarken DEC1 kullandığımda ekranda 10.1 göreceğimi sanıyordum ama aslı 10.3' müş, mantık hatası yapmışım :)
Kodlar şu anda çalışıyor, programa ayrıca başka bir sensör bağlanabilmesini düşünerek rom kodu okuma kısmı ekledim. Projenin son halini Üyelere ait projeler kısmına ekleyeceğim.

Saygılar...

Mucit23

Arkadaşlar ben pic basicde İki sensörü aynı hattan okumak istiyorum. Wire hakkında anlamadığım bazı noktalar var.İki adet sensörü okutacağız . Her sensörün Ayrı bir seri numarası ve crc kodu var. sensörü diğer sensörlerden ayrıran serinumarasımı yoksa crc kodumu
ben pic basicde ufak bişeyler yaptım. Sensörün bilgilerini okuyorum CRC kodu 8E, Seri numarası ise 30C5B8000000h çıkıyor o sensör yerine isiste başka bi sensör takıyorum yine aynı şekilde aynı kodlar çıkıyor. Her sensörün Ayrı bir rom kodu varsa isisteki sensörlereden neden aynı kod çıkıyor anlamadım.
Asıl yapmak istediğim şey ise Bu sensörleri tek hattan okuyup lcd ekranda ayrı ayrı göstermektir. bunu yapabilmek için sensörlerin rom kodlarını kaydetmemiz gerekiyor. Isı sensöründen okunan tüm değerlerimi kaydediceğiz yoksa seri numarası veya CRC kodunumu
Isı sensöründen okumaya gelince hangi işlemleri izlemeliyim. yani ilk olarak hangi kodu göndermeliyimki isteiğim ısı sensörü bana sıcaklık bilgisini versin. Bunun gibi aklıma takılan birkaç konu var yardımlarnızı bekliyorum. Yapmam gerekenler sırasıyla nelerdir.

emrah

slm arkadaşlar,  sensörün seri numarasını ve crc denilen kodu nasıl buluyorsun ?

Mucit23

sensöre $33 bilgisini gönderdikten sonra 64 bitlik rom kodu alınıyor.

omereliusuk

TAM DA BU KONU ÜZERİNDE YOĞUNLAŞMIŞTIM ancak bu kadar olur. şimdi armut piş ağzıma düş gibi oldu.:)))))))) ;D

omereliusuk

Alıntı yapılan: mucit23 - 20 Aralık 2010, 17:43:58
Arkadaşlar ben pic basicde İki sensörü aynı hattan okumak istiyorum. Wire hakkında anlamadığım bazı noktalar var.İki adet sensörü okutacağız . Her sensörün Ayrı bir seri numarası ve crc kodu var. sensörü diğer sensörlerden ayrıran serinumarasımı yoksa crc kodumu
ben pic basicde ufak bişeyler yaptım. Sensörün bilgilerini okuyorum CRC kodu 8E, Seri numarası ise 30C5B8000000h çıkıyor o sensör yerine isiste başka bi sensör takıyorum yine aynı şekilde aynı kodlar çıkıyor. Her sensörün Ayrı bir rom kodu varsa isisteki sensörlereden neden aynı kod çıkıyor anlamadım.
Asıl yapmak istediğim şey ise Bu sensörleri tek hattan okuyup lcd ekranda ayrı ayrı göstermektir. bunu yapabilmek için sensörlerin rom kodlarını kaydetmemiz gerekiyor. Isı sensöründen okunan tüm değerlerimi kaydediceğiz yoksa seri numarası veya CRC kodunumu
Isı sensöründen okumaya gelince hangi işlemleri izlemeliyim. yani ilk olarak hangi kodu göndermeliyimki isteiğim ısı sensörü bana sıcaklık bilgisini versin. Bunun gibi aklıma takılan birkaç konu var yardımlarnızı bekliyorum. Yapmam gerekenler sırasıyla nelerdir.

ds18b20'nin üzerine tıkla edit
rom serial number
orayı değiştir.

Mucit23


emrah

yukardaki örnekte şöyle bir rom adresi yazmış   OWrite termdata, 1, [$55,$28,$30,$C5,$B8,$00,$00,$00,$8E,$44]  ' 1.sensör rom kodu

benim sensöreden okuyacagım rom kodu 64 bit olarak gelecek, örnekteki gibi nasıl yazılacak peki ????

Mucit23

İlk başta $55 verisini göndereceksin, ardından rom kodu ve ondan sonrada $44 verisi ni göndereceksin
OWrite termdata, 1, [$55,$28,$30,$C5,$B8,$00,$00,$00,$8E,$44]
Kırmızı ile yazılanlar rom kodu oluyor.

omereliusuk

#13
ORead ROM,2,[TERM.LowByte,TERM.HighByte]
TERM_TAM=TERM>>4
TERM_ONDA=(TERM.LowByte//16)
TERM_ONDA=(TERM_ONDA*10)/16
Print $FE,$D4 ,DEC2 TERM_TAM,",",DEC1 TERM_ONDA

TERMSONUC=(TERM_TAM*10)+TERM_ONDA  'BURADA TERM_TAM TAMSAYI DEĞERİNİ TERM_ONDA ONDALIK DEĞERİNİ İFADE EDİYOR. TOPLADIĞIMIZ ZAMAN DEĞER ATIYORUM 375 DEĞERİNİ BULUYORSAK GEREKLİ TERMOSTAT TA BU DEĞERİ KULLANIYORUZ.
yani termostat için
if termsonuc<375 then 'sıcaklık 375 ten küçükse yani 37.5 ten küçükse diyerek başlıyoruz.
tabi bu durum + pozitif sıcaklıklar için geçerli.
hesaplama böyle de olabilir.