Başa dön
Arduino ile Kablosuz Hava Durumu İstasyonu Projesi Yapımı

Arduino ile Kablosuz Hava Durumu İstasyonu Projesi Yapımı

Merhaba arkadaşlar, bu yazımızda Arduino tabanlı bir Kablosuz Hava Durumu İstasyonu (Hava Tahmin Projesi) yapmayı öğreneceğiz. Aşağıdaki videoyu izleyebilir veya aşağıdaki yazılı eğitimi okuyabilirsiniz.

Genel Bakış

Hava durumu istasyonu projesinde ortam sıcaklığı ve nem, DHT22 nem sensörü kullanılarak ölçülür ve bu veriler NRF24L01 alıcı-verici modülleri kullanılarak kablosuz olarak iç üniteye gönderilir. İç ünitede, iç sıcaklık ve nemi ölçmek için başka bir DHT22 sensörü ve Arduino güç kaybetse bile zamanı takip edebilen bir DS3231 Gerçek Zaman Saati modülü vardır. Tüm bu veriler 0.96 inç OLED ekran veya elinizde bulunan farklı tür ekran üzerinde yazdırılır.

 

Arduino Kablosuz Hava İstasyonu Devre Şeması

Hava durumu istasyonu devre şemasına ve bu projenin nasıl çalıştığına bakalım. Bu modüllerin her birinin nasıl çalıştığı hakkında ayrıntılı eğitimlere sahip olmak için bunları kontrol edebilirsiniz: NRF24L01 EğitimiDHT22 EğitimiDS3231 Eğitimi.

Bu proje için gerekli bileşenleri aşağıdaki bağlantılardan alabilirsiniz:

 

Hem gerçek zamanlı saat modülü hem de OLED ekran, Arduino ile iletişim için I2C protokolünü kullanır, böylece I2C pinlerine veya Arduino Nano kartındaki 4 ve 5 numaralı analog pinlere bağlanırlar. NRF24L01 alıcı-verici modülünün hemen yanında, güç kaynağını daha kararlı tutmak için bir kapasitör vardır. Ayrıca sensörün düzgün çalışması için DHT22 veri pinine bağlı bir çekme direnci vardır.

Güç kaynağına gelince, iç ünite için 12V DC güç adaptörü kullandım ve diğer tarafta, dış üniteye güç vermek için 7.5V civarında iki Li-on pil kullandım. Sistem, bu konfigürasyon ile yaklaşık 10 gün çalışabilir, çünkü verileri periyodik olarak iletiriz ve bu arada Arduino’yu güç tüketiminin sadece 7mA olduğu uyku moduna geçiririz.

 

Özel Tasarım PCB

Elektronik bileşenleri düzenli tutmak için devre şemasına göre EasyEDA ücretsiz çevrimiçi devre tasarım yazılımını kullanarak özel bir PCB tasarladım. Aynı PCB’nin hem iç hem de dış ünite için kullanılabileceğini not edebiliriz. Sadece Arduino kartı farklı programlanmalıdır.

Tasarımı burada bitirdikten sonra, PCB’yi üretmek için kullanılan Gerber dosyasını dışa aktarabiliriz. Arduino kablosuz hava istasyonu EasyEDA proje dosyalarını kontrol edebilirsiniz BURADA.

Burada Gerber dosyasını sürükleyip bırakabiliriz ve yüklendikten sonra PCB’yi Gerber görüntüleyicide inceleyebiliriz. Her şey yolundaysa, PCB’imiz için istediğimiz özellikleri seçebilir ve PCB’imizi makul bir fiyata sipariş edebiliriz. JLCPCB’den ilk siparişinizse, sadece 2 $ karşılığında 10 PCB alabileceğinizi unutmayın.

Bununla birlikte, birkaç gün sonra PCB’ler geldi. PCB’lerin kalitesi mükemmel ve her şey tasarımdakiyle aynı.

Bu projenin elektronik bileşenlerini PCB’ye pim başlıklarını lehimleyerek monte etmeye başladım. Bu şekilde, gerektiğinde bileşenleri kolayca bağlayabilir ve bağlantısını kesebiliriz.

Sonra da kondansatörü ve çekme direncini yerleştirdim ve lehimledim. Bu adım tamamlandığında, bileşenleri basitçe PCB’nin pim başlıklarına bağlayabiliriz.

