บทความ: สร้างระบบเก็บน้ำฝนอัจฉริยะด้วย ESP32-C6 และ LoRaWAN

เรียนรู้วิธีสร้างระบบเก็บน้ำฝนอัตโนมัติที่ตรวจสอบระดับน้ำ ควบคุมปั๊ม และส่งข้อมูลไกลผ่าน LoRaWAN เหมาะสำหรับฤดูฝนที่กำลังจะมาถึง

📅 6 เมษายน 2026⏱️ 15 นาที🎯 ระดับกลาง

ภาพรวมโปรเจกต์

ระบบเก็บน้ำฝนอัจฉริยะนี้เหมาะสำหรับฤดูฝนที่กำลังจะมาถึง โดยอัตโนมัติทั้งหมดและสามารถตรวจสอบระดับน้ำในถังเก็บน้ำฝน ควบคุมปั๊มน้ำเพื่อเติมน้ำเมื่อระดับต่ำ และส่งข้อมูลไปยังศูนย์กลางผ่านเครือข่าย LoRaWAN ที่มีระยะทางไกล

คุณสมบัติหลัก

  • ✅ ตรวจสอบระดับน้ำแบบเรียลไทม์ด้วยเซ็นเซอร์ Ultrasonic กันน้ำ
  • ✅ ควบคุมปั๊มน้ำอัตโนมัติเมื่อระดับน้ำต่ำหรือสูง
  • ✅ สื่อสารไกลผ่าน LoRaWAN (ระยะทางได้ถึง 10 กม.)
  • ✅ แสดงผลบนจอ OLED และเว็บแดชบอร์ด
  • ✅ เตือนภัยผ่าน Line Notify เมื่อมีปัญหา
  • ✅ รองรับพลังงานแสงอาทิตย์สำหรับการติดตั้ง outdoor
  • ✅ เชื่อมต่อกับแพลตฟอร์ม CynoIoT สำหรับวิเคราะห์ข้อมูล

ข้อควรระวัง: โปรเจกต์นี้เกี่ยวข้องกับไฟฟ้าและน้ำ ควรใช้ความระมัดระวังและติดตั้งอุปกรณ์กันน้ำอย่างเหมาะสม หากไม่มั่นใจ ควรขอคำแนะนำจากช่างผู้เชี่ยวชาญ

อุปกรณ์ที่ต้องใช้

Hardware

Microcontroller

ESP32-C6 (WiFi 6, Bluetooth LE, 802.15.4) - ฿150-250

หรือใช้ HELTEC WiFi LoRa 32 V4 (ESP32-S3 + SX1262)

LoRa Module

SX1262 LoRa transceiver module (868/915 MHz) - ฿200-350

หรือใช้บอร์ดที่มี LoRa in-built (เช่น HELTEC)

Water Level Sensor

JSN-SR04T หรือ AJSR04M Waterproof Ultrasonic Sensor - ฿80-150

ระยะวัด 25cm - 4.5m, กันน้ำ IP67

Relay Module

5V Relay Module (1-channel หรือ 2-channel) - ฿40-80

สำหรับควบคุมปั๊มน้ำ

Display

OLED Display 0.96 inch (I2C) - ฿60-100

แสดงผลระดับน้ำและสถานะระบบ

Power Supply

Solar Panel 5V + TP4056 Charger + 18650 Battery - ฿200-350

สำหรับการติดตั้ง outdoor แบบไม่มีสายไฟ

Software & Tools

  • • Arduino IDE 2.x หรือ PlatformIO
  • • ESP32 Board Package (เวอร์ชันล่าสุด)
  • • Library: SX126x-Arduino
  • • Library: NewPing
  • • Library: Adafruit_SSD1306
  • • Library: WiFi, HTTPClient
  • • CynoIoT Account (ฟรี) - cynoiot.com
  • • LoRaWAN Gateway (เช่าหรือสร้างเอง)

