นี้คือโปรแกรมสำหรับใช้งาน ESP32 กับ Door Magnetic Sensor พร้อมส่งข้อมูลไปยัง Host ด้วย HTTP POST และเน้นการประหยัดพลังงานให้มากที่สุด (Low Power Consumption):
แนวทางการออกแบบ:
- ใช้ Deep Sleep Mode ของ ESP32 เพื่อประหยัดพลังงาน
- ใช้ Magnetic Sensor (เช่น Reed Switch) เชื่อมต่อกับ GPIO ของ ESP32 (ใช้ interrupt เพื่อปลุก ESP32 จาก Deep Sleep เมื่อเซ็นเซอร์เปลี่ยนสถานะ)
- ใช้ HTTP POST ส่งข้อมูลไปยัง Host เมื่อเซ็นเซอร์เปลี่ยนสถานะ
- ปิด WiFi เมื่อไม่ได้ใช้งาน เพื่อลดการใช้พลังงาน
อธิบายโค้ด:
- ตั้งค่า Magnetic Sensor:
- ใช้
INPUT_PULLUPเพื่อให้ค่าเป็น HIGH โดยปกติเมื่อวงจรเปิด - เซ็นเซอร์จะเปลี่ยนเป็น LOW เมื่อวงจรปิด (แม่เหล็กอยู่ใกล้)
- ใช้
- Deep Sleep:
- ใช้
esp_sleep_enable_ext0_wakeupเพื่อปลุก ESP32 เมื่อเซ็นเซอร์เปลี่ยนสถานะ
- ใช้
- WiFi & HTTP POST:
- เปิด WiFi เชื่อมต่อและส่งข้อมูลเมื่อเซ็นเซอร์เปลี่ยนสถานะ
- ปิด WiFi ทันทีหลังส่งข้อมูลเสร็จ (Deep Sleep จะปิด WiFi ให้อัตโนมัติ)
- ประหยัดพลังงาน:
- ESP32 จะทำงานเฉพาะเมื่อมีการเปลี่ยนสถานะของเซ็นเซอร์
- ใช้ Deep Sleep ในช่วงเวลาที่ไม่ได้ใช้งาน
การเชื่อมต่อฮาร์ดแวร์:
- Magnetic Sensor (Reed Switch):
- ต่อ Pin หนึ่งของเซ็นเซอร์เข้ากับ GPIO 34 ของ ESP32
- อีก Pin หนึ่งต่อเข้ากับ GND
- 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 และส่งค่าแรงดันไปพร้อมข้อมูลเซ็นเซอร์ได้เลยครับ
การออกแบบเพิ่มเติม:
- ใช้ Voltage Divider Circuit (วงจรแบ่งแรงดัน) เพื่อลดแรงดันจากแบตเตอรี่ (สูงสุด ~4.2V) ให้เหมาะสมกับช่วงแรงดันที่รองรับของ ADC ของ ESP32 (0V-3.3V)
- วัดแรงดันแบตเตอรี่ผ่าน ADC (เช่น GPIO 35 หรือ 36)
- คำนวณเปอร์เซ็นต์แบตเตอรี่ที่เหลือจากแรงดันที่วัดได้ และส่งไปยัง Host
การเชื่อมต่อฮาร์ดแวร์:
- Voltage Divider Circuit:
- ใช้ตัวต้านทาน 2 ตัว (R1 และ R2) ต่อแบ่งแรงดันจากแบตเตอรี่
- ค่าที่แนะนำ:
- R1 = 100 kΩ
- R2 = 100 kΩ
- ต่อขาแบตเตอรี่:
- ขั้วบวกแบตเตอรี่ -> R1 -> R2 -> GND
- จุดต่อระหว่าง R1 และ R2 -> GPIO (เช่น GPIO 35)
- คำนวณแรงดันที่อ่านได้:
- ใช้สูตรคำนวณแรงดัน:
โดยที่ \(( 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 เมื่อเซ็นเซอร์เปลี่ยนสถานะ
}
อธิบายเพิ่มเติม:
- การวัดแรงดันแบตเตอรี่:
- อ่านค่า ADC ผ่าน
analogRead() - ใช้สูตรคำนวณแรงดันจริงของแบตเตอรี่จากค่า ADC และวงจรแบ่งแรงดัน
- เปลี่ยนแรงดันที่อ่านได้ให้เป็นเปอร์เซ็นต์แบตเตอรี่ โดยอ้างอิงค่าระหว่าง 3.0V (หมด) และ 4.2V (เต็ม)
- อ่านค่า ADC ผ่าน
- ส่งข้อมูล:
- เพิ่มค่า
battery_levelใน JSON ที่ส่งไปยัง Host พร้อมกับสถานะเซ็นเซอร์
- เพิ่มค่า
- การประหยัดพลังงาน:
- ยังคงใช้ Deep Sleep Mode เช่นเดิม
- การวัดแบตเตอรี่ใช้พลังงานต่ำมากเพราะใช้ ADC ของ ESP32