ระบบรดน้ำทางเกษตรโดยใช้ LoRa

ผู้เขียนบทความ นาย รัชชานนท์ อินเมือง COE#15

วิชา 04-513-201 การโปรแกรมคอมพิวเตอร์ขั้นสูง 1/2566

1. ความเป็นมา

เนื่องด้วยปัญหาการเกษตรในพื้นที่ที่อินเตอร์เน็ตเข้าไม่ถึงหรือจะเป็นพื้นที่ห่างไกลอีกทั้งเส้นทางที่ไปฟาร์มยังเป็นเส้นทางที่ลำบากทำให้ระบบSmart farm ทั่วไปที่ใช้สัญญาณ wi-fi เข้าไม่ถึง จนทำให้ระบบต่างๆไม่สามารถทำงานได้เต็มประสิทธิภาพทำให้เกษตรกรที่อยากได้ความสะดวกสบายแต่กลับนำระบบ smart farm มาใช้ไม่ได้เนื่องจากความจำกัดของพื้นที่

จากการศึกษาดังกล่าวและสำรวจสภาพปัญหาจากพื้นที่ที่สัญญาณเข้าไม่ถึงเพราะฉะนั้นนักศึกษาจึงได้ทำการแก้ปัญหาดังกล่าวโดยนำเทคโนโลยีการสื่อสารที่สามารถควบคุมเซ็นเซอร์หรือที่เรียกว่าLora โดยLoraสามารถนำมาประยุกต์ใช้กับพื้นที่ที่ไม่มีสัญญาณwifiได้ และสามารถสั่งควบคุมเซ็นเซอร์ทางระยะไกลได้พบว่าโครงการชิ้นนี้ตอบสนองต่อเกษตกรอย่างมากดังนั้นเพื่อแก้ปัญหาดังกล่าวผู้ประดิษฐ์จึงได้จัดทำระบบรดน้ำทางการเกษตรโดยใช้ LoRa ขึ้น

2. วัตถุประสงค์

2.1 เพื่อศึกษาและเข้าใจการเขียนโปรแกรมเพื่อสั่งการLoRa

2.2 เพื่อนำความรู้จากLoraไปใช้จริง

2.3 เพื่อพิสูจน์ว่าสามารถใช้สัญญาณLoraสามารถควบคุมเซ็นเซอร์ได้จริง

3. ขอบเขต

3.1 ระบบสามารถควบคุมเซ็นเซอร์ต่างๆได้

3.2 สามารถสั่งงานระบบได้ผ่านระยะไกล

3.3 ระบบยังสามารถใช้งานโดยไม่ต้องมี wifi ได้

4. ประโยชน์ที่คาดว่าจะได้รับ

4.1 สามารถเข้าใจเกี่ยวกับสัญญาณLora

4.2 สามารถนำความรู้จากสัญญาณLoraไปใช้งานจริง

4.3 สามารถประยุกต์ใช้สัญญาณLoraเพื่อควบคุมเซ็นเซอร์ได้ในระยะไกล

5. ความรู้เกี่ยวข้อง

5.1 LoRa คืออะไร
LoRa เป็นเทคโนโลยีการเชื่อมต่อไร้สายเหมาะสำหรับงาน Internet of Thing (IoT) ที่ข้อมูลหลักๆมาจากเซ็นเซอร์รับข้อมูลต่างๆ โดยเป็นเทคโนโลยีที่มีการใช้งานแพร่หลาย บริษัทชั้นนำผู้พัฒนาไมโครคอนโทรลเลอร์พัฒนาอุปกรณ์มารองรับการเชื่อมต่อ LoRa เทคโนโลยี LoRa มีจุดเด่นในเรื่องระยะทางในการสื่อสาร สามารถรับ-ส่งข้อมูลได้ในระยะไกลประหยัดพลังงานจากการใช้พลังงานในช่วงรับ-ส่งข้อมูลค่อนข้างต่ำ ในช่วงที่ไม่ส่งข้อมูล สามารถกำหนดให้อุปกรณ์เข้าสู่โหมดประหยัดพลังงานได้ ทำให้ประหยัดค่าใช้จ่าย

5.1 โมดูล sx1278 ra-01

