ESP32 ทำ door magnetic sensorและส่งข้อมูลไปยัง host ผ่าน http

นี้คือโปรแกรมสำหรับใช้งาน ESP32 กับ Door Magnetic Sensor พร้อมส่งข้อมูลไปยัง Host ด้วย HTTP POST และเน้นการประหยัดพลังงานให้มากที่สุด (Low Power Consumption):

แนวทางการออกแบบ:

  1. ใช้ Deep Sleep Mode ของ ESP32 เพื่อประหยัดพลังงาน
  2. ใช้ Magnetic Sensor (เช่น Reed Switch) เชื่อมต่อกับ GPIO ของ ESP32 (ใช้ interrupt เพื่อปลุก ESP32 จาก Deep Sleep เมื่อเซ็นเซอร์เปลี่ยนสถานะ)
  3. ใช้ HTTP POST ส่งข้อมูลไปยัง Host เมื่อเซ็นเซอร์เปลี่ยนสถานะ
  4. ปิด WiFi เมื่อไม่ได้ใช้งาน เพื่อลดการใช้พลังงาน

อธิบายโค้ด:

  1. ตั้งค่า Magnetic Sensor:
    • ใช้ INPUT_PULLUP เพื่อให้ค่าเป็น HIGH โดยปกติเมื่อวงจรเปิด
    • เซ็นเซอร์จะเปลี่ยนเป็น LOW เมื่อวงจรปิด (แม่เหล็กอยู่ใกล้)
  2. Deep Sleep:
    • ใช้ esp_sleep_enable_ext0_wakeup เพื่อปลุก ESP32 เมื่อเซ็นเซอร์เปลี่ยนสถานะ
  3. WiFi & HTTP POST:
    • เปิด WiFi เชื่อมต่อและส่งข้อมูลเมื่อเซ็นเซอร์เปลี่ยนสถานะ
    • ปิด WiFi ทันทีหลังส่งข้อมูลเสร็จ (Deep Sleep จะปิด WiFi ให้อัตโนมัติ)
  4. ประหยัดพลังงาน:
    • ESP32 จะทำงานเฉพาะเมื่อมีการเปลี่ยนสถานะของเซ็นเซอร์
    • ใช้ Deep Sleep ในช่วงเวลาที่ไม่ได้ใช้งาน

การเชื่อมต่อฮาร์ดแวร์:

  1. Magnetic Sensor (Reed Switch):
    • ต่อ Pin หนึ่งของเซ็นเซอร์เข้ากับ GPIO 34 ของ ESP32
    • อีก Pin หนึ่งต่อเข้ากับ GND
  2. Power:
    • ใช้แหล่งจ่ายไฟแบตเตอรี่ (เช่น LiPo) เพื่อใช้งานในระยะยาว
#include <WiFi.h>
#include <HTTPClient.h>

// --------- Configurations ---------
const char* ssid = "Your_SSID";          // ใส่ชื่อ WiFi ของคุณ
const char* password = "Your_PASSWORD";  // ใส่รหัสผ่าน WiFi
const char* serverURL = "http://your-host-url.com/endpoint"; // URL สำหรับส่งข้อมูล

#define MAGNETIC_SENSOR_PIN 34  // Pin ที่เชื่อมต่อ Magnetic Sensor
#define WAKEUP_PIN MAGNETIC_SENSOR_PIN // ใช้ Pin เดียวกันสำหรับ Wakeup จาก Deep Sleep

RTC_DATA_ATTR int lastSensorState = HIGH; // เก็บสถานะล่าสุดของเซ็นเซอร์ (รักษาค่าใน Deep Sleep)

// --------- ฟังก์ชันตั้งค่า WiFi ---------
void connectToWiFi() {
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi connected!");
}

// --------- ฟังก์ชันส่งข้อมูล ---------
void sendDataToHost(int sensorState) {
  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;
    http.begin(serverURL);
    http.addHeader("Content-Type", "application/json"); // ส่งข้อมูลแบบ JSON
    
    String payload = "{\"sensor_state\": " + String(sensorState) + "}";
    int httpResponseCode = http.POST(payload);

    if (httpResponseCode > 0) {
      Serial.println("Data sent successfully: " + payload);
    } else {
      Serial.println("Error sending data: " + String(httpResponseCode));
    }
    http.end();
  } else {
    Serial.println("WiFi not connected!");
  }
}