การต่อวงจร

ต่อไปนี้คือการเชื่อมต่ออุปกรณ์ต่างๆ กับ ESP32-C6:

// ESP32-C6 Pin Connections:
//
// Ultrasonic Sensor (JSN-SR04T / AJSR04M):
// VCC  -> 3.3V หรือ 5V
// GND  -> GND
// TRIG -> GPIO 4
// ECHO -> GPIO 5
//
// OLED Display (I2C):
// VCC  -> 3.3V
// GND  -> GND
// SDA  -> GPIO 6
// SCL  -> GPIO 7
//
// LoRa Module (SX1262 - SPI):
// VCC   -> 3.3V
// GND   -> GND
// SCK   -> GPIO 15
// MISO  -> GPIO 13
// MOSI  -> GPIO 12
// NSS   -> GPIO 10
// RESET -> GPIO 11
// DIO1  -> GPIO 14
// BUSY  -> GPIO 16
//
// Relay Module:
// VCC -> 5V หรือ 3.3V (ตามขนาด)
// GND -> GND
// IN  -> GPIO 8
                                

💡 เคล็ดลับ:

  • • ใช้ตัวต้านทาน pull-up 10kΩ สำหรับสาย NSS และ RESET ของ LoRa module
  • • เพิ่ม capacitor 100µF ข้าม 3.3V และ GND เพื่อกรอง noise
  • • วาง antenna ของ LoRa ให้ห่างจาก sensor และ relay
  • • ใช้ enclosure กันน้ำ IP65 หรือ IP66 สำหรับ outdoor

ซอฟต์แวร์และโค้ด

โค้ดด้านล่างนี้สำหรับ ESP32-C6 ที่ทำงานเป็น LoRaWAN End Device และส่งข้อมูลระดับน้ำไปยัง Gateway:

#include <Arduino.h>
#include <LoRaWan.h>
#include <NewPing.h>
#include <Adafruit_SSD1306.h>
#include <Wire.h>

// ===== ตั้งค่า LoRaWAN =====
// แก้ไขค่าตาม LoRaWAN Network ของคุณ (The Things Network หรือ ChirpStack)
#define LORA_WAKE_FREQ          923200000  // ความถี่ 923.2 MHz (ไทย)
#define LORA_WAKE_TX_POWER      20        // กำลังส่ง 20 dBm
#define LORA_WAKE_SPREADING     7         // Spreading Factor 7
#define LORA_WAKE_BANDWIDTH     125       // Bandwidth 125 kHz

// LoRaWAN Keys (ต้องแก้ไขตามที่ได้จาก LoRaWAN Network Server)
#define DEV_EUI   "YOUR_DEV_EUI"      // Device EUI
#define APP_EUI   "YOUR_APP_EUI"      // Application EUI
#define APP_KEY   "YOUR_APP_KEY"      // Application Key

// ===== ตั้งค่า Sensor =====
#define TRIGGER_PIN  4
#define ECHO_PIN     5
#define MAX_DISTANCE 450  // ระยะสูงสุด 450 cm
#define TANK_HEIGHT  200  // ความสูงถังน้ำ 200 cm
#define TANK_RADIUS  100  // รัศมีถังน้ำ 100 cm

// ===== ตั้งค่า OLED =====
#define SCREEN_WIDTH  128
#define SCREEN_HEIGHT 64
#define OLED_RESET    -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// ===== ตั้งค่า Relay =====
#define PUMP_RELAY_PIN  8

// ===== ตั้งค่าระดับน้ำ =====
#define WATER_LEVEL_LOW   30    // 30% - เปิดปั๊ม
#define WATER_LEVEL_HIGH  80    // 80% - ปิดปั๊ม

// สร้าง object
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);

// ตัวแปรสำหรับเก็บข้อมูล
float waterLevel = 0;      // ระดับน้ำเป็นเปอร์เซ็นต์
float waterVolume = 0;     // ปริมาณน้ำเป็นลิตร
bool pumpStatus = false;   // สถานะปั๊ม