โมดูล SX1278 RA-01 คือโมดูลสื่อสารไร้สายที่ใช้เทคโนโลยี LoRaและระบบ RF (Radio Frequency) เพื่อการสื่อสารไร้สายระยะไกล โมดูลนี้มักถูกนำมาใช้ในการส่งข้อมูลในระยะทางที่ไกลโดยไม่ต้องใช้โปรโตคอลการสื่อสารที่เหมาะกับการสื่อสารในระยะทางสั้น เช่น Wi-Fi หรือ Bluetooth นอกจากนี้ SX1278 RA-01 ยังสนับสนุนการสื่อสารแบบทฤษฎีการสื่อสารแบบ Spread Spectrum หรือการกระจายสเปคตรัม ซึ่งช่วยลดโอกาสที่จะเกิดการรบกวนในการสื่อสารและช่วยให้สามารถทำงานในสภาพแวดล้อมที่มีระยะทางไกลและมีข้อกำหนดเสถียรสูงโมดูล SX1278 RA-01 นั้นมีความสามารถในการส่งข้อมูลที่อยู่ในช่วงความถี่ของ 433MHz หรือ 868MHz ซึ่งทำให้เหมาะสำหรับการใช้งานในหลายประเภทของแอปพลิเคชันที่ต้องการการสื่อสารไร้สายระยะไกล

นี่คือโค้ดที่ให้โมดูล Lora เชื่อมต่อกันโดยทั้งสองตัวเชื่อมต่อกันที่คลื่นความถี่ 433 MHzโดยใช้โค้ดนี้ทั้งตัวส่งและตัวรับ

LoRa.setPins(ss, rst, dio0);
 if (!LoRa.begin(433E6)) {
  Serial.println("LoRa initialization failed.");
  while (1);
}

5.3 Water flow senser

“Water flow sensor” หรือ “เซ็นเซอร์การไหลของน้ำ” เป็นอุปกรณ์ที่ใช้เพื่อวัดปริมาณน้ำที่ไหลผ่านท่อหรือทางน้ำในระบบต่าง ๆ โดยมักใช้ในแอปพลิเคชันที่ต้องการการควบคุมหรือการวัดปริมาณน้ำ เช่น ในระบบน้ำประปา ระบบรดน้ำพืช หรือแอปพลิเคชันที่เกี่ยวข้องกับการจัดการน้ำในอุตสาหกรรมหรือโรงงาน.

เซ็นเซอร์น้ำที่ไหลมักมีลักษณะที่สามารถตรวจจับการไหลของน้ำโดยใช้วิธีต่าง ๆ เช่นการใช้ตัวตรวจสัญญาณไฟฟ้า, ตรวจวัดการหมุนเวียนของลูกปืนหรือตัวร่อง, หรือใช้วิธีการอื่น ๆ ที่สามารถตรวจวัดการไหลของน้ำได้. บางตัวยังมีความสามารถในการวัดปริมาณน้ำที่ไหลผ่านในหน่วยของปริมาณหน่วยต่อหน่วยเวลา เช่น ลิตรต่อนาทีหรือแม้กระทั่งกัลลอนต่อนาที.

การใช้งานเซ็นเซอร์น้ำที่ไหลมักช่วยให้ระบบสามารถตรวจจับและตอบสนองต่อการเปลี่ยนแปลงในการไหลของน้ำได้, ทำให้มีประสิทธิภาพในการจัดการและควบคุมการใช้น้ำ.

long currentMillis = 0;
long previousMillis = 0;
int interval = 1000; // 1 วินาที
float calibrationFactor = 4.5;
volatile byte pulseCount;
byte pulse1Sec = 0;
float flowRate;
unsigned int flowMilliLitres;
unsigned long totalMilliLitres;