// --------- ฟังก์ชัน setup ---------
void setup() {
  Serial.begin(115200);

  // อ่านสถานะของ Magnetic Sensor
  pinMode(MAGNETIC_SENSOR_PIN, INPUT_PULLUP); // ใช้ Pull-up Resistor เพื่อให้ค่าเป็น HIGH เมื่อวงจรเปิด
  int currentSensorState = digitalRead(MAGNETIC_SENSOR_PIN);

  // หากสถานะเซ็นเซอร์เปลี่ยนแปลง ส่งข้อมูลไปยัง Host
  if (currentSensorState != lastSensorState) {
    // เชื่อมต่อ WiFi
    connectToWiFi();

    // ส่งข้อมูล
    sendDataToHost(currentSensorState);

    // อัปเดตสถานะเซ็นเซอร์ล่าสุด
    lastSensorState = currentSensorState;
  }

  // เตรียม ESP32 เข้าสู่ Deep Sleep Mode
  esp_sleep_enable_ext0_wakeup(WAKEUP_PIN, LOW); // ปลุกเมื่อเซ็นเซอร์เปลี่ยนเป็น LOW (วงจรปิด)
  Serial.println("Going to sleep...");
  delay(100); // รอเล็กน้อยเพื่อความเสถียร
  esp_deep_sleep_start();
}

// --------- ฟังก์ชัน loop ---------
void loop() {
  // ไม่ต้องใช้งาน loop เพราะเราจะปลุก ESP32 เมื่อเซ็นเซอร์เปลี่ยนสถานะ
}

ถ้าต้องการใช้งาน ถ่าน 18650 และต้องการส่งข้อมูล ปริมาณแบตเตอรี่ที่เหลือ (Battery Level) ไปยัง Host คุณสามารถทำได้โดยการเพิ่มการวัดแรงดันแบตเตอรี่ด้วย ADC (Analog-to-Digital Converter) ของ ESP32 และส่งค่าแรงดันไปพร้อมข้อมูลเซ็นเซอร์ได้เลยครับ

การออกแบบเพิ่มเติม:

  1. ใช้ Voltage Divider Circuit (วงจรแบ่งแรงดัน) เพื่อลดแรงดันจากแบตเตอรี่ (สูงสุด ~4.2V) ให้เหมาะสมกับช่วงแรงดันที่รองรับของ ADC ของ ESP32 (0V-3.3V)
  2. วัดแรงดันแบตเตอรี่ผ่าน ADC (เช่น GPIO 35 หรือ 36)
  3. คำนวณเปอร์เซ็นต์แบตเตอรี่ที่เหลือจากแรงดันที่วัดได้ และส่งไปยัง Host

การเชื่อมต่อฮาร์ดแวร์:

  1. Voltage Divider Circuit:
    • ใช้ตัวต้านทาน 2 ตัว (R1 และ R2) ต่อแบ่งแรงดันจากแบตเตอรี่
    • ค่าที่แนะนำ:
      • R1 = 100 kΩ
      • R2 = 100 kΩ
    • ต่อขาแบตเตอรี่:
      • ขั้วบวกแบตเตอรี่ -> R1 -> R2 -> GND
      • จุดต่อระหว่าง R1 และ R2 -> GPIO (เช่น GPIO 35)
  2. คำนวณแรงดันที่อ่านได้:
    • ใช้สูตรคำนวณแรงดัน:
\( V_{in} = V_{out} \times \left( \frac{R1 + R2}{R2} \right) \)

โดยที่ \(( V_{out} )\) คือแรงดันที่ ADC อ่านได้ และ \(( V_{in} )\) คือแรงดันจากแบตเตอรี่จริง

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

// --------- Configurations ---------
const char* ssid = "Your_SSID";          // ใส่ชื่อ WiFi ของคุณ
const char* password = "Your_PASSWORD";  // ใส่รหัสผ่าน WiFi
const char* serverURL = "http://your-host-url.com/endpoint"; // URL สำหรับส่งข้อมูล

#define MAGNETIC_SENSOR_PIN 34  // Pin ที่เชื่อมต่อ Magnetic Sensor
#define BATTERY_PIN 35          // Pin ADC สำหรับวัดแรงดันแบตเตอรี่
#define WAKEUP_PIN MAGNETIC_SENSOR_PIN // ใช้ Pin เดียวกันสำหรับ Wakeup จาก Deep Sleep

RTC_DATA_ATTR int lastSensorState = HIGH; // เก็บสถานะล่าสุดของเซ็นเซอร์ (รักษาค่าใน Deep Sleep)

// --------- Battery Voltage Divider ---------
const float R1 = 100000.0; // ตัวต้านทาน R1 ในวงจรแบ่งแรงดัน (หน่วย: โอห์ม)
const float R2 = 100000.0; // ตัวต้านทาน R2 ในวงจรแบ่งแรงดัน (หน่วย: โอห์ม)
const float ADC_MAX = 4095.0;    // ค่า ADC สูงสุด (12-bit ADC)
const float REF_VOLTAGE = 3.3;   // แรงดันอ้างอิงของ ADC (3.3V สำหรับ ESP32)
const float BATTERY_FULL = 4.2;  // แรงดันสูงสุดของแบตเตอรี่ 18650 (เมื่อชาร์จเต็ม)
const float BATTERY_EMPTY = 3.0; // แรงดันต่ำสุดของแบตเตอรี่ (ก่อนที่แบตเตอรี่จะหมด)