// ฟังก์ชันสำหรับส่งข้อมูลผ่าน LoRaWAN
void sendLoRaMessage() {
  // สร้าง payload (2 bytes: water level 0-100, pump status 0/1)
  uint8_t payload[2];
  payload[0] = (uint8_t)waterLevel;
  payload[1] = pumpStatus ? 1 : 0;

  // ส่งข้อมูลผ่าน LoRaWAN
  if (LoRaWAN.send(payload, sizeof(payload), 1, false)) {
    Serial.println("LoRaWAN message sent successfully");
    
    // แสดงผลบน OLED
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);
    display.setCursor(0, 0);
    display.println("Data sent via LoRaWAN");
    display.print("Level: ");
    display.print(waterLevel);
    display.println("%");
    display.print("Pump: ");
    display.println(pumpStatus ? "ON" : "OFF");
    display.display();
  } else {
    Serial.println("Failed to send LoRaWAN message");
  }
}

// ฟังก์ชันวัดระดับน้ำ
void measureWaterLevel() {
  // วัดระยะทางจาก sensor ไปยังผิวน้ำ
  unsigned int distance = sonar.ping_cm();
  
  if (distance == 0) {
    distance = MAX_DISTANCE;  // ถ้าไม่พบวัตถุ ให้ถือว่าเป็นระยะสูงสุด
  }
  
  // คำนวณระดับน้ำเป็นเปอร์เซ็นต์
  float emptySpace = distance;  // พื้นที่ว่างเหนือน้ำ
  waterLevel = ((TANK_HEIGHT - emptySpace) / TANK_HEIGHT) * 100;
  
  // จำกัดค่าระหว่าง 0-100
  if (waterLevel < 0) waterLevel = 0;
  if (waterLevel > 100) waterLevel = 100;
  
  // คำนวณปริมาณน้ำ (ลิตร)
  // ปริมาตรถัง = π × r² × h
  float tankVolume = 3.14159 * (TANK_RADIUS * TANK_RADIUS) * TANK_HEIGHT / 1000; // ลิตร
  waterVolume = tankVolume * (waterLevel / 100);
  
  Serial.print("Distance: ");
  Serial.print(distance);
  Serial.println(" cm");
  Serial.print("Water Level: ");
  Serial.print(waterLevel);
  Serial.println("%");
  Serial.print("Volume: ");
  Serial.print(waterVolume);
  Serial.println(" liters");
}

// ฟังก์ชันควบคุมปั๊มน้ำ
void controlPump() {
  if (waterLevel <= WATER_LEVEL_LOW && !pumpStatus) {
    // ระดับน้ำต่ำ - เปิดปั๊ม
    digitalWrite(PUMP_RELAY_PIN, HIGH);
    pumpStatus = true;
    Serial.println("Pump turned ON");
    
    // ส่งแจ้งเตือน (ตัวอย่าง: เชื่อมต่อกับ CynoIoT ในฟังก์ชันถัดไป)
    sendAlert("Pump started");
    
  } else if (waterLevel >= WATER_LEVEL_HIGH && pumpStatus) {
    // ระดับน้ำสูง - ปิดปั๊ม
    digitalWrite(PUMP_RELAY_PIN, LOW);
    pumpStatus = false;
    Serial.println("Pump turned OFF");
    
    sendAlert("Pump stopped");
  }
}

