C# ile DHT22 Sıcaklık Nem sensörü değerlerinin okunması

Uzunca bir zaman sonra merhaba. İhtiyaç duyduğum bir proje için en iyi prototipleme aracı olduğunu düşündüğüm Arduino’dan yardım almam gerekti. Enson 2 yıl kadar önce hafif birşeyler çalıştığım Arduino ile ilgili neredeyse hiç not tutmamam sebebiyle yaptığım çalışmaları buraya not düşerek ilerlemeye karar verdim.

Projemde PC ile haberleşme ihtiyacı olmasa da 2 yılın verdiği hamlığı atmak ve bu güzel cumartesiyi güzel bir etkinlikle geçirmek için işin içine bilgisayarla haberleşmeyi de kattım. Projemin önemli detaylarından birisi sıcaklık ve nem verileri ile ilişkili karar mekanizmaları oluşturmak. Bu yazının konusu da sıcaklık ve nem sensörü olan DHT22 üzerinden C#üzerine değer almaya çalışmak. (bir sonraki step/görev Android olsun)

Önce internette bilgilerine kolayca ulaşabileceğiniz DHT22 sensörünü kabaca tanıyalım;

3.3 – 6 V besleme gerilimde kullanılabilir
Maksimum 1.5mA akım tüketimi
%0 – %100 arası nem ölçümünde %2 – (Max%5) doğruluk
-40 / +80°C arası sıcaklık ölçümünde ±0.5°C doğruluk (DS18B20)
Maksimum 0.5 Hz örnekleme hızı (Min 2 saniyede bir okuma yapılabilir)

Robotistan’ın sayfasında datasheet’i detaylı inceleyebilirsiniz : LINK

DHT22 ‘nin kullanım için pin dağılımı şöyledir ;

Bu tabloya göre pin dağılımı;
#1 – VCC : 3.3V – 6V arası kullanılabilir. Biz Arduino üzerinde 5V’luk pini kullanacağız
#2 – Data in/out
#3 – Boş pin
#4 – GND : Toprak

Fritzing’de hazırladığım sketch ise şöyle;

fritzing

ilk bacağı 5V pinine, 4.bacağı GND (toprak) pinine bağlıyoruz. Data pini olarak 2 nolu pini 10K’lık bir dirençle kullanıyoruz. Sketch’de de görmüşsünüzdür, direncin bi ucu Arduino’nun 2 nolu pini ile sensörün 2 nolu bacağını 1 nolubacak ile güç kaynağımız olan 5V pin arasına uyguluyoruz. Eğer bunu yapmazsak veri alamıyoruz.

Benim çalışmamın son görüntüsü şu şekilde;

Skecth’i hazırladıktan sonra sensörün çalışabilmesi için sensör kullanım kütüphanesini indirip, programımızın kurulu olduğu dizin altında library’e açmamız gerekiyor.

Kütüphanenin son halini güncel olarak şu adreste bulabilirsiniz;
http://playground.arduino.cc/Main/DHTLib

İndirdiğiniz sıkıştırılmış dosyayı açmanız gerek adreste şöyle;
C:\Program Files\Arduino\libraries

Sketchi hazırladınız, kütüphaneyi kurdunuz, şimdi programımız menülerinden sensör imalatçısının örnek uygulamasını deneyebilirsiniz. Adresi şöyle;
File>Examples>DHT Sensor Library>DHTtester

Bağlantılarla ilgili bir sorun yaşamadıysanız sorunsuz çalışıyor olması gerek. Çalıştığını “görmek” için uygulama üzerinde bulunan serial port’u açmanız gerekiyor.

Konu başlığındada belirttiğim gibi seriportla haberleşen bir uygulmaya odaklanmamız gerekiyor. Sensor imalatcısının uygulaması arduino çalışmaya başladıktan sonra seriporta düzenli olarak 2 saniye frekansla nem, sıcaklık ve hissedilen sıcaklık değerlerini yazıyordu.

