نحوه کار با سنسور رطوبت سنج خاک

ما در این جا با سنسور رطوبت سنج YL-69 کار می کنیم. این سنسور دارای ۴ اتصال به شرح زیر است:
VCC: اتصال به منبع تغذیه ۳/۳ ولتی
GND: اتصال به GND
DO: خروجی دیجتال (۰ یا ۱)
AO: خروجی آنالوگ
برای تعیین میزان رطوبت، خروجی AO باید به صورت مقابل به ورودی آنالوگ برد NodeMCU متصل گردد.

ما در این پروژه با محیط برنامه نویسی آردوینو کار می کنیم. (شکل مقابل) در این محیط برنامه نویسی دستوراتی که باید در برد ما اجرا شوند را به زبان C++ می نویسیم و خود محیط برنامه نویسی این دستورات را کامپایل کرده و روی برد میریزد. این دستورات با هر بار روشن شدن برد اجرا می شوند. هر برنامه ی NodeMCU دارای ۲ تابع اولیه هستند:

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}

با هر بار روشن شدن یا ریست برد تابع setup() یک بار فراخوانی میشود. در این تابع مقداردهی های اولیه و دستورات مربوط به شروع انجام کار قرار میگرد. پس از پایان فراخوانی تابع setup()، تابع loop() به صورت متوالی در یک حلقه بینهایت فراخوانی میشود. برنامه زمانی خاتمه پیدا میکند که برد خاموش یا توسط دکمه RST ریست شود. در این تابع دستورانی قرار میگیرد که باید بارها به طور متوالی تکرار شوند.

هر پین این برد دارای یه مد ورودی و خروجی است که باید قبل از استفاده از آن این مد را مشخص کرد. مد ورودی برای خواندن ولتاژ روی پین استفاده میشود و مد خروجی برای تنظیم ولتاژ روی آن پین مثلاٌ برای روشن کردن یک چراغ LED استفاده میشود. حال برای خواندن مقدار رطوبت باید میزان ولتاژ روی پایه A0 را که بین ۰ و ۳/۳ ولت است، اندازه گیری کنیم. قبل از کار باید دستور زیر را در تابع setup() قرار دهیم:

pinMode(sensorPin, INPUT);
سپس از تابع analogRead(int pin) برای خواندن ورودی استفاده می کنیم.
int moisture = analogRead(A0);
این تابع ولتاژ ورودی را با عددی در بازه ۰ تا ۱۰۲۳ به ما می دهد که ۰ بیانگر ولتاژ ۰ و عدد ۱۰۲۳ بیانگر ولتاژ ۳/۳ ولت است.

با آزمایش می فهمیم که با این سنسور برای خاک بسیار مرطوب عددی حدود ۲۰۰ و برای خاک خشک حدوداٌ ۱۰۰۰ به دست می آید. پس اگر بخواهیم با درصد رطوبت کار کنیم عدد ۱۰۰۰ را رطوبت ٪۰ و عدد ۲۰۰ را ٪۱۰۰ در نظر میگیریم. برای این تبدیل از تابع map(int value, int fromLow, int fromHigh, int toLow, int toHigh) استفاده میکنیم.

moisture = constrain(moisture, 200, 1000);
moisture = map(moisture, 200, 1000, 100, 0);
توجه کنید که در ابتدا باید مقادیر خارج از بازه را حذف کنیم و بعد از تابع map استفاده کنیم. حالا درصد رطوبت را به درصد برای نمایش داریم.

راه اندازی وبسایت

این بورد باید قادر باشد که در یک شبکه WiFi محلی یک صفحه وب داشته باشد که در آن درصد رطوبت نمایش داده شود. برای این کار متغیر server را تعریف میکنیم که با آن بتوانیم کارهای مربوط به صفحه خود را انجام دهیم. عدد 80 در ESP8266WebServer server(80); به این معناست که سایت روی پورت HTTP اجرا شود. دستورات زیر ابتدا پورت سریال را با پهنای باند 115200 برای ارتباط با کامپیوتر راه اندازی میکند. سپس به یک شبکه وایفای وصل می شود و آدرس صفحه خود را توسط پورت سریال در کامپیوتر چاپ میکند. زمانی که شما وارد این صفحه وب میشوید در واقع یک درخواست به برد ارسال می کنید. سپس درخواست شما بررسی میشود و صفحه مریوطه با کد HTML به شما فرستاده میشود که بتوانید صفحه وب را ببینید. پس ما برای پاسخ دادن به درخواست صفحه اصلی سایت باید یک تابع را مسئول پاسخ دادن به آن درخواست کنیم. در این جا نام این تابع handleRoot() است که با استفاده از server.on("/", handleRoot); آن را مسئول این کار می کنیم. در نهایت با دستور server.begin() سایت راه اندازی میشود. در تابع loop() هم دستور server.handleClient(); درخواست ها را بررسی میکند که درصورتی که درخواستی به صفحه اصلی وجود داشت تابع handleRoot را فراخوانی کند.

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>

const int sensorPin = A0;
const char *ssid = "IUT-City";
const char *password = "";

ESP8266WebServer server(80);

void setup() {
  pinMode(sensorPin, INPUT);

  Serial.begin(115200);

  Serial.print("\nConnecting to ");
  Serial.println(ssid);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.println("");

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  server.on("/", handleRoot);
  server.begin();
  Serial.println("HTTP server started");
}

void loop() {
  server.handleClient();
}

حال باید تابع handleRoot() را بنویسیم. این تابع درصد رطوبت را به دست میاورد و آن را در یک متن HTML جایگذاری میکند. (علامت / یعنی این که متن داخل دابل کوتیشن در خط بعد ادامه پیدا میکند) سپس آن را به عنوان پاسخ درخواست به کاربر میفرستد. توجه کنید که عدد 200 در server.send(200, "text/html", response); نشانه موفقیت در پاسخ است. متن زیر تابع نوشته شده است.

String temp = "\
<!DOCTYPE html>\
<html>\
  <body>\
    <center>\
      <h3>\
        Moisture Level : $moisture$%\
      </h3>\
    </center>\
  </body>\
</html>";

void handleRoot() {
  int moisture = analogRead(sensorPin);
  moisture = constrain(moisture, 200, 1000);
  moisture = map(moisture, 200, 1000, 100, 0);

  String response = temp;
  response.replace("$moisture$", String(moisture));

  server.send(200, "text/html", response);
}

کد زیر متن کل برنامه ست. قسمت بعدی را در این جا ببینید.

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>

bool ledOn = false;
const int sensorPin = A0;
const char *ssid = "IUT-City";
const char *password = "";
String temp = "\
<!DOCTYPE html>\
<html>\
  <body>\
    <center>\
      <h3>\
        Moisture Level : $moisture$%\
      </h3>\
    </center>\
  </body>\
</html>";

ESP8266WebServer server(80);

void handleRoot() {
  int moisture = analogRead(sensorPin);
  moisture = constrain(moisture, 200, 1000);
  moisture = map(moisture, 200, 1000, 100, 0);
  
  String response = temp;
  response.replace("$moisture$", String(moisture));
  server.send(200, "text/html", response);
}

void setup() {
  pinMode(sensorPin, INPUT);
 
  Serial.begin(115200);
 
  Serial.print("\nConnecting to ");
  Serial.println(ssid);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.println("");

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  if (MDNS.begin("esp8266")) {
    Serial.println("MDNS responder started");
  }
  
  server.on("/", handleRoot);
  server.begin();
  Serial.println("HTTP server started");
}

void loop() {
  server.handleClient();
}