// ฟังก์ชันแสดงผลบน OLED
void updateDisplay() {
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  
  // หัวข้อ
  display.setCursor(0, 0);
  display.println("Rainwater System");
  
  // ระดับน้ำ
  display.setCursor(0, 16);
  display.print("Level: ");
  display.print(waterLevel, 1);
  display.println("%");
  
  // ปริมาณน้ำ
  display.setCursor(0, 26);
  display.print("Volume: ");
  display.print(waterVolume, 0);
  display.println(" L");
  
  // สถานะปั๊ม
  display.setCursor(0, 36);
  display.print("Pump: ");
  display.println(pumpStatus ? "ON " : "OFF");
  
  // สถานะ LoRaWAN
  display.setCursor(0, 46);
  display.print("LoRa: ");
  display.println(LoRaWAN.isJoined() ? "Connected" : "Disconnected");
  
  // Battery
  display.setCursor(0, 56);
  display.print("Battery: ");
  display.print(getBatteryVoltage());
  display.println("V");
  
  display.display();
}

// ฟังก์ชันอ่านแรงดันแบตเตอรี่ (ตัวอย่าง)
float getBatteryVoltage() {
  // สำหรับ ESP32-C6 ที่มี ADC บน pin ขาด
  // ต้องต่อ voltage divider เพื่อวัด 0-5V
  // นี่คือตัวอย่างง่ายๆ ควรปรับแต่งตาม hardware จริง
  return 3.7;  // ค่าจำลอง
}

// ฟังก์ชันส่งแจ้งเตือนไปยัง CynoIoT
void sendAlert(String message) {
  // เชื่อมต่อ WiFi และส่งข้อมูลไปยัง CynoIoT API
  // (ดูรายละเอียดในหัวข้อถัดไป)
  Serial.print("Alert: ");
  Serial.println(message);
}

void setup() {
  Serial.begin(115200);
  while (!Serial);
  
  Serial.println("\n=== Rainwater Harvesting System ===");
  
  // ตั้งค่า pins
  pinMode(PUMP_RELAY_PIN, OUTPUT);
  digitalWrite(PUMP_RELAY_PIN, LOW);  // เริ่มต้นปิดปั๊ม
  
  // เริ่มต้น OLED
  Wire.begin(6, 7);  // SDA=GPIO6, SCL=GPIO7
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println("Failed to start OLED");
    while (1);
  }
  display.display();
  delay(2000);
  
  // แสดงข้อความเริ่มต้น
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(10, 20);
  display.println("Starting...");
  display.display();
  
  // เริ่มต้น LoRaWAN
  LoRaWAN.begin(
    LORA_WAKE_FREQ,
    LORA_WAKE_TX_POWER,
    LORA_WAKE_SPREADING,
    LORA_WAKE_BANDWIDTH
  );
  
  // เข้าร่วม LoRaWAN network
  if (LoRaWAN.join(DEV_EUI, APP_EUI, APP_KEY)) {
    Serial.println("Joined LoRaWAN network successfully");
  } else {
    Serial.println("Failed to join LoRaWAN network");
  }
  
  // เชื่อมต่อ WiFi (สำหรับ CynoIoT)
  WiFi.begin("YOUR_WIFI_SSID", "YOUR_WIFI_PASSWORD");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  
  delay(2000);
}

void loop() {
  // วัดระดับน้ำ
  measureWaterLevel();
  
  // ควบคุมปั๊ม
  controlPump();
  
  // อัปเดตหน้าจอ
  updateDisplay();
  
  // ส่งข้อมูลผ่าน LoRaWAN (ทุก 5 นาที)
  static unsigned long lastSend = 0;
  if (millis() - lastSend > 300000) {  // 5 นาที
    sendLoRaMessage();
    lastSend = millis();
  }
  
  delay(5000);  // วัดทุก 5 วินาที
}
                                

หมายเหตุ: นี่คือโค้ดพื้นฐาน คุณต้องแก้ไข DEV_EUI, APP_EUI, APP_KEY ตามที่ได้จาก LoRaWAN Network Server ของคุณ (เช่น The Things Network หรือ ChirpStack)

การตั้งค่า LoRaWAN

LoRaWAN เป็นเทคโนโลยี wireless ที่เหมาะสำหรับ IoT ที่ต้องการระยะทางไกลและใช้พลังงานต่ำ นี่คือขั้นตอนการตั้งค่า:

1. สมัครบัญชี LoRaWAN Network Server

มีหลาย platform ให้เลือก แนะนำสำหรับผู้เริ่มต้น:

  • The Things Network (TTN) - ฟรี ใช้งานง่าย มี community ที่ดี (thethingsnetwork.org)
  • ChirpStack - Open-source สามารถ self-host ได้ (chirpstack.io)
  • Helium - Decentralized network ที่มี coverage ทั่วโลก (helium.com)

2. สร้าง Application และ Device

ใน TTN Console:

  1. สร้าง Application ใหม่ (เลือก name และ description)
  2. เพิ่ม Device ใหม่ใน Application
  3. เลือก "LoRaWAN 1.0.3" และ "ABP" หรือ "OTAA" activation mode
  4. บันทึก DEV_EUI, APP_EUI และ APP_KEY ที่ได้

3. ตั้งค่า Gateway (ถ้าจำเป็น)

ถ้าพื้นที่ของคุณไม่มี LoRaWAN Gateway cover คุณอาจต้อง:

  • ซื้อ LoRaWAN Gateway (เช่น RAK831, Mikrotik)
  • สร้าง DIY Gateway ด้วย Raspberry Pi + LoRa HAT
  • เช่าบริการ LoRaWAN network จากผู้ให้บริการในไทย

💡 เคล็ดลับ:

ใช้ OTAA (Over-The-Air Activation) สำหรับ production เพราะมีความปลอดภัยกว่า แต่ใช้ ABP (Activation By Personalization) สำหรับการทดสอบเพราะตั้งค่าง่ายกว่า

เชื่อมต่อ CynoIoT Platform

CynoIoT เป็นแพลตฟอร์มที่ช่วยให้คุณเก็บข้อมูล วิเคราะห์ และแสดงผลข้อมูล IoT ได้อย่างง่าย:

การเชื่อมต่อพื้นฐาน

// เพิ่มฟังก์ชันนี้ในโค้ดของคุณ:

#include <WiFi.h>
#include <HTTPClient.h>

const char* cynoiotApiKey = "YOUR_CYNOIOT_API_KEY";
const char* cynoiotDeviceId = "YOUR_DEVICE_ID";

// ฟังก์ชันส่งข้อมูลไปยัง CynoIoT
void sendToCynoIoT(float level, float volume, bool pump) {
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("WiFi not connected");
    return;
  }
  
  HTTPClient http;
  http.begin("https://api.cynoiot.com/v1/data");
  http.addHeader("Content-Type", "application/json");
  http.addHeader("Authorization", cynoiotApiKey);
  
  // สร้าง JSON payload
  String payload = "{";
  payload += "\"device_id\":\"" + String(cynoiotDeviceId) + "\",";
  payload += "\"data\":{";
  payload += "\"water_level\":" + String(level) + ",";
  payload += "\"water_volume\":" + String(volume) + ",";
  payload += "\"pump_status\":" + String(pump ? "true" : "false");
  payload += "}}";
  
  int httpResponseCode = http.POST(payload);
  
  if (httpResponseCode > 0) {
    Serial.print("CynoIoT Response: ");
    Serial.println(httpResponseCode);
    String response = http.getString();
    Serial.println(response);
  } else {
    Serial.print("Error sending to CynoIoT: ");
    Serial.println(httpResponseCode);
  }
  
  http.end();
}

// เรียกใช้ใน loop():
if (millis() - lastCynoIoTSend > 60000) {  // ทุก 1 นาที
  sendToCynoIoT(waterLevel, waterVolume, pumpStatus);
  lastCynoIoTSend = millis();
}
                                

