ผู้เขียนบทความ นาย รัชชานนท์ อินเมือง 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