avatar_anlhlc

Pic16F628A ile DHT22 Sensör Kullanımı Hk.

Başlatan anlhlc, 11 Ocak 2017, 15:45:04

anlhlc

Merhaba arkadaşlar DHT22 sensörünü pic ile okuyamadım. DHT11 sensörünü kullanmakta sıkıntım yok daha hassas ölçüm yaptığı için DHT22 kullanmak istiyorum. Elinde örnek olan veya nasıl okuma yapacağım hakkında bilgisi olan varsa yardımcı olabilir mi? Programlama dili olarak picbasic kullanıyorum.Şimdiden teşekkürler.

ete

Her ikisinin de data sheetlerine baktım. Sinyal formatı aynı tek fark start durumu.
DHT-11 de işlemci Data hattını LOW a çekip 18ms bekliyor sonra data hattını HIGH yapıp yaklaşık 40us bekleyip data hattını girişe çeviriyor ve hat pullup dan dolayı hemen HIGH oluyor. Bu aşamada sensör hattı LOW a çekmeli çekmiyorsa hata var demektir. Hat LOW olduktan sonra data alımı başlıyor.

DHT-22 de ise İşlemci Data hattını LOW a çekip 1 ms bekliyor (bazı data sheetlerde bu süre 500us verilmiş) sonra hattı HIGH yapıp yine 40 us bekleyip hattı giriş olarak ayarlayıp bırakıyor. Hat pullup dan dolayı hemen HIGH oluyor. Bu aşamada Sensör hattı LOW a çekmesi gerekiyor. Çekmiyorsa hata var demektir. Hat LOW olduktan sonra asıl data alışı başlamış oluyor.

Gelelim Data bitlerine,
DHT-11 de  DATA biti 50us lik LOW biti ile başlıyor. Ardından Data hattı HIGH yapılıyor. Bu high süresi bitin "1" mi yoksa "0" mı olduğunu belirliyor. Şayet HIGH Süresi= 28us kadar ise bu bit LOW yani "0" dır. Şayet HIGH süresi =70us ise bu bit HIGH yani "1" dir. Bütün bitler bu mantık çerçevesinde süre bazında okunuyor.

DHT-22 de ise durum aynı, Data biti 50us lik LOW biti ile başlıyor ardından hat HIGH yapılıp high süresi=28us ise bit LOW yani "0" veya High Süresi=70us ise bit HIGH yani "1" dir deniliyor.
Bütün bitler bu şekilde okundktan sonra hesaplamaya geçilmesi gerekir.

Bütün bu açıklamalara bakarak DHT-22 yi okumak için , DHT11 okuyan programda başlangıç kısmı olan start verme işlemini aşağıdaki şekilde değiştirmek gerekiyor.

output dta :LOW DTA: Pause 1'önce hattı çıkış yapıp LOW a çektik ve 1 ms bekledik.
HIGH DTA           'Data pinini High yaptık
Pauseus 40   '40 us bekledik.
input dta       'hattı giriş olarak ayarlayıp
pauseus 5     'bir 5 us bekledik
WHILE DTA=0:WEND  'hattı okuyarak LOW olduğu sürece lowdan kurtulmasını bekledik
PAUSEUS 85  'ardından 85us lik bir gecikme uyguladık. Bu süre sonunda sensörün vereceği LOW sinyaline ulaşmamız gerekir
IF DTA=1 then hata  'hala sensör çıkışı HIGH ise bir sorun var demektir.

Bu aşamadan sonra ki kısım DHT-11 ile aynı olup tamamen data bitlerinin okunuması işlemi yapılacaktır.

Ete

anlhlc

#2
Hocam dediğiniz gibi kodlarıdeğiştirdim ama nem %3 ten yukarı çıkmıyor. Kodlarım şöyle

@ DEVICE pic16F628A                      'işlemci 16F628                               
@ DEVICE pic16F628A, WDT_OFF              'Watch Dog timer açık
@ DEVICE pic16F628A, PWRT_ON             'Power on timer açık
@ DEVICE pic16F628A, PROTECT_OFF         'Kod Protek kapalı
@ DEVICE pic16F628A, MCLR_OFF            'MCLR pini kullanılMIYOR.
@ DEVICE pic16F628A, INTRC_OSC_NOCLKOUT  'Dahili osilatör kullanılacak
'***********Seri İletişim Dosyası***********
Include "MODEDEFS.BAS"

CMCON=7
DEFINE OSC 4

'***********LCD Tanımlamaları***********