การตั้งค่า Dashboard ใน CynoIoT

  1. สมัครบัญชีที่ cynoiot.com
  2. สร้าง Device ใหม่และบันทึก Device ID และ API Key
  3. สร้าง Dashboard และเพิ่ม widgets:
    • Gauge Chart สำหรับระดับน้ำ (%)
    • Line Chart แสดงประวัติระดับน้ำ
    • Status Indicator สำหรับสถานะปั๊ม
    • Text Widget แสดงปริมาณน้ำ (ลิตร)
  4. ตั้งค่า Alert rules (เช่น แจ้งเตือนเมื่อระดับน้ำ < 20%)

การทดสอบระบบ

1. ทดสอบ Ultrasonic Sensor

  • ใช้ Serial Monitor ตรวจสอบระยะทางที่วัดได้
  • ทดสอบโดยวาง object ที่ระยะต่างๆ (10cm, 50cm, 100cm)
  • ตรวจสอบค่าที่แสดงบน OLED

2. ทดสอบ Relay และ Pump

  • เชื่อมต่อ relay กับมัลติมิเตอร์เพื่อตรวจสอบการทำงาน
  • ทดสอบด้วยการใส่น้ำในถังจริง หรือจำลองด้วยการเคลื่อนย้าย sensor
  • ตรวจสอบว่าปั๊มเปิดเมื่อน้ำต่ำและปิดเมื่อน้ำเต็ม

3. ทดสอบ LoRaWAN

  • ตรวจสอบใน TTN Console ว่ามีข้อมูลเข้ามาหรือไม่
  • ตรวจสอบ Signal Strength (RSSI) และ Signal-to-Noise Ratio (SNR)
  • ทดสอบระยะทางจริงโดยย้าย device ไปไกลๆ

4. ทดสอบ CynoIoT Integration

  • ตรวจสอบว่าข้อมูลปรากฏใน Dashboard หรือไม่
  • ทดสอบการแจ้งเตือน (Alerts) โดยจงใจสร้างสถานการณ์ผิดปกติ
  • ตรวจสอบ Historical Data ว่าบันทึกถูกต้องหรือไม่

⚠️ ปัญหาที่พบบ่อยและวิธีแก้ไข:

  • Sensor วัดระยะไม่ได้: ตรวจสอบการต่อสาย VCC/GND และลองเปลี่ยนตำแหน่งตั้งค่า sensor
  • LoRaWAN เชื่อมต่อไม่ได้: ตรวจสอบ DEV_EUI, APP_EUI, APP_KEY และ frequency (923.2 MHz สำหรับไทย)
  • Relay ทำงานไม่ถูกต้อง: ตรวจสอบว่าใช้ 5V relay หรือ 3.3V relay และต่อสาย GND ร่วมกัน
  • OLED ไม่ติด: ตรวจสอบ I2C address (โดยปกติ 0x3C หรือ 0x3D) และการต่อสาย SDA/SCL

สรุป

ในบทความนี้ คุณได้เรียนรู้วิธีสร้างระบบเก็บน้ำฝนอัจฉริยะที่:

  • ✅ ตรวจสอบระดับน้ำอัตโนมัติด้วย ultrasonic sensor
  • ✅ ควบคุมปั๊มน้ำอัตโนมัติ
  • ✅ ส่งข้อมูลไกลผ่าน LoRaWAN ได้ถึง 10 กม.
  • ✅ เชื่อมต่อกับ CynoIoT Platform สำหรับ monitoring และ analytics
  • ✅ ทำงานด้วยพลังงานแสงอาทิตย์ได้

ถัดไป

  • • เพิ่ม sensor วัด pH และ EC สำหรับระบบ hydroponics
  • • สร้าง Mobile App สำหรับ monitoring ระยะไกล
  • • เพิ่ม AI/ML สำหรับทำนายปริมาณน้ำฝน
  • • เชื่อมต่อกับ Home Assistant สำหรับ automation ภายในบ้าน

หากคุณชอบบทความนี้ อย่าลืมแชร์ให้เพื่อนๆ และติดตามบทความเกี่ยวกับ ESP32, IoT และ electronics เพิ่มเติม: