Bu projede, NodeMCU V3 (ESP8266) ve HC-SR04 ultrasonik mesafe sensörü kullanarak bir depodaki sıvı seviyesini yüzde (%) ve mesafe (cm) cinsinden ölçüyoruz. Web arayüzü üzerinden Boş Seviye ve Dolu Seviye mesafelerini dinamik olarak kalibre edip EEPROM (kalıcı hafıza) üzerine kaydedebilirsiniz. Ayrıca anlık veriler Seri Port Ekranı üzerinden de takip edilebilir.
Şemadaki pin eşleşmeleri şu şekildedir:
map fonksiyonu ile).
Aşağıdaki kodu NodeMCU'nuza yükleyerek web arayüzünden kalibrasyon yapabilir ve Seri Port üzerinden anlık çıktı alabilirsiniz:
// ESP8266 HC-SR04 Kalibrasyonlu Sıvı Seviye Ölçer ve Web Server
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>
// Wi-Fi Ağ Bilgileriniz
const char* ssid = "WIFI_ADINIZ";
const char* password = "WIFI_SIFRENIZ";
// Pin Tanımlamaları
#define TRIG_PIN D1
#define ECHO_PIN D2
#define LED_PIN D4
ESP8266WebServer server(80);
// Kalibrasyon Değişkenleri (EEPROM Adresleri: 0 ve 4)
float bosMesafe = 100.0; // cm (Sıvı en uzaktayken)
float doluMesafe = 10.0; // cm (Sıvı sensöre en yakınken)
// Zamanlayıcı
unsigned long lastMeasureTime = 0;
float mevcutMesafe = 0.0;
int mevcutYuzde = 0;
// EEPROM'dan Kalibrasyon Değerlerini Oku
void readEEPROM() {
EEPROM.get(0, bosMesafe);
EEPROM.get(4, doluMesafe);
// İlk açılışta mantıksız değer gelirse varsayılan atansın
if (isnan(bosMesafe) || bosMesafe <= 0) bosMesafe = 100.0;
if (isnan(doluMesafe) || doluMesafe <= 0) doluMesafe = 10.0;
}
// Sensörden Mesafe Okuma (cm)
float getMesafe() {
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
long duration = pulseIn(ECHO_PIN, HIGH, 30000); // 30ms timeout
if (duration == 0) return -1; // Hatalı okuma
return (duration * 0.0343) / 2.0;
}
// Ana Web Arayüzü
void handleRoot() {
String html = "<!DOCTYPE html><html lang='tr'><head><meta charset='UTF-8'>";
html += "<meta name='viewport' content='width=device-width, initial-scale=1.0'>";
html += "<meta http-equiv='refresh' content='3'>"; // 3 saniyede bir otomatik yenile
html += "<title>Sıvı Seviye Kontrolü</title>";
html += "<style>";
html += "body { font-family: Arial, sans-serif; text-align: center; background: #f0f2f5; margin-top: 20px; }";
html += ".card { background: white; max-width: 480px; margin: 0 auto; padding: 20px; border-radius: 12px; box-shadow: 0 4px 10px rgba(0,0,0,0.1); }";
html += ".progress-bg { background: #e0e0e0; border-radius: 20px; height: 30px; width: 100%; overflow: hidden; margin: 15px 0; }";
html += ".progress-bar { background: #2196F3; height: 100%; width: " + String(mevcutYuzde) + "%; text-align: center; color: white; line-height: 30px; font-weight: bold; transition: width 0.5s; }";
html += "input[type='number'] { width: 80px; padding: 6px; margin: 5px; border: 1px solid #ccc; border-radius: 4px; }";
html += ".btn { background: #28a745; color: white; padding: 8px 15px; border: none; border-radius: 4px; cursor: pointer; font-weight: bold; margin-top: 10px; }";
html += "</style></head><body>";
html += "<div class='card'>";
html += "<h2 style='color:#007acc;'>Sıvı Seviye Takibi</h2><hr>";
html += "<h3>Seviye: %" + String(mevcutYuzde) + "</h3>";
html += "<div class='progress-bg'>";
html += "<div class='progress-bar'>%" + String(mevcutYuzde) + "</div>";
html += "</div>";
html += "<p><strong>Ölçülen Mesafe:</strong> " + String(mevcutMesafe, 1) + " cm</p><hr>";
html += "<h4>Kalibrasyon Ayarları</h4>";
html += "<form action='/kalibre' method='GET'>";
html += "Boş Depo Mesafesi (cm): <input type='number' step='0.1' name='bos' value='" + String(bosMesafe, 1) + "'><br>";
html += "Dolu Depo Mesafesi (cm): <input type='number' step='0.1' name='dolu' value='" + String(doluMesafe, 1) + "'><br>";
html += "<input class='btn' type='submit' value='Kalibrasyon Kaydet'>";
html += "</form>";
html += "</div></body></html>";
server.send(200, "text/html", html);
}
// Kalibrasyon Değerlerini Kaydetme Endpoint'i
void handleKalibre() {
if (server.hasArg("bos") && server.hasArg("dolu")) {
bosMesafe = server.arg("bos").toFloat();
doluMesafe = server.arg("dolu").toFloat();
// EEPROM'a Yaz
EEPROM.put(0, bosMesafe);
EEPROM.put(4, doluMesafe);
EEPROM.commit();
Serial.println("\n[KALİBRASYON GÜNCELLENDİ]");
Serial.print("Yeni Boş Mesafe: "); Serial.print(bosMesafe); Serial.println(" cm");
Serial.print("Yeni Dolu Mesafe: "); Serial.print(doluMesafe); Serial.println(" cm");
}
// Ana sayfaya yönlendir
server.sendHeader("Location", "/");
server.send(302, "text/plain", "Yönlendiriliyor...");
}
void setup() {
Serial.begin(115200);
EEPROM.begin(512);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(LED_PIN, OUTPUT);
readEEPROM();
// Wi-Fi Bağlantısı
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.print("\nWi-Fi Ağına Bağlanılıyor");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\n[BAĞLANDI]");
Serial.print("Web Server IP Adresi: ");
Serial.println(WiFi.localIP());
// Server Yönlendirmeleri
server.on("/", handleRoot);
server.on("/kalibre", handleKalibre);
server.begin();
Serial.println("HTTP Sunucusu Başlatıldı.");
}
void loop() {
server.handleClient();
// Her 1 saniyede bir ölçüm ve Seri Port çıktısı yap
if (millis() - lastMeasureTime >= 1000) {
lastMeasureTime = millis();
float m = getMesafe();
if (m > 0) {
mevcutMesafe = m;
// Mesafeyi % Yüzdeye Dönüştür
// bosMesafe (uzak) = %0, doluMesafe (yakın) = %100
float yuzde = map(mevcutMesafe * 10, bosMesafe * 10, doluMesafe * 10, 0, 100);
mevcutYuzde = constrain((int)yuzde, 0, 100);
// Uyarı LED'i (%10 altındaysa yansın)
digitalWrite(LED_PIN, (mevcutYuzde <= 10) ? HIGH : LOW);
// Seri Port Çıktısı
Serial.print("Mesafe: ");
Serial.print(mevcutMesafe, 1);
Serial.print(" cm | Doluluk: %");
Serial.print(mevcutYuzde);
Serial.print(" | [Ayar - Boş: ");
Serial.print(bosMesafe, 1);
Serial.print(" cm, Dolu: ");
Serial.print(doluMesafe, 1);
Serial.println(" cm]");
} else {
Serial.println("[HATA] Sensör okuma yapamadı!");
}
}
}
115200 baud hızında Seri Port Ekranını açın. Kartın aldığı IP adresini ve anlık ölçülen mesafeleri oradan takip edebilirsiniz.45 cm) Boş Depo Mesafesi kutusuna girin.5 cm) Dolu Depo Mesafesi kutusuna girin.Henüz yorum yapılmamış. İlk yorumu siz yapın!