Bizse C# uygulamamız içinden veri istendiğinde bize sıcaklık ve nem değerlerini vermesini istiyoruz. Buna göre kodu biraz devşirmek zorunda kaldım. Algoritmaya göre bağlanılan seriportta “deger” stringi girilip gönderirse geriye sıcaklık ve nem değerlerini döndüreceğiz.

Önce sonucu gösterip, sonra Arduino kodlarını paylaşayım;

Sorunsuz çalışıyor, kodları da paylaşayım;

#include "DHT.h"        // Kütüphane

#define DHTPIN 2        // Bağlı olduğumuz pin
#define DHTTYPE DHT22   // DHT 22  (AM2302) Sensörümüzün tipi

DHT dht(DHTPIN, DHTTYPE);
String getValue = "";    // Seriport'ta gelen metini taşır

void setup() {
  pinMode(13, OUTPUT);  // Haberleşme sırasında görsel uyarı olsun
  Serial.begin(9600);   // Seri haberleşme başlıyor
  dht.begin();          // Sensor başlatılıyor
}//setup

void loop() {
  digitalWrite(13, LOW);            // LED : OFF
  float h = dht.readHumidity();     // Nem değeri
  float t = dht.readTemperature();  // Sıcaklık degeri
  
  while (Serial.available() > 0) {
    digitalWrite(13, HIGH);         // LED : ON
      int inChar = Serial.read();   // Seriport oku
  
      if (inChar != '\n') {         // Satırsonu gelene kadar oku
        getValue += (char)inChar;
      }//if
      else {                        // Satırsonu gelince gelen değere bak
        if (getValue == "deger"){   //  Seriporta "deger" yazılmışsa sıcaklık ve nem gönder
          if (!(isnan(t) || isnan(h))){
            Serial.print("Sicaklik: ");          
            Serial.print(t);          // Sıcaklık
            Serial.print(" C");          
            Serial.print(" \t");        
            Serial.print("Nem : % ");          
            Serial.println(h);        // Nem
            delay(1*3000);            // Bekleyelim biraz
          }
        }//if
        getValue = "";
      }//else
  }//while
}//loop

Benim için asıl zor olan kısmı şimdi başlıyor (hep karşısında olduğum microsoft ürünleri ile geliştirmekte çok ama çok  zorlanıyorum aslında!) . C#’dan seri porta sihirli kelimemizi gönderelim, ve gelen yanıtı karşılayalım. Tabi internette küçük bir aramayla yüzlercesine ulaşabilirsiniz, bende öyle yaptım.

Boş form üzerine serialport, 2 text yada combobox 2 buton koyarak rahatlıkla yapabilirsiniz. Ben statusbarları sevdiğim için alta statusStrip’de koydum. Son tasarım hali aşağıdaki gibi oldukça sade ve yalındır (üzerine tıklayarak büyütebilirsiniz)

 

Uygulamanın ekran görüntüleri şöyledir;

Açılış sırasında default port ve hız ile açılıyor. Siz uygulama içinden dilediğiniz gibi değiştirip bağlantı sağlayabiliyorsunuz. Bağlantı oluşunca kullanıcıya bir uyarı veriyor.


Seriport’a bağlandık ama hatırlarsanız veri çekmekden bahsetmiştik. Bunun için oluşturduğumuz Veri Çek butonu devreye giriyor. Bu butona tıkladığımızda ise seriporta deger kelimesini gönderip, sonucu çekiyoruz.

screen

Kodlara gelirsek, try-catch gibi hata kontrolleri yok, sınıfsal bir çalışma yok hatta değişkenleride çok cimri kullanmadım. Eğer ciddi bir uygulama çalışacaksanız detayları atlamayın. Ben gereken noktaları kod içinde açıkladım.

Kodlarımız şöyle;

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.IO.Ports;

namespace WindowsFormsApplication2
{
    public partial class Form1 : Form
    {
        String RxString = "";       // Seri porttan gelen veriler
        String RxStringLine = "";   // Seri porttan gelen veri cümlesi

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //Seri haberleşme için Default değerlerimizi seçiyoruz
            comboBox1.SelectedIndex = comboBox1.Items.IndexOf("COM3");
            comboBox2.SelectedIndex = comboBox2.Items.IndexOf("9600");
        }

        //Seriporta Bağlan Butonu
        private void button1_Click_1(object sender, EventArgs e)
        {

            serialPort1.PortName = comboBox1.Items[comboBox1.SelectedIndex].ToString();
            serialPort1.BaudRate = Convert.ToInt32(comboBox2.Items[comboBox2.SelectedIndex].ToString());
            toolStripStatusLabel1.Text = "Port: " + serialPort1.PortName + " - Hız: " + serialPort1.BaudRate;

            if (!serialPort1.IsOpen == false)
            {
                serialPort1.Close();
            }
            serialPort1.Open();
            button3.Enabled = true;
            MessageBox.Show("Bağlantı Sağlandı", "Bilgilendirme", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }


        //Seriportla bağlantı kes Butonu
        private void button2_Click(object sender, EventArgs e)
        {
            serialPort1.Close();
            MessageBox.Show("Bağlantı Kesildi", "Bilgilendirme", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        //Form kapanırken seriport açık kalmasın
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (serialPort1.IsOpen) serialPort1.Close();  
        }

        //Veri Çek butonu
        private void button3_Click(object sender, EventArgs e)
        {
            RxStringLine = "";
            serialPort1.Write("deger\n");

        }

        //Seriporttan veri gelirse...
        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            RxString = serialPort1.ReadExisting();
            this.Invoke(new EventHandler(DisplayText));

        }

        //Metni göster
        private void DisplayText(object sender, EventArgs e)
        {
            foreach (var i in RxString)
            {
                RxStringLine = RxStringLine + i;
            }
            label3.Text = RxStringLine;

        }

    }
}

 

Yaptığınız çalışmalarınızda umarım faydasını görürsünüz.

Hakan Müştak @2015

Bilgi : DHT11 içinde benzer yol izleyebilirsiniz

 

 


18 yorum

  1. hmustak dedi ki:

    SHT15’in DHT22’den daha stabil ve doğru çalıştığı bilgisini öğrendim. Daha ciddi projeler için not olarak düşmekte fayda var.

  2. Özcan ALTINBAŞ dedi ki:

    Merhaba Hakan kardeşim,
    Her zamanki formdasın. Arduino’ya doğru sürüklendiğimi hissediyorum 🙂

  3. hmustak dedi ki:

    Öncelikle sizi, eksikliğinizi yakınen hissediyorum, çok özledik.
    Geçmiş senelerde yazma isteğim çok olmadığı için, havada kalmış, uçmuş herşey. Bu sefer yazmak ve gerektiğinde dönüp okumak istiyorum. Sırf o yüzden yazıyorum aslında 🙂

  4. Anıl dedi ki:

    Bu yapıcağımız,program ile Arduino programını kurmadan sadece Arduino Driver’ını yükleyerek çalıştırabilir miyiz?
    Serial Manitör’den oluyordu ve bu iş arduino arayüzünden zahmetli bir işlemdi yani demek istediğim.Bu program ile daha kolay mı oluyor ?

    • hmustak dedi ki:

      Soruyu net anlamadım açıkcası ama; Arduino IDE’sini, Driver’ını, yada serial monitoru yüklemediğiniz bir bilgisayarda çalışan C# uygulamanızla donanımınızı bu şekilde haberleştirebilirsiniz.

      • Anıl dedi ki:

        Cevabınız için teşekkürler,sorum için kusura bakmayın vaktim olmadığı için biraz anlamsız yazmış olabilirim.

  5. Mira dedi ki:

    @hmustak
    Kodlar Çalışmıyor.
    Gerekli tabloyu vs. herşeyi oluşturdum fakat çalışmıyor yaklaşık 10 tane hata buldu program.
    Kendimce düzelttim ama program çalışmıyor.

    • hmustak dedi ki:

      Merhaba, Denemediğim, çalıştığından emin olmadığım hiçbir kodu sitemde paylaşmam. Eminim atladığınız bir şeyler vardır.

  6. Mira dedi ki:

    Rica Etsem,Exe’li bir şekilde reklamsız olarak paylaşabilir misiniz?

    Ödevim var,benim için çok gerekli.

  7. Anıl dedi ki:

    Hakan bey aldığım hata şöyle ;
    Error 1 Expected class, delegate, enum, interface, or struct C:\Users\LAB2\Desktop\Form1.cs 60 13 WindowsFormsApplication2

    4 tane hatam var hepside böyle:

    —- KOD —-

    —- / KOD —-

  8. Massive dedi ki:

    Hakan Bey sorunumu çözdüm sadece DisplayText oluşturamadım DisplayText nereden oluşturabilirim?

    • hmustak dedi ki:

      Telefonla ezbere yaziyorum
      serialPort1_DataReceived icinde eventhandleri cagirdiginizda bu fonksiyonu ide otomatik yazmali. Yazmuyorsa da copy/paste’le yazabilirsiniz.
      Sanirim label yada textbox gibi bir nesne zannettiniz.

  9. Massive dedi ki:

    Teşekkürler,Hakan Bey çok yardımcı oldunuz.

  10. Joeyray11 dedi ki:

    hakan bey serialPort1.Write(“deger\n”); kısmını anlamadım ve sürekli buradan hata alıyorum. deger değişkeni formda tanımlı olmadığı için sürekli hata alıyorum. Yardımcı olursanız sevinirim 🙄

    • hmustak dedi ki:

      Günaydın, aslında yazıda ki örnekte de verdiğim gibi manuel yada program içinden seriport aracılığı ile sensorun bağlı olduğu işlemciye “deger” string’i geldiğinde sıcaklık ve nemi okuyup göndermesini sağlamak. Bunu işlemciye gömülen kodun 28. satırında görüyoruz. Kodun bir üzerindeki seriport bağlantısında da manuel, el ile “deger” yazıp gönderirken bir ekran görüntüsü de koymuşum konu anlaşılsın diye.
      C# kodu içinde ise temelde, sıcaklık ve nemi alabilmek için uygulama içinden serialPort1.Write(“deger\n”) ile “deger” stringini gönderiyor (C# kodunun 67.satırı) ve sonrasında da işlemcinin sıcaklık nem değerlerini çekiyoruz.
      Kendim hata alıyor olsaydım ilk bakacaklarım; Sayfama SerialPort1 nesnesi koyup koymadığım ve port ayarlarımın doğru olup olmadığı olurdu.
      Selamlar 😉

      • Joeyray11 dedi ki:

        Hallettim hocam çok sağolun. deger değişkenini tırnak içerisinde yazmazsak çalışmıyormuş görmüş oldum. 😛 😛

        • hmustak dedi ki:

          String değil değişken olarak yazmaya çalışmışsınız 🙂 Geçmiş olsun. uygulama sorunsuz çalışıyor değil mi? 😉

  11. Joeyray11 dedi ki:

    Port kısmı sıkıntı hocam. Port bilgisi combobox a gelmiyor. Doğal olarak hız bilgisi ile alakalı combobox ta çalışmıyor. O bilgileri el ile girince de tahmin edeceğiniz üzere serialPort1.PortName = comboBox1.Items[comboBox1.SelectedIndex].ToString(); kodunda hata veriyor. Çözecez inşallah 🙂

Massive için bir yanıt yazın Yanıtı iptal et

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

question razz sad evil exclaim smile redface biggrin surprised eek confused cool lol mad twisted rolleyes wink idea arrow neutral cry mrgreen

*

Captcha Kontrolü * Zaman aşımı, sayfayı tekrar yükleyin


Top