// --------- ฟังก์ชันคำนวณเปอร์เซ็นต์แบตเตอรี่ ---------
float getBatteryPercentage() {
  int rawADC = analogRead(BATTERY_PIN); // อ่านค่า ADC
  float voltageOut = (rawADC / ADC_MAX) * REF_VOLTAGE; // คำนวณแรงดันที่อ่านได้
  float batteryVoltage = voltageOut * ((R1 + R2) / R2); // คำนวณแรงดันแบตเตอรี่จริง

  // คำนวณเปอร์เซ็นต์แบตเตอรี่
  float batteryPercent = ((batteryVoltage - BATTERY_EMPTY) / (BATTERY_FULL - BATTERY_EMPTY)) * 100.0;
  batteryPercent = constrain(batteryPercent, 0.0, 100.0); // จำกัดค่าให้อยู่ในช่วง 0-100%
  return batteryPercent;
}

// --------- ฟังก์ชันตั้งค่า WiFi ---------
void connectToWiFi() {
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi connected!");
}

// --------- ฟังก์ชันส่งข้อมูล ---------
void sendDataToHost(int sensorState, float batteryLevel) {
  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;
    http.begin(serverURL);
    http.addHeader("Content-Type", "application/json"); // ส่งข้อมูลแบบ JSON
    
    String payload = "{\"sensor_state\": " + String(sensorState) +
                     ", \"battery_level\": " + String(batteryLevel, 2) + "}";
    int httpResponseCode = http.POST(payload);

    if (httpResponseCode > 0) {
      Serial.println("Data sent successfully: " + payload);
    } else {
      Serial.println("Error sending data: " + String(httpResponseCode));
    }
    http.end();
  } else {
    Serial.println("WiFi not connected!");
  }
}

// --------- ฟังก์ชัน setup ---------
void setup() {
  Serial.begin(115200);

  // อ่านสถานะของ Magnetic Sensor
  pinMode(MAGNETIC_SENSOR_PIN, INPUT_PULLUP); // ใช้ Pull-up Resistor เพื่อให้ค่าเป็น HIGH เมื่อวงจรเปิด
  int currentSensorState = digitalRead(MAGNETIC_SENSOR_PIN);

  // อ่านระดับแบตเตอรี่
  float batteryLevel = getBatteryPercentage();

  // หากสถานะเซ็นเซอร์เปลี่ยนแปลง ส่งข้อมูลไปยัง Host
  if (currentSensorState != lastSensorState) {
    // เชื่อมต่อ WiFi
    connectToWiFi();

    // ส่งข้อมูลเซ็นเซอร์และแบตเตอรี่
    sendDataToHost(currentSensorState, batteryLevel);

    // อัปเดตสถานะเซ็นเซอร์ล่าสุด
    lastSensorState = currentSensorState;
  }

  // เตรียม ESP32 เข้าสู่ Deep Sleep Mode
  esp_sleep_enable_ext0_wakeup(WAKEUP_PIN, LOW); // ปลุกเมื่อเซ็นเซอร์เปลี่ยนเป็น LOW (วงจรปิด)
  Serial.println("Going to sleep...");
  delay(100); // รอเล็กน้อยเพื่อความเสถียร
  esp_deep_sleep_start();
}

// --------- ฟังก์ชัน loop ---------
void loop() {
  // ไม่ต้องใช้งาน loop เพราะเราจะปลุก ESP32 เมื่อเซ็นเซอร์เปลี่ยนสถานะ
}

อธิบายเพิ่มเติม:

  1. การวัดแรงดันแบตเตอรี่:
    • อ่านค่า ADC ผ่าน analogRead()
    • ใช้สูตรคำนวณแรงดันจริงของแบตเตอรี่จากค่า ADC และวงจรแบ่งแรงดัน
    • เปลี่ยนแรงดันที่อ่านได้ให้เป็นเปอร์เซ็นต์แบตเตอรี่ โดยอ้างอิงค่าระหว่าง 3.0V (หมด) และ 4.2V (เต็ม)
  2. ส่งข้อมูล:
    • เพิ่มค่า battery_level ใน JSON ที่ส่งไปยัง Host พร้อมกับสถานะเซ็นเซอร์
  3. การประหยัดพลังงาน:
    • ยังคงใช้ Deep Sleep Mode เช่นเดิม
    • การวัดแบตเตอรี่ใช้พลังงานต่ำมากเพราะใช้ ADC ของ ESP32

Leave a Comment