Sonra, proje için kutu hazırladım. Bu amaçla 8mm MDF tahta kullandım ve dairesel bir testere kullanarak tüm parçaları boyuta göre kestim.

Doğru sıcaklık ve nem ölçümlerine sahip olmak için kasaların yanları kasaya hava girmesine izin vermek zorundadır. Böylece, bir matkap ve törpü kullanarak hem iç hem de dış ünitelerin yan panellerinde birkaç yuva yaptım.

Ayrıca ön paneldeki OLED ekran için bir yuva yaptım, ayrıca daha sonra ön panele bir dekorasyon olarak ekleyeceğim küçük bir alüminyum parçasını kestim.

Kutuları monte etmek için ahşap tutkalı ve vida kullandım.

Kutuları bir sprey boya ile boyadım. Dış ünite için beyaz boya, iç ünite için siyah boya kullandım. Boya kuruduktan sonra PCB’leri kasalara yerleştirdim.

İç ünitenin arka tarafına bir güç girişi ve bir güç anahtarı taktım ve dış ünitede güç anahtarı olarak basit bir jumper teli kullandım.

Artık arduino kablosuz hava istasyonumuz çalışmaya hazır. Ancak programın nasıl çalıştığına bir göz atmak gerekiyor.

 

Arduino Kablosuz Hava İstasyonu Kodu

/*
  Arduino Wireless Communication Tutorial
      Outdoor unit - Transmitter 
      
  by Dejan Nedelkovski, www.HowToMechatronics.com
Libraries:
NRF24L01 - TMRh20/RF24, https://github.com/tmrh20/RF24/
DHT22 - DHTlib, https://github.com/RobTillaart/Arduino/tree/master/libraries/DHTlib
LowPower - https://github.com/rocketscream/Low-Power 
*/
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <dht.h>
#include <LowPower.h>
#define dataPin 8 // DHT22 data pin
dht DHT; // Creates a DHT object
RF24 radio(10, 9); // CE, CSN
const byte address[6] = "00001";
char thChar[32] = "";
String thString = "";
void setup() {
  radio.begin();
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_MIN);
  radio.stopListening();
}
void loop() {
  int readData = DHT.read22(dataPin); // Reads the data from the sensor
  int t = DHT.temperature; // Gets the values of the temperature
  int h = DHT.humidity; // Gets the values of the humidity
  thString = String(t) + String(h);
  thString.toCharArray(thChar, 12);
  // Sent the data wirelessly to the indoor unit
  for (int i = 0; i <= 3; i++) {           // Send the data 3 times
    radio.write(&thChar, sizeof(thChar));
    delay(50);
  }
  // Sleep for 2 minutes, 15*8 = 120s
  for (int sleepCounter = 15; sleepCounter > 0; sleepCounter--)
  {
    LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
  }
}

Açıklama: Dış ünite, kablosuz iletişimin vericisidir. Bu yüzden burada önce Arduino’yu uyku moduna geçirmek için kullanılan RF24 kütüphanesini , DHT kütüphanesini ve LowPower kütüphanesini eklememiz gerekir.

Modüllerin bağlı olduğu pimleri ve bazı değişkenleri tanımladıktan sonra, kurulum bölümünde kablosuz iletişim adresini başlatmamız gerekir. Sonra döngü bölümünde, önce DHT22 sensöründen verileri okuyoruz. Başlangıçta bu değerler tamsayıdır ve ayrılmıştır, bu yüzden onları tek bir String değişkenine dönüştüreceğiz ve radio.write () işlevini kullanarak bu verileri iç üniteye göndereceğiz. For döngüsünü kullanarak, denetleyicinin gönderme sırasında meşgul olması durumunda alıcının veri alabildiğinden emin olmak için verileri 3 kez göndeririz.

Sonunda güç tüketimini en aza indirgemek için Arduino’yu belirli bir süre uyku moduna geçiririz.

Arduino hava istasyonu iç ünite kodu:

/*
  Arduino Wireless Communication Tutorial
        Indoor unit  - Receiver
  by Dejan Nedelkovski, www.HowToMechatronics.com
 Libraries:
 DS3231 - http://www.rinkydinkelectronics.com/library.php?id=73
 U8G2 - https://github.com/olikraus/u8g2
*/
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <dht.h>
#include <DS3231.h>
#include <U8g2lib.h>
#include <Wire.h>
#define dataPin 8 // DHT22 sensor
dht DHT; // Creats a DHT object
DS3231  rtc(SDA, SCL);
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
RF24 radio(10, 9); // CE, CSN
const byte address[6] = "00001";
char text[6] = "";
int readDHT22, t, h;
String inTemp, inHum, outTemp, outHum;
String rtcTime, rtcDate;
int draw_state = 0;
unsigned long previousMillis = 0;
long interval = 3000;
#define Temperature_20Icon_width 27
#define Temperature_20Icon_height 47
static const unsigned char Temperature_20Icon_bits[] U8X8_PROGMEM = {
 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x80, 0x7f, 0x00, 0x00,
 0xc0, 0xe1, 0x00, 0x00, 0xe0, 0xc0, 0x01, 0x00, 0x60, 0x80, 0xf9, 0x03,
 0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x79, 0x00,
 0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0xf9, 0x03,
 0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x01, 0x00, 0x60, 0x8c, 0x79, 0x00,
 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0xf9, 0x03,
 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x79, 0x00,
 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0xf9, 0x03,
 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00,
 0x70, 0x9e, 0x03, 0x00, 0x38, 0x1e, 0x07, 0x00, 0x18, 0x3e, 0x0e, 0x00,
 0x1c, 0x3f, 0x0c, 0x00, 0x0c, 0x7f, 0x18, 0x00, 0x8c, 0xff, 0x18, 0x00,
 0x8e, 0xff, 0x38, 0x00, 0xc6, 0xff, 0x31, 0x00, 0xc6, 0xff, 0x31, 0x00,
 0xc6, 0xff, 0x31, 0x00, 0x8e, 0xff, 0x38, 0x00, 0x8c, 0xff, 0x18, 0x00,
 0x0c, 0x7f, 0x1c, 0x00, 0x3c, 0x1c, 0x0e, 0x00, 0x78, 0x00, 0x06, 0x00,
 0xe0, 0x80, 0x07, 0x00, 0xe0, 0xff, 0x03, 0x00, 0x80, 0xff, 0x00, 0x00,
 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
#define Humidity_20Icon_width 27
#define Humidity_20Icon_height 47
static const unsigned char Humidity_20Icon_bits[] U8X8_PROGMEM = {
 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
 0x00, 0x70, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00,
 0x00, 0xdc, 0x01, 0x00, 0x00, 0x8e, 0x01, 0x00, 0x00, 0x86, 0x03, 0x00,
 0x00, 0x06, 0x03, 0x00, 0x00, 0x03, 0x07, 0x00, 0x80, 0x03, 0x06, 0x00,
 0x80, 0x01, 0x0c, 0x00, 0xc0, 0x01, 0x1c, 0x00, 0xc0, 0x00, 0x18, 0x00,
 0xe0, 0x00, 0x38, 0x00, 0x60, 0x00, 0x30, 0x00, 0x70, 0x00, 0x70, 0x00,
 0x30, 0x00, 0xe0, 0x00, 0x38, 0x00, 0xc0, 0x00, 0x18, 0x00, 0xc0, 0x01,
 0x1c, 0x00, 0x80, 0x01, 0x0c, 0x00, 0x80, 0x03, 0x0e, 0x00, 0x80, 0x03,
 0x06, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x07,
 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06,
 0x63, 0x00, 0x00, 0x06, 0x63, 0x00, 0x00, 0x06, 0x63, 0x00, 0x00, 0x06,
 0xe3, 0x00, 0x00, 0x06, 0xc7, 0x00, 0x00, 0x06, 0xc6, 0x01, 0x00, 0x07,
 0x86, 0x03, 0x00, 0x03, 0x0e, 0x1f, 0x00, 0x03, 0x0e, 0x1e, 0x80, 0x01,
 0x1c, 0x00, 0xc0, 0x01, 0x38, 0x00, 0xe0, 0x00, 0x78, 0x00, 0x70, 0x00,
 0xf0, 0x00, 0x38, 0x00, 0xe0, 0x07, 0x1f, 0x00, 0x80, 0xff, 0x0f, 0x00,
 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00
};
void setup() {
 radio.begin();
 radio.openReadingPipe(0, address);
 radio.setPALevel(RF24_PA_MIN);
 radio.startListening();
 u8g2.begin();
 rtc.begin();
}
void loop() {
 if (radio.available()) {
   radio.read(&text, sizeof(text)); // Read incoming data
   outTemp = String(text[0]) + String(text[1]) + char(176) + "C"; // Outdoor Temperature
   outHum = String(text[2]) + String(text[3]) + "%"; // Outdoor Humidity
 }
 unsigned long currentMillis = millis();
 if (currentMillis - previousMillis > interval) {
   previousMillis = currentMillis;
   u8g2.firstPage();
   do {
     switch (draw_state ) {
       case 0: drawDate(); break;
       case 1: drawInTemperature(); break;
       case 2: drawInHumidity(); break;
       case 3: drawOutTemperature(); break;
       case 4: drawOutHumidity(); break;
     }
   } while ( u8g2.nextPage() );
   draw_state++;
   if (draw_state > 4) {
     draw_state = 0;
   }
 }
}
void drawDate() {
 String dowa = rtc.getDOWStr();
 dowa.remove(3);
 rtcDate = dowa + " " + rtc.getDateStr();
 u8g2.setFont(u8g2_font_timB14_tr);
 u8g2.setCursor(0, 15);
 rtcTime = rtc.getTimeStr(); // DS3231 RTC time
 rtcTime.remove(5);
 u8g2.print(rtcDate);
 u8g2.setFont(u8g2_font_fub30_tf);
 u8g2.setCursor(8, 58);
 u8g2.print(rtcTime);
}
void drawInTemperature() {
 readDHT22 = DHT.read22(dataPin); // Reads the data from the sensor
 t = DHT.temperature; // Gets the values of the temperature
 inTemp = String(t) + char(176) + "C";
 u8g2.setFont(u8g2_font_helvR14_tr);
 u8g2.setCursor(24, 15);
 u8g2.print("INDOOR");
 u8g2.setFont(u8g2_font_fub30_tf);
 u8g2.setCursor(36, 58);
 u8g2.print(inTemp);
 u8g2.drawXBMP( 0, 17, Temperature_20Icon_width, Temperature_20Icon_height, Temperature_20Icon_bits);
}
void drawInHumidity() {
 h = DHT.humidity; // Gets the values of the humidity
 inHum = String(h) + "%";
 u8g2.setFont(u8g2_font_helvR14_tr);
 u8g2.setCursor(24, 15);
 u8g2.print("INDOOR");
 u8g2.setFont(u8g2_font_fub30_tf);
 u8g2.setCursor(36, 58);
 u8g2.print(inHum);
 u8g2.drawXBMP( 0, 17, Humidity_20Icon_width, Humidity_20Icon_height, Humidity_20Icon_bits);
}
void drawOutTemperature() {
 u8g2.setFont(u8g2_font_helvR14_tr);
 u8g2.setCursor(12, 15);
 u8g2.print("OUTDOOR");
 u8g2.setFont(u8g2_font_fub30_tf);
 u8g2.setCursor(36, 58);
 u8g2.print(outTemp);
 u8g2.drawXBMP( 0, 17, Temperature_20Icon_width, Temperature_20Icon_height, Temperature_20Icon_bits);
}
void drawOutHumidity() {
 u8g2.setFont(u8g2_font_helvR14_tr);
 u8g2.setCursor(12, 15);
 u8g2.print("OUTDOOR");
 u8g2.setFont(u8g2_font_fub30_tf);
 u8g2.setCursor(36, 58);
 u8g2.print(outHum);
 u8g2.drawXBMP( 0, 17, Humidity_20Icon_width, Humidity_20Icon_height, Humidity_20Icon_bits);
}

Açıklama: Diğer tarafta, iç ünitede veya alıcıda, biri DS3231 gerçek zamanlı saat modülü ve diğeri OLED ekran için U8G2 kütüphanesi olmak üzere iki kitaplık daha eklememiz gerekiyor. Daha önce olduğu gibi, aşağıdaki program için gereken örnekleri, pinleri ve bazı değişkenleri tanımlamamız gerekir. Ayrıca burada sıcaklık ve nem simgelerini bitmap olarak tanımlamamız gerekir.

Sıcaklık Simgesi Bitmap:

#define Temperature_20Icon_width 27
#define Temperature_20Icon_height 47
static const unsigned char Temperature_20Icon_bits[] U8X8_PROGMEM = {
 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x80, 0x7f, 0x00, 0x00,
 0xc0, 0xe1, 0x00, 0x00, 0xe0, 0xc0, 0x01, 0x00, 0x60, 0x80, 0xf9, 0x03,
 0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x79, 0x00,
 0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0xf9, 0x03,
 0x60, 0x80, 0x01, 0x00, 0x60, 0x80, 0x01, 0x00, 0x60, 0x8c, 0x79, 0x00,
 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0xf9, 0x03,
 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x79, 0x00,
 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0xf9, 0x03,
 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00, 0x60, 0x9e, 0x01, 0x00,
 0x70, 0x9e, 0x03, 0x00, 0x38, 0x1e, 0x07, 0x00, 0x18, 0x3e, 0x0e, 0x00,
 0x1c, 0x3f, 0x0c, 0x00, 0x0c, 0x7f, 0x18, 0x00, 0x8c, 0xff, 0x18, 0x00,
 0x8e, 0xff, 0x38, 0x00, 0xc6, 0xff, 0x31, 0x00, 0xc6, 0xff, 0x31, 0x00,
 0xc6, 0xff, 0x31, 0x00, 0x8e, 0xff, 0x38, 0x00, 0x8c, 0xff, 0x18, 0x00,
 0x0c, 0x7f, 0x1c, 0x00, 0x3c, 0x1c, 0x0e, 0x00, 0x78, 0x00, 0x06, 0x00,
 0xe0, 0x80, 0x07, 0x00, 0xe0, 0xff, 0x03, 0x00, 0x80, 0xff, 0x00, 0x00,
 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

Bu amaçla, açık kaynak kodlu bir resim editörü olan GIMP’i kullanabiliriz. Bu sayede her şeyi çizebilir ve bitmap (.xbm) olarak dışa aktarabiliriz.

Sonra bu dosyayı bir not defteri kullanarak açabiliriz ve oradan bitmap’i Arduino koduna kopyalayabiliriz.

Burada bitmap’i PROGMEM değişkenini kullanarak sabit olarak tanımlayabileceğimizi ve bu şekilde bitmap’in Arduino kartının SRAM yerine flash bellekte saklanacağını unutmayın.

 
static const unsigned char Temperature_20Icon_bits[] U8X8_PROGMEM // Save in the Flash memory 
static unsigned char Temperature_20Icon_bits[] // Save in the SRAM

Kurulum bölümünde OLED ekranı ve gerçek zamanlı saat modülünü başlatmanın yanı sıra kablosuz iletişimi başlatmamız gerekiyor.

Sonra döngü bölümünde sürekli olarak NRF24L01 modülleri aracılığıyla okunabilecek bir veri olup olmadığını kontrol ediyoruz. True ise, radio.read () işlevini kullanarak okuruz ve ilk iki karakteri temperature String değişkenine ve sonraki iki karakteri humidity String değişkenine kaydederiz.

Ardından, 3 saniyeye ayarladığım aralık değişkeni ile tanımlanan aralıklarda çeşitli verileri ekranda görüntülemek için millis () işlevini kullanırız. Millis () işlevini kullanıyoruz, çünkü bu şekilde kodun geri kalanı tekrar tekrar çalıştırılabilirken, delay () işlevini kullanmamız durumunda, program bu dönemi bekler.

Ardından, U8G2 kütüphanesinin firstPage () ve nextPage () işlevini kullanarak, özel işlevlerle tanımlanan beş farklı ekranı yazdırırız.

DrawDate () özel işlevi, tarih ve saat bilgilerini gerçek zamanlı saat modülünden alır ve uygun şekilde ekrana yazdırır. DrawInTemperature () işlevi iç sıcaklığı okur ve uygun şekilde ekrana yazdırır. Aslında, aynı yöntem tüm verileri ekrana yazdırmak için kullanılır.

 

Hepsi bu kadar. Umarım makalemizi beğenmiş ve yeni bir şeyler öğrenmişsinizdir.

Memnun kaldıysanız aşağıda bulunan “yukarı ok” işaretine tıklayarak +1 puan verebilirsiniz. 

Diğer Güncel Arduino Projeleri için BURAYA TIKLAYABİLİRSİNİZ.

Sizde Robotlara ve Maker’lığa Meraklıysanız Robotik Marketimiz ROBOCOMBO‘yu Ziyaret Edebilirsiniz.

 

Robot El Yapımı – İlginç Arduino Projeleri

Videodaki Robot El Ürünümüzü Satın Almak İsterseniz Bağlantıya Göz Atabilirsiniz.

Okuduğunuz İçin Teşekkürler.

 

Kaynak: howtomechatronics.com/tutorials/arduino/arduino-wireless-weather-station-project/