DIY ELECTRONICSEN

← Tüm projeler

Hava İstasyonu

Orta40 dk

Odanın ya da balkonun havasını ölçen küçük bir hava istasyonu: BME280 sensörü sıcaklığı, nemi ve hava basıncını ölçer, Arduino basınçtan yaklaşık rakımı hesaplar. Değerler 16x2 LCD ekranda sayfa sayfa görünür; butona her basışta sonraki sayfaya geçilir, değerler iki saniyede bir yenilenir. İki modülün aynı iki kabloyu (SDA ve SCL) paylaştığı I2C hattını kurmayı, basınçtan rakım hesaplamayı ve LCD'yi titretmeden güncellemeyi öğretir. Kitaplık Yöneticisi'nden "Adafruit BME280 Library" (sorduğu ek kitaplıklarla birlikte) ve "LiquidCrystal I2C" kurulur.

Uygulamada adım adım yap

Gerekli malzemeler

Bağlantı adımları

  1. 1

    Güç kablolarını bağla

    Güç kablolarını bağla

    Kırmızı erkek-erkek jumper kabloyu Arduino'nun güç başlığındaki 5V pinine tak, diğer ucunu breadboard'un üstteki kırmızı çizgili (+) güç sırasına bağla; kablo breadboard'un altından dolanıp gelir. Siyah kabloyu Arduino'nun üst sırasında, 13 numaralı pinin yanındaki GND pinine tak, diğer ucunu üstteki mavi çizgili (−) sıraya bağla. Bu projede yalnızca üstteki güç sıraları kullanılır.

    • Arduino 5V → üstteki kırmızı çizgili (+) sıra (kırmızı kablo)
    • Arduino GND (üst sıradaki) → üstteki mavi çizgili (−) sıra (siyah kablo)
  2. 2

    Butonu tak ve bağla

    Butonu tak ve bağla

    Butonu breadboard'un ortasındaki boşluğun üstüne, bacakları 4. ve 6. sütunlara gelecek şekilde tak. Yeşil kabloyla Arduino'nun 2 numaralı pinini 4. sütunun üst yarısına bağla (BUTTON_PIN 2). Kısa siyah bir kabloyla 6. sütunun üst yarısını üstteki (−) sıraya bağla. Butona basınca 2 numaralı pin GND'ye bağlanır; direnci kod Arduino'nun içindeki pull-up ile sağlar, ayrıca direnç gerekmez.

    • buton → ortadaki boşluğun üstüne, 4. ve 6. sütunlar
    • Arduino pin 2 → 4. sütun, üst yarı (yeşil kablo)
    • 6. sütun, üst yarı → üstteki mavi çizgili (−) sıra (siyah kablo)
  3. 3

    BME280 sensörünü tak ve bağla

    BME280 sensörünü tak ve bağla

    BME280 modülünü, pinleri üst yarıda F sırasına gelecek şekilde tak: SDA 9., SCL 10., GND 11., VIN 12. sütuna gelsin; modülün gövdesi ortadaki boşluğa doğru uzanır, yazıları sana ters görünür. Mavi kabloyla Arduino'nun üst sırasında AREF'in yanındaki SDA pinini 9. sütuna, sarı kabloyla onun yanındaki SCL pinini 10. sütuna bağla. Kısa siyah kabloyla 11. sütunu üstteki (−) sıraya, kısa kırmızı kabloyla 12. sütunu üstteki (+) sıraya bağla. Uno R3'te SDA ve SCL iki yerde vardır: AREF'in yanındaki bu iki pin, A4 ve A5 ile aynı hattır. VIN yazan dört pinli modül 5V ile çalışır; VIN yerine VCC yazan altı pinli kartlar 3.3V'luktur, onların VCC'sini 3.3V pinine bağla.

    • BME280 sensörü SDA → 9. sütun, üst yarı
    • BME280 sensörü SCL → 10. sütun, üst yarı
    • BME280 sensörü GND → 11. sütun, üst yarı
    • BME280 sensörü VIN → 12. sütun, üst yarı
    • Arduino SDA (AREF'in yanındaki) → 9. sütun, üst yarı (mavi kablo)
    • Arduino SCL (AREF'in yanındaki) → 10. sütun, üst yarı (sarı kablo)
    • 11. sütun, üst yarı → üstteki mavi çizgili (−) sıra (siyah kablo)
    • 12. sütun, üst yarı → üstteki kırmızı çizgili (+) sıra (kırmızı kablo)
  4. 4

    LCD ekranı bağla

    LCD ekranı bağla

    LCD'nin arkasındaki I2C modülünün dört pinine erkek-dişi kabloların dişi uçlarını tak. GND'yi üstteki (−) sıraya, VCC'yi üstteki (+) sıraya, SDA'yı 18. sütunun, SCL'yi 19. sütunun üst yarısına bağla. Sonra mavi bir erkek-erkek kabloyla Arduino'nun A4 pinini 18. sütunun, sarı kabloyla A5 pinini 19. sütunun üst yarısına bağla. I2C'de birçok modül aynı iki kabloyu paylaşır: kod onları adresleriyle ayırır (LCD 0x27, BME280 0x76).

    • LCD ekran GND → üstteki mavi çizgili (−) sıra (siyah kablo)
    • LCD ekran VCC → üstteki kırmızı çizgili (+) sıra (kırmızı kablo)
    • LCD ekran SDA → 18. sütun, üst yarı (mavi kablo)
    • LCD ekran SCL → 19. sütun, üst yarı (sarı kablo)
    • Arduino A4 → 18. sütun, üst yarı (mavi kablo)
    • Arduino A5 → 19. sütun, üst yarı (sarı kablo)

Arduino kodu

// Kitaplık Yöneticisi'nden kurulacaklar:
// "Adafruit BME280 Library" (sorduğu ek
// kitaplıklarla) ve "LiquidCrystal I2C"
#include <Wire.h>
#include <Adafruit_BME280.h>
#include <LiquidCrystal_I2C.h>

// Sayfa değiştiren buton
const int BUTTON_PIN = 2;
// İki ölçüm arasındaki süre (ms)
const unsigned long READ_EVERY = 2000;
// Bulunduğun yerin deniz seviyesindeki
// basıncı (hPa): hava durumundaki
// basıncı yazarsan rakım daha doğru çıkar
const float SEA_LEVEL_HPA = 1013.25;

// I2C adresi çoğunda 0x27, bazısında 0x3F
LiquidCrystal_I2C lcd(0x27, 16, 2);
Adafruit_BME280 bme;

// Sayfalar: sıcaklık, nem, basınç, rakım
const int PAGES = 4;
int page = 0;

float temperature = 0;
float humidity = 0;
float pressure = 0;
float altitude = 0;
unsigned long lastRead = 0;

bool lastButton = HIGH;
unsigned long lastChange = 0;

// Bir satırı yazar, kalanını boşlukla
// siler (ekran titremez)
void printLine(int row, const char *text) {
  lcd.setCursor(0, row);
  int n = 0;
  while (text[n] && n < 16) lcd.print(text[n++]);
  while (n++ < 16) lcd.print(' ');
}

// Sensörün kimliği: BME280'de 0x60,
// BMP280'de 0x58, hiç yoksa 0
byte chipId(byte address) {
  Wire.beginTransmission(address);
  Wire.write(0xD0);
  if (Wire.endTransmission() != 0) return 0;
  Wire.requestFrom((int)address, 1);
  return Wire.available() ? Wire.read() : 0;
}

// Sensör bulunamayınca nedenini yazar
void showSensorError() {
  byte id = chipId(0x76);
  if (id == 0) id = chipId(0x77);
  if (id == 0x58) {
    printLine(0, "Bu bir BMP280");
    printLine(1, "Nem olcmez");
    Serial.println("Sensör BMP280: nem ölçmez, BME280 gerekir.");
  } else {
    printLine(0, "Sensor yok");
    printLine(1, "Kablolara bak");
    Serial.println("BME280 bulunamadı: SDA, SCL, VIN, GND kablolarına bak.");
  }
}

// Modüle göre adres 0x76 ya da 0x77
bool startSensor() {
  return bme.begin(0x76) || bme.begin(0x77);
}

void readSensor() {
  bme.takeForcedMeasurement();
  temperature = bme.readTemperature();
  humidity = bme.readHumidity();
  pressure = bme.readPressure() / 100.0;
  // Yükseldikçe basınç düşer (alçakta
  // her ~8 m'de 1 hPa); rakım buradan
  altitude = 44330.0 * (1.0 - pow(pressure / SEA_LEVEL_HPA, 0.1903));

  Serial.print("Sıcaklık: ");
  Serial.print(temperature, 1);
  Serial.print(" °C  Nem: %");
  Serial.print(humidity, 0);
  Serial.print("  Basınç: ");
  Serial.print(pressure, 1);
  Serial.print(" hPa  Rakım: ");
  Serial.print(altitude, 0);
  Serial.println(" m");
}

void showPage() {
  // Üst satır: sayfanın adı ve numarası
  const char *titles[PAGES] = {"Sicaklik", "Nem", "Basinc", "Rakim"};
  char top[17];
  snprintf(top, sizeof(top), "%-12s%d/%d", titles[page], page + 1, PAGES);
  printLine(0, top);

  // Alt satır: değer ve birimi
  char value[10];
  char bottom[17];
  if (page == 0) {
    dtostrf(temperature, 1, 1, value);
    // \xDF ekranın derece işareti
    snprintf(bottom, sizeof(bottom), "%s \xDF" "C", value);
  } else if (page == 1) {
    dtostrf(humidity, 1, 0, value);
    snprintf(bottom, sizeof(bottom), "%%%s", value);
  } else if (page == 2) {
    dtostrf(pressure, 1, 1, value);
    snprintf(bottom, sizeof(bottom), "%s hPa", value);
  } else {
    dtostrf(altitude, 1, 0, value);
    snprintf(bottom, sizeof(bottom), "yaklasik %s m", value);
  }
  printLine(1, bottom);
}

void setup() {
  Serial.begin(9600);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  lcd.init();
  lcd.backlight();
  // Sensör yoksa bulunana dek dener;
  // kabloyu düzeltince kendisi başlar
  while (!startSensor()) {
    showSensorError();
    delay(2000);
  }
  // Hava istasyonu ayarı: istenince bir
  // kez ölçer, arada uyur; ısınmaz,
  // sıcaklığı yüksek göstermez
  bme.setSampling(Adafruit_BME280::MODE_FORCED,
                  Adafruit_BME280::SAMPLING_X1,
                  Adafruit_BME280::SAMPLING_X1,
                  Adafruit_BME280::SAMPLING_X1,
                  Adafruit_BME280::FILTER_OFF);
  readSensor();
  showPage();
  lastRead = millis();
}

void loop() {
  // Butona basınca sonraki sayfa
  bool button = digitalRead(BUTTON_PIN);
  if (button != lastButton && millis() - lastChange > 30) {
    lastChange = millis();
    lastButton = button;
    if (button == LOW) {
      page = (page + 1) % PAGES;
      showPage();
    }
  }
  if (millis() - lastRead >= READ_EVERY) {
    lastRead = millis();
    readSensor();
    showPage();
  }
}

Seri Monitörde göreceğin

SERIAL MONITOR · 9600 BAUD
Sıcaklık: 23.4 °C  Nem: %45  Basınç: 1008.6 hPa  Rakım: 39 m
Sıcaklık: 23.4 °C  Nem: %45  Basınç: 1008.6 hPa  Rakım: 39 m
Sıcaklık: 23.5 °C  Nem: %46  Basınç: 1008.5 hPa  Rakım: 40 m

Sonuç

Kodu yükleyince LCD'de ilk sayfa görünür: üst satırda "Sicaklik 1/4", alt satırda sıcaklık (ör. 23.4 °C). Butona her basışta sonraki sayfaya geçer: nem (ör. %45), basınç (ör. 1008.6 hPa) ve yaklaşık rakım; dördüncüden sonra başa döner. Değerler iki saniyede bir yenilenir ve Seri Monitöre de yazılır. Sensörü parmaklarınla tutunca ya da üstüne hafifçe hohlayınca sıcaklığın ve nemin değiştiğini görürsün. Rakım hava basıncından hesaplanır, hava değiştikçe onlarca metre oynayabilir; daha doğru olsun istersen bulunduğun yerin deniz seviyesi basıncını (hava durumunda "basınç" diye geçer) koddaki SEA_LEVEL_HPA'ya yaz. Ekranda "Sensor yok" yazıyorsa SDA, SCL, VIN ve GND kablolarına bak; düzeltince kendiliğinden başlar. "Bu bir BMP280" yazıyorsa elindeki sensör BMP280'dir: görünüşü aynıdır ama nem ölçmez. Ekranın ışığı yanıyor ama yazı yoksa I2C modülünün arkasındaki mavi trimpotu çevirerek kontrastı ayarla; hâlâ yoksa koddaki 0x27'yi 0x3F yap.

Uygulamada her bağlantıyı tek tek işaretle, envanterindeki parçalarla eşleştir ve kaldığın yerden devam et.

Uygulamada adım adım yap