void setup() {
    pinMode(SENSOR, INPUT_PULLUP);
    
    pulseCount = 0;
    flowRate = 0.0;
    flowMilliLitres = 0;
    previousMillis = 0;


    attachInterrupt(digitalPinToInterrupt(SENSOR), pulseCounter, FALLING);
}
void loop() {

    currentMillis = millis();

    if (currentMillis - previousMillis > interval) {
    pulse1Sec = pulseCount;
    pulseCount = 0;
    
    flowRate = ((1000.0 / (millis() - previousMillis)) * pulse1Sec) / calibrationFactor;
    previousMillis = millis();

    flowMilliLitres = (flowRate / 60) * 1000;

    Serial.print("Flow rate: ");
    Serial.print(int(flowRate));
    Serial.print("L/min");
    Serial.print("\t");

   Serial.print("Output Liquid Quantity: ");
   Serial.print(flowMilliLitres);
   Serial.print("mL / ");
   Serial.print(flowMilliLitres / 1000);
   Serial.println("L");
}

นี่คือตัวอย่างโค้ดของ water flow senser ที่จะทำการเปลี่ยนพลังงานกลเป็นตัวเลขและเป็นปริ้นค่าน้ำที่กำลังไหลอยู่กับน้ำที่ไหลไปทั้งหมดโดยจะประกาศตัวแปรเพื่อเก็บน้ำและตัวแปรที่นำไปใช้กับสูตรคำนวณ

โค้ดที่ให้ตัวรับส่งค่าน้ำไปยังตัวส่ง

    LoRa.beginPacket();
    LoRa.print(flowRate);
    LoRa.endPacket();

โค้ดที่รับค่าน้ำมาจากตัวรับและแสดงค่าผ่านจอ Lcd และ หน้า Blynk

 void loop() { 

    
int packetSize = LoRa.parsePacket();
    if (packetSize) {
      float receivedFlowRate = LoRa.parseFloat();
      
      Serial.print("Received Flow rate: ");
      Serial.print(receivedFlowRate);
      Serial.println("L/min");
      
      LoRa.beginPacket();
      LoRa.print(receivedFlowRate);
      Blynk.virtualWrite(V0, receivedFlowRate);
      LoRa.endPacket();
      
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("FlowRate : ");
      lcd.setCursor(11, 0);
      lcd.print(receivedFlowRate);
    }
    

6. ผลการดำเนินงาน

การทำงานของระบบนี้ก้คือการสั่งเปิดปิดปั้มน้ำโดยจะเป็นการสั่งเปิดปิดรีเลย์

ขั้นตอนที่ 1

เป็นการสั่งเปิดรีเลย์ผ่าน Blynk ที่ตัวส่งก็คือเชื่อม wifi ใว้กับแค่ตัวส่งและให้ตัวส่งส่งค่าไปที่ตัวรับผ่านสัญญาณ Lora เพื่อทำการเปิดรีเลย์

ขั้นตอนที่ 2

เมื่อตัวส่งไม่ได้เชื่อ wifi จะมีปุ่มที่จะสามารถเปิดรีเลย์ได้ติดอยู่กับตัวส่งซึ่งในระบบนี่มีโค้ดที่สามารถเชื่อมต่อ wifiก่อนแต่ถ้าเชื่อมไม่ได้จะใช้เป็นโหมดออฟไลน์แทนแต่ระบบนี้ถ้าไม่ได้เชื่อมต่อwifiไม่สามารถสั่งการผ่านBlynkและดูค่าน้ำผ่านBlynkแต่สามารถเปิดปิดได้โดยปุ่มและดูค่าผ่านจอที่ติดอยู่กับตัวส่งแทน

โค้ดในส่วนของตัวส่ง

#define BLYNK_PRINT Serial

#define BLYNK_TEMPLATE_ID "TMPL6G42yr2St"
#define BLYNK_TEMPLATE_NAME "LoRa"
#define BLYNK_AUTH_TOKEN "uJs2bMGIdQOrdPaiXki3ndevSWfdt-SA"

#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>

char auth[] = "uJs2bMGIdQOrdPaiXki3ndevSWfdt-SA";
char ssid[] = "wifi";
char pass[] = "00000000";

#include <SPI.h>
#include <LoRa.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

#define ss 5
#define rst 14
#define dio0 2

#define buttonPin 25

int lastButtonState = LOW;
bool relayState = LOW;
LiquidCrystal_I2C lcd(0x27, 20, 4);

unsigned long wifiConnectStartTime = 0;
bool isWifiConnected = false;

void setup() {

  Serial.begin(115200);
  pinMode(buttonPin, INPUT_PULLUP);

  lcd.init();
  lcd.backlight();

  Serial.println("กำลังเชื่อมต่อ Wi-Fi...");
  WiFi.begin(ssid, pass);

  wifiConnectStartTime = millis();

  while (!isWifiConnected && (millis() - wifiConnectStartTime <= 10000)) {
    if (WiFi.status() == WL_CONNECTED) {
      isWifiConnected = true;
      Blynk.begin(auth, ssid, pass);

    }
  }

  if (isWifiConnected) {
    Serial.println("เชื่อมต่อ Wi-Fi สำเร็จ!");
  } else {
    Serial.println("ไม่สามารถเชื่อมต่อ Wi-Fi ภายใน 10 วินาที จะทำการใช้โหมดออฟไลน์แทน");

  }

  LoRa.setPins(ss, rst, dio0);
  if (!LoRa.begin(433E6)) {
    Serial.println("LoRa initialization failed.");
    while (1);
  }
}

void loop() {
  if (isWifiConnected) {
    int packetSize = LoRa.parsePacket();
    if (packetSize) {
      float receivedFlowRate = LoRa.parseFloat();
      
      Serial.print("Received Flow rate: ");
      Serial.print(receivedFlowRate);
      Serial.println("L/min");
      
      LoRa.beginPacket();
      LoRa.print(receivedFlowRate);
      Blynk.virtualWrite(V0, receivedFlowRate);
      LoRa.endPacket();
      
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("FlowRate : ");
      lcd.setCursor(11, 0);
      lcd.print(receivedFlowRate);
    }
    Blynk.run();
    
    // ตรวจสอบปุ่มและส่งคำสั่งไปที่ตัวรับ
    int buttonState = digitalRead(buttonPin);
    if (buttonState != lastButtonState) {
      if (buttonState == LOW) {
        // ส่งคำสั่งไปที่ตัวรับเมื่อปุ่มถูกกด
        LoRa.beginPacket();
        LoRa.print("TurnOnRelay");
        LoRa.endPacket();
        }else if (buttonState == HIGH) {
        LoRa.beginPacket();
        LoRa.print("TurnOffRelay");
        LoRa.endPacket();
      }
      lastButtonState = buttonState;
    }
  } else {
    int packetSize = LoRa.parsePacket();
    if (packetSize) {
      float receivedFlowRate = LoRa.parseFloat();
      Serial.print("Received Flow rate: ");
      Serial.print(receivedFlowRate);
      Serial.println("L/min");
      
      LoRa.beginPacket();
      LoRa.print(receivedFlowRate);
      LoRa.endPacket();
      
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("FlowRate : ");
      lcd.setCursor(11, 0);
      lcd.print(receivedFlowRate);
    }
    
    // ตรวจสอบปุ่มและส่งคำสั่งไปที่ตัวรับ
    int buttonState = digitalRead(buttonPin);
    if (buttonState != lastButtonState) {
      if (buttonState == HIGH) {
        // ส่งคำสั่งไปที่ตัวรับเมื่อปุ่มถูกกด
        LoRa.beginPacket();
        LoRa.print("TurnOnRelay");
        LoRa.endPacket();
      }else if (buttonState == LOW) {
      LoRa.beginPacket();
      LoRa.print("TurnOffRelay");
      LoRa.endPacket();
      
      lastButtonState = buttonState;
     }
   }
 }
}
BLYNK_WRITE(V1) {
  int value = param.asInt();
  if (isWifiConnected) {
    if (value == 1) {
      LoRa.beginPacket();
      LoRa.print("TurnOnRelay");
      relayState = HIGH;

      LoRa.endPacket();
    } else if (value == 0) {
      LoRa.beginPacket();
      LoRa.print("TurnOffRelay");
      relayState = LOW;

      LoRa.endPacket();
    }
  
}
}

โค้ดในส่วนของตัวรับ

#include <SPI.h>
#include <LoRa.h>

#define ss 5
#define rst 14
#define dio0 2
#define SENSOR 27
#define relay 4

long currentMillis = 0;
long previousMillis = 0;
int interval = 1000; // 1 วินาที
float calibrationFactor = 4.5;
volatile byte pulseCount;
byte pulse1Sec = 0;
float flowRate;
unsigned int flowMilliLitres;
unsigned long totalMilliLitres;

void IRAM_ATTR pulseCounter() {
  pulseCount++;
}

void setup() {
  Serial.begin(115200);
  LoRa.setPins(ss, rst, dio0);
  if (!LoRa.begin(433E6)) {
    Serial.println("LoRa initialization failed.");
    while (1);
  }

  pinMode(SENSOR, INPUT_PULLUP);
  pinMode(relay, OUTPUT);
  digitalWrite(relay, LOW); // เริ่มต้นเป็นสถานะปิด (Off)

  pulseCount = 0;
  flowRate = 0.0;
  flowMilliLitres = 0;
  previousMillis = 0;

  attachInterrupt(digitalPinToInterrupt(SENSOR), pulseCounter, FALLING);
}

void loop() {
  currentMillis = millis();

  if (currentMillis - previousMillis > interval) {
    pulse1Sec = pulseCount;
    pulseCount = 0;

    flowRate = ((1000.0 / (millis() - previousMillis)) * pulse1Sec) / calibrationFactor;
    previousMillis = millis();

    flowMilliLitres = (flowRate / 60) * 1000;

    Serial.print("Flow rate: ");
    Serial.print(int(flowRate));
    Serial.print("L/min");
    Serial.print("\t");

    Serial.print("Output Liquid Quantity: ");
    Serial.print(flowMilliLitres);
    Serial.print("mL / ");
    Serial.print(flowMilliLitres / 1000);
    Serial.println("L");

    LoRa.beginPacket();
    LoRa.print(flowRate);
    LoRa.endPacket();
  }

  int packet = LoRa.parsePacket();
  if (packet) {
    String receivedCommand = LoRa.readString();
    if (receivedCommand == "TurnOnRelay") {
      digitalWrite(relay, HIGH); // เปิดรีเลย์
    } else if (receivedCommand == "TurnOffRelay") {
      digitalWrite(relay, LOW); // ปิดรีเลย์
    }
  }
}

การทดลอง

การทดลองที่ 1

การทดลองโดยการเชื่อมต่อโมดูลLora เข้าด้วยกันที่คลื่นความถี่ 433MHzผลการทดลองปรากฎว่าโมดูลทั้งสองตัวสามารเชื่อมต่อกันได้จริง

การทดลองที่ 2

การทดลองโดยการส่งค่าน้ำที่ไหลจากตัวรับกลับมาที่ตัวส่งผลที่ได้คือสามารถส่งค่ากลับมาที่ตัวส่งได้แบบเรียลไทม์

การทดลองที่ 3

ทดลองโดยการสั่งเปิดปิดรีเลย์โดยให้ตัวส่งเชื่อมwifiและสั่งการตัวส่งผ่าน Blynk โดยกดปุ่มที่หน้าจอมือถือผลที่ได้คือสามารถเปิดปิดรีเลย์ได้จริงและปั้มสามารถทำงานได้

การทดลองที่ 4

การทดสอบระยะไกลทดสอบสอบโดยการเพิ่มระยะการสั่งเปิดปิดเรื่อยว่าไกลได้แค่ไหนโดยจากการทดลองพบว่าในระยะที่ไม่มีสิ่งกีดขวางระยะที่ได้จะอยู่ที่ประมาณ 150-200เมตร

7. สรุปผลและข้อเสนอแนะ

สรุปผล

การทดลองต่างๆของอุปกรณ์ การสั่งงานผ่าน Blynk สามารถสั่งการได้เพื่อเปิดการทำงานรีเลย์ที่อยู่ฝั่งตัวรับได้และตัวรับสามารถรับค่าจาก water flow senser และส่งค่ากลับที่ตัวส่งเพื่อแสดงผลผ่านจอ LCD และแอปผลิเคชั่น Blynk ได้และเมื่อน้ำไหลถึงพิกัดรีเลย์จะทำการปิดโดยอัตโนมัติ ส่วนระยะความไกลที่ได้อยู่ที่ประมาณ 150-200เมตร

ข้อเสนอแนะ

สามารถอัพเกรดโมดูลLoraเป็นตัวที่ดีกว่านี้ได้เพื่อเพิ่มระยะในการส่งสัญญาณได้ไกลยิ่งขึ้นและมีความเสถียรมากขึ้น หรือจะอัพเกรดโดยการเพิ่ทเซ็นเซอร์ที่ตัวรับเพิ่มเพื่อจะได้เป็นแบบสมาชฟาร์มมากขึ้นไปอีก

8. ข้อมูลอ้างอิง

[1] โมดูลsx1278 ra-01 สืบค้นจาก
https://www.cybertice.com/การใช้งานsx1278ra-01
[2] water flow senser สืบค้นจาก
https://www.allnewstep.com/b/warterflowsenser
[3] การใช้งาน ESP32สืบค้นจาก

https://www.analogread.com/article/

[4] การใช้งาน Blynk สืบค้นจาก

https://www.cybertice.com/สอนเชื่อมต่อblynk

วีดีโอการทำงานของระบบรดน้ำทางการเกษตรโดยใช้สัญญาณ LoRa

You may also like...

ใส่ความเห็น

อีเมลของคุณจะไม่แสดงให้คนอื่นเห็น ช่องข้อมูลจำเป็นถูกทำเครื่องหมาย *