DEFINE LCD_DREG PORTB
DEFINE LCD_DBIT 0
DEFINE LCD_EREG PORTA
DEFINE LCD_EBIT  3
DEFINE LCD_RSREG PORTA
DEFINE LCD_RSBIT 2
DEFINE LCD_BITS 4
DEFINE LCD_LINES 2

'***********Özel Karakter Tanımlamaları
'LCDOUT $FE,$40, 6, 9, 9, 6, 0, 0, 0, 0 'Derece İşareti
'LCDOUT $FE,$48, 4, 14, 4, 4, 4, 4,14,0 'İ Harfi
'LCDOUT $FE,$50, 14, 17, 16, 16,16,17,14,4 'Ç Harfi
'LCDOUT $FE,$58, 14, 17, 16, 14,1, 17,14,4 'Ş Harfi
'LCDOUT $FE,$60,4,14,21,4,4,4,4,0 ;YUKARI OK İŞARETİ SIFIRINCI ADRES
'LCDOUT $FE,$68,4,4,4,4,21,14,4,0 ;AŞAĞI OK İŞARETİ BİRİNCİ ADRES
'LCDOUT $FE,$70,0,4,8,31,8,4,0,0  ;SOL OK İŞARETİ  İKİNCİ ADRES
'LCDOUT $FE,$78,0,4,2,31,2,4,0,0  ;SAG OK İŞARETİ ÜÇÜNCÜ ADRES

'***********Port Ayarları***********

TrisA=%00100011
TrisB=%00110000

PortA=0
PortB=0 
'***********Sensör Tanımlamaları***********

DS18B20   VAR PORTA.0  'DS18B20 PORTA.0 E BAĞLI
symbol DHT11=PORTA.1  'DHT11 PORTA.1 E BAĞLI
symbol SEC=PORTA.5
SYMBOL ARTTIR=PORTB.4
SYMBOL AZALT=PORTB.5
SYMBOL ISITMA=PORTA.7
SYMBOL NEM=PORTA.6
SYMBOL FAN=PORTB.7
SYMBOL NEMFAN=PORTB.6


Busy        VAR BIT
HAM         VAR WORD
ISI           VAR WORD
SIGN        VAR BYTE
SIGN_BITI   VAR HAM.Bit11
NEGAT_ISI   CON 1
TEMP        VAR BYTE
Float        VAR WORD
SURE       VAR byte
I              VAR BYTE
TAMRUT   VAR WORD
ONDARUT VAR BYTE
TAMISI     VAR WORD
ONDAISI   VAR BYTE
CONTROL var byte
DERECE  CON 223     ' ° işareti
MAXTAMISI VAR BYTE
GUN VAR BYTE
MAXONDAISI VAR BYTE
GUNSAY VAR WORD
MAXNEM VAR BYTE
DONGU VAR BYTE



'***********LCD yi Kullanıma Hazır Hale Getir***********


lcdout $FE,1
PAUSE 200   ' LCD nin kullanıma hazır hale gelebilmesi için gerekli süre
READ 1,MAXTAMISI
READ 2,MAXONDAISI
READ 3,MAXNEM
PAUSE 50
LCDOUT  $FE,$C0,"AYAR YAPINIZ"
GUN=0
GUNSAY=0
DONGU=0
gosub SENSOROKU
GOSUB DHT11OKU


'****************PROGRAM BAŞLANGICI*********************************

Basla:
GUNSAY=GUNSAY+1
DONGU=DONGU+2
IF DONGU>2 THEN
DONGU=0
GOSUB DHT11OKU
ENDIF
IF GUNSAY>43200 THEN
GUN=GUN+1
GUNSAY=0
ENDIF
WHILE SEC=1
    LCDOUT $FE,1
     GOTO MAXSICAYAR   
WEND
    gosub SENSOROKU
   PAUSE 1350
   IF MAXTAMISI>100 THEN MAXTAMISI=37
   IF MAXONDAISI>100 THEN MAXONDAISI=0
   IF MAXNEM>90 THEN MAXNEM=70
LCDOUT  $FE,$C0,"S:",DEC MAXTAMISI,".",DEC MAXONDAISI,"/",DEC MAXNEM,"-",DEC2 GUN,".GUN"

Goto Basla

'****************DS18B20 OKUMA*********************************

SENSOROKU:
     
   
           OWOUT   DS18B20, 1, [$CC, $44]' ISI değerini oku
         
             Pauseus 40
Bekle:
           OWIN    DS18B20, 4, [Busy]    ' Busy değerini oku
           IF      Busy = 0 THEN Bekle  ' hala meşgulmü? , evet ise goto Bekle..!
           OWOUT   DS18B20, 1, [$CC, $BE]' scratchpad memory oku
           OWIN    DS18B20, 2, [HAM.Lowbyte, HAM.Highbyte]' İki byte oku ve okumayı bitir.
           
           GOSUB   Hesapla
           RETURN
   
Hesapla:                 ' Ham değerden Santigrat derece hesabı
    Sign  = "+"
    IF SIGN_BITI = NEGAT_ISI THEN
       Sign   = "-" 
       temp=($ffff-ham+1)*625
       ISI  = DIV32 10
        Pauseus 40
       GOTO GEC   
    endif
    TEMP = 625 * (HAM+1)        '
    ISI = DIV32 10          ' Div32 hassas derece hesabı için 32 bit bölme yapıyoruz.
GEC:
    FLOAT = (ISI //1000)/100
    ISI=(ISI/1000)
    IF ISI>=65 then GOTO DS18B20_HATA
   
    LCDOUT $FE,$80,"ISI:",DEC ISI,".",DEC (Float),"/NEM:% ",DEC2 TAMRUT,",",DEC1 ONDARUT
    GOSUB CIKISAYAR         
    RETURN

'****************DHT11 OKUMA********************************* 
DHT11OKU:
          OUTPUT DHT11
           DHT11=0
           PAUSE 5      '1-10 ms bekle
           DHT11=1         'Data pinini High yap
           PAUSEUS 40      '40 us bekle
           INPUT DHT11
           PAUSEUS 5
           WHILE DHT11=0:WEND
           PAUSEUS 80

           IF DHT11=1 then GOTO DHT11_HATA

           TAMRUT=0
           FOR I=15 TO 0 STEP-1  'MSB bitleri önce geleceği için döngümüzü tersten kuruyoruz.
             WHILE DHT11=0:WEND 
             PAUSEUS 30
             IF DHT11=1 THEN TAMRUT.0[I]=1
             WHILE DHT11=1:WEND
           NEXT

           TAMISI=0
           FOR I=15 TO 0 STEP-1  'MSB bitleri önce geleceği için döngümüzü tersten kuruyoruz.
             WHILE DHT11=0:WEND
             PAUSEUS 30
             IF DHT11=1 THEN TAMISI.0[I]=1
             WHILE DHT11=1:WEND
           NEXT
         
          CONTROL=0
          FOR I=7 TO 0 STEP-1  'MSB bitleri önce geleceği için döngümüzü tersten kuruyoruz.
            WHILE DHT11=0:WEND
            PAUSEUS 30
            IF DHT11=1 THEN CONTROL.0[I]=1
            WHILE DHT11=1:WEND
          NEXT
          OUTPUT DHT11
          DHT11=0
          ONDARUT=TAMRUT//10:TAMRUT=TAMRUT/10
          ONDAISI=TAMISI//10:TAMISI=TAMISI/10
          LCDOUT $FE,$80,"ISI:",DEC ISI,".",DEC (Float),"/NEM:% ",DEC2 TAMRUT,","DEC1 ONDARUT
          GOSUB CIKISAYAR     
          RETURN

'****************MAX SICAKLIK AYAR*********************************   
    MAXSICAYAR:
    WHILE SEC=1:WEND 
    LCDOUT  $FE,$80,"MAX. SICAKLIK"
    LCDOUT $FE,$C0,DEC MAXTAMISI,".", DEC MAXONDAISI,"    "
    IF ARTTIR=1 THEN
       MAXONDAISI=MAXONDAISI+1
      PAUSE 500
    ENDIF
 
   IF MAXONDAISI>9 THEN
      MAXTAMISI=MAXTAMISI+1
      MAXONDAISI=0
   ENDIF

   IF AZALT=1 THEN
      MAXONDAISI=MAXONDAISI-1
     PAUSE 500
   ENDIF
 
   IF MAXONDAISI=255 THEN
      MAXONDAISI=9
      MAXTAMISI=MAXTAMISI-1
   ENDIF
   IF MAXTAMISI>50 THEN MAXTAMISI=50


    IF SEC=1 THEN
      LCDOUT $FE,1
     GOTO MAXNEMAYAR
   ENDIF

  GOTO MAXSICAYAR


'****************NEM AYAR*********************************     
MAXNEMAYAR:
     WHILE SEC=1:WEND
     LCDOUT  $FE,$80,"MAX. NEM"
     LCDOUT $FE,$C0,DEC MAXNEM," %   "   
     IF ARTTIR=1 THEN
        MAXNEM=MAXNEM+1
        PAUSE 500
     ENDIF

     IF AZALT=1 THEN
        MAXNEM=MAXNEM-1
        PAUSE 500
     ENDIF

     IF MAXNEM=255 THEN MAXNEM=80
     IF MAXNEM>80 THEN MAXNEM=0
 
     IF SEC=1 THEN
         LCDOUT $FE,1
         GOTO AYARCIKIS
     ENDIF
     GOTO MAXNEMAYAR

'****************AYAR ÇIKIŞ*********************************
AYARCIKIS:
  LCDOUT $FE,1
     LCDOUT  $FE,$80,"KAYDEDILIYOR"
      PAUSE 1000
WRITE 1,MAXTAMISI
PAUSE 10
WRITE 2,MAXONDAISI
PAUSE 10
WRITE 3,MAXNEM
PAUSE 10
LCDOUT $FE,1
     LCDOUT  $FE,$81,"AYARLAR"
     LCDOUT  $FE,$C0,"KAYDEDILDI"
      PAUSE 1000
       LCDOUT $FE,1
       pause 200
       LCDOUT  $FE,$C0,"S:",DEC MAXTAMISI,".",DEC MAXONDAISI,"/",DEC MAXNEM,"-",DEC2 GUN,".GUN"
     GOTO BASLA
     
'****************HATA*********************************
DS18B20_HATA:
LCDOUT $FE,1
     LCDOUT  $FE,$80,"DS18B20 HATASI"
GOTO BASLA
DHT11_HATA:
LCDOUT $FE,1
     LCDOUT  $FE,$C0,"DHT11 HATASI"
GOTO BASLA
CIKISAYAR:
   IF ISI=MAXTAMISI AND FLOAT=MAXONDAISI THEN
    LOW ISITMA
    ENDIF
    IF ISI=MAXTAMISI AND FLOAT>MAXONDAISI THEN
    LOW ISITMA
    ENDIF
     IF ISI>MAXTAMISI THEN
    LOW ISITMA
    ENDIF
    IF ISI=MAXTAMISI AND FLOAT<MAXONDAISI THEN
    HIGH ISITMA
    ENDIF
    IF ISI<MAXTAMISI THEN
    HIGH ISITMA
    ENDIF
    IF TAMRUT<MAXNEM+2 THEN
     LOW FAN
     HIGH NEM
     high NEMFAN
     ENDIF
     Pauseus 40
IF TAMRUT>MAXNEM+1  THEN
     LOW FAN
     low NEM
     LOW NEMFAN
     ENDIF
     Pauseus 40
IF TAMRUT>MAXNEM+2 THEN
     HIGH FAN
     LOW NEM
     LOW NEMFAN   
     endif
     Pauseus 40

  RETURN
END

ete

#3
DHT22 aslında hem rutubet hemde sıcaklık ölçebilen bir sensör neden ayrıca sıcaklık sensörü kullandın acaba?
Data sheet start durumu için en az 1 ms data hattının LOW da tutulması gerekli demiş. Bi rkaç data sheet buldum ve diğerlerinde bu sürenin 1-10ms arasında olması gerektiği söyleniyor. Bende onu 5 ms yapmaya karar verdim.

Bu sensör okuduğu rutubet değerini ondalık kısmı dahil olarak okuyup bize vermektedir. Örnek vermek gerekirse sensörden okunan TAMRUT değeri 675 ise bu aslında %67,5 demek oluyor.
Sen ise okunan değerde bir hesap yapmadan direk ,
"/NEM:",DEC2 TAMRUT,"%" şeklinde ekrana yazdırıyorsun. Bu kısım hatalı. Aynı örnek ile devam edersek 675 değerini sensörden okumuş isen ve bunu yukarıdaki şekilde ekrana verirsen ekranda /NEM= 75 % şeklinde bir ifade görürsünki buda yanlış olur. Muhtemelen  %3 görmenin sebebi budur. Doğru gösterim için TAMRUT=TAMRUT/10 şeklinde bir komut eklemen gerekir (ben ekledim)
Verdiğin kodları yeniden düzenledim ve olması gereken şekle soktum oradan alıp yeniden dene istersen.
Bu arada sensörün sıcaklık okuma kısmınıda kullanmayı ihmal etme bence. Zira bir okumada sensörden 40 bit okuman gerek. Sen 16+8=24 bit okuyorsun.
Ete

not:Okuma kısmında yeniden bir düzeltme yaptım. Bu düzeltme ile 16 bitlik TAMRUT değerini okuyup ardından yine 16bitlik TAMISI değerini okuttum. Önceki durumda 8 bit tamsayı kısmını 8 bit de ondalık kısmını okuyorduk.

Elimde sensör olmadığı için deneme şansım yok ama çalışacağını umduğum bir deneme programını ekledim. Sensörü olan deneyip sonucu bildirirse sevinirim.

Simulasyon 8.5 de DHT_22 varmış. Devreyi hazırladım ve programı denedim. Ufak tefek kusurlar çıktı ama sonunda düzelttim hepsini ve sistemi çalışır hale getirdim. Gerçekte de çalışacağından eminim artık.
SOnuçta ek deki örnek programı çalışan ile değiştirdim.

anlhlc

Hocam öncelikle ilgi ve alakaniz için teşekkürler. 
Yarin deneyip buraya yazacağım .dht11in sicaklik hassasiyetli kötü olduğu için sicaklik olcumunde DS18B20 kullandim fakat dht22 yi sorunsuz okuyabilirsem gerek kalmayacak isi ve nemi dht22den almayi düşünüyorum.  Sizce dogruluk bakimindan hangisi daha iyidir DS18B20 mi yoksa DHT22 mi ?

ete

Çözünürlük ve toleranslar bakımından dnt22  daha iyi gözüküyor..

Ete

anlhlc

Hocam merhaba programı denedim değer geliyor fakat 2-3 sn de bir sensor hatasına geçiyor

ete

Bu sorun simulasyonda da ortaya çıkmış idi. Aşmak için okuma işlemi bittikten sonra Sensör Data hattını çıkışa çevirip sonrada LOW a çekilmesi gerekti. Bunu yaptıktan sonra bir daha hata vermedi.
Yukarıda senin kodlarını da olması gerektiği gibi bugün yeniden düzenledim. Oraya bak istersen ve aynısını kullan.
Ete

anlhlc

Yukardaki kodları aynen yükledim fakat yine sensör hatasına geçiyor :(

ete

Aşağıdaki satırları bul,
          OUTPUT DHT11
          DHT11=0
          ONDARUT=TAMRUT//10:TAMRUT=TAMRUT/10
bu satırları şöyle değiştir bakalım sonuç değişecekmi?
          OUTPUT DHT11
          DHT11=1:PAUSEUS 5
          DHT11=0
          ONDARUT=TAMRUT//10:TAMRUT=TAMRUT/10
Normalde yeni okumada data hattı yeniden çıkış yapılıyor ama bunu haberleşmenin hemen bitiminde de istiyor sensör.
Bunu yapınca düzelmişti. Örnek programı çalıştırırsan anlarsın. Tabiiki sen gerçek devrede deniyorsun acaba arada bir farkmı vardır. Data sheetlere baktım okuma sonlandırmasında ne yapılıyor hiç açıklanmamış. Sadece hat işlemciye bırakılıyor ve işlemci hattı low da iken alıp HIGH yapıyor gerisini göstermemişler. Ama hatta LOW vermez isen mutlaka sensör hatasına giriyor. Buda sensörün HIGH da tutulması onun düşük akım çekme moduna sokuyormuş. Sorun bu olabilir Bu moda girmemesi için hattı LOW a çekmek gerekiyor ki onuda yapıyoruz. Son çare olarak yukarıdakini dene olmuyorsa yapabileceğim bir şey yok maalesef.
Ete


anlhlc

Hocam yine olmadı yardımcı olabilecek başka bi arkadaş yok mu acabaa ????

anlhlc

http://esersenturk.blogspot.com.tr/2016/07/dht22-ile-sicaklik-ve-nem-olcumu.html
böyle bişey buldum hocam ben pek anlayamadım aama değişik bişeyler yapılmasını söylemiş sanki arkadaş

anlhlc

Hocam değiştir dediğiniz kodları start sinyali gönderiminde değiştirdim sorun kalmadı şuan hatasız çalışıyor yardımlarınız için çok teşekkürler

ete

Ne değiştirdiğini pek anlamadım. Buraya kod koyarmısın bir anlayayım.
Ete

anlhlc

Bu kısmı
DHT11OKU:
          OUTPUT DHT11
           DHT11=0
           PAUSE 5      '1-10 ms bekle
           DHT11=1         'Data pinini High yap
           PAUSEUS 40      '40 us bekle
           INPUT DHT11
           PAUSEUS 5
           WHILE DHT11=0:WEND
           PAUSEUS 80

bunun ile değiştirdim
DHT11OKU:
           output DHT11
            DHT11=1:PAUSEUS 5
            DHT11=0
            pause 5      '1-10 ms bekle
           DHT11=1         'Data pinini High yap
           Pauseus 40      '40 us bekle
           INPUT DHT11
           PAUSEUS 5
           WHILE DHT11=0:WEND
           PAUSEUS 80

Powered by EzPortal