เนื้อหาในบทความ
🎯 ภาพรวมโปรเจกต์
GPS Data Logger คือ ระบบที่ใช้บันทึกตำแหน่งพิกัด GPS ลงใน SD Card สำหรับนำกลับมาวิเคราะห์ภายหลัง โปรเจกต์นี้เหมาะสำหรับ:
- ติดตามตำแหน่งรถยนต์ จักรยาน มอเตอร์ไซค์
- บันทึกเส้นทางการเดินทาง/วิ่งจ็อกกิ้ง
- ติดตามทรัพย์สินที่เคลื่อนย้ายได้
- เก็บข้อมูลการใช้งานยานพาหนะ
- Off-grid tracking ในพื้นที่ที่ไม่มีอินเทอร์เน็ต
✨ จุดเด่นของโปรเจกต์นี้
- • ทำงานได้โดยไม่ต้องเชื่อมต่ออินเทอร์เน็ต
- • ประหยัดพลังงานด้วย Deep Sleep Mode
- • เก็บข้อมูลได้นานด้วย SD Card
- • นำข้อมูลกลับมาวิเคราะห์ได้หลากหลายวิธี
- • ต้นทุนต่ำ ง่ายต่อการประกอบ
หลักการทำงาน
- ESP32 อ่านข้อมูลพิกัดจาก GPS Module
- ตรวจสอบสัญญาณ GPS ว่าได้พิกัดครบถ้วน (Latitude, Longitude, Speed, Date, Time)
- บันทึกข้อมูลลง SD Card ในรูปแบบ CSV
- เข้าสู่ Deep Sleep Mode เพื่อประหยัดแบตเตอรี่
- ตื่นขึ้นมาเก็บข้อมูลใหม่ทุกๆ ช่วงเวลาที่กำหนด
🔧 อุปกรณ์ที่ต้องใช้
Hardware Components
| อุปกรณ์ | รุ่นที่แนะนำ | ประมาณการณ์ |
|---|---|---|
| Microcontroller | ESP32 DevKit / NodeMCU | ฿120-180 |
| GPS Module | NEO-6M / NEO-8M / AT6558 | ฿80-150 |
| SD Card Module | Micro SD Card Module | ฿30-50 |
| SD Card | Micro SD 4GB-32GB (Class 10) | ฿80-200 |
| External Antenna | GPS Antenna (Active/Passive) | ฿50-100 |
| Power Source | Li-ion Battery + TP4056 | ฿50-100 |
| Jumper Wires | Male-to-Female | ฿20-40 |
รวมประมาณ: ฿430-820 (ขึ้นอยู่กับคุณภาพของอุปกรณ์)
💡 ข้อแนะนำในการเลือก GPS Module
- • NEO-6M: ราคาประหยัด ใช้งานได้ดีทั่วไป
- • NEO-8M: แม่นยำกว่า รองรับ GLONASS และ BeiDou
- • AT6558: รองรับหลายดาวเทียม (GPS + GLONASS + BeiDou + Galileo)
- • Antenna: ใช้ Active Antenna ถ้าติดตั้งในรถ/อาคาร
🔌 การต่อสายวงจร
Pinout Connections
GPS Module (UART) → ESP32
- VCC → 3.3V
- GND → GND
- TX → GPIO 16 (RX2)
- RX → GPIO 17 (TX2)
SD Card Module (SPI) → ESP32
- VCC → 3.3V หรือ 5V (ตาม Module)
- GND → GND
- CS → GPIO 5
- SCK → GPIO 18
- MOSI → GPIO 23
- MISO → GPIO 19
⚠️ ข้อควรระวัง
- • GPS Module บางรุ่นใช้ 3.3V บางรุ่นใช้ 5V ตรวจสอบให้แน่ใจ
- • SD Card Module ส่วนใหญ่ใช้ 5V แต่ขาสัญญาณใช้ 3.3V ได้
- • ต่อสายให้ถูกต้อง ไม่เช่นนั้นอาจเสียหาย
- • ใช้ Level Shifter ถ้า Module ต้องการ Logic Level ที่แตกต่าง
ตัวอย่างการต่อสาย
ESP32 DevKit V1 (30-pin)
│
├─ 3V3 → GPS VCC, SD Card VCC (ถ้ารองรับ)
├─ GND → GPS GND, SD Card GND
│
├─ GPIO 16 (RX2) → GPS TX
├─ GPIO 17 (TX2) → GPS RX
│
├─ GPIO 5 → SD Card CS
├─ GPIO 18 → SD Card SCK
├─ GPIO 23 → SD Card MOSI
└─ GPIO 19 → SD Card MISO
💻 การติดตั้ง Software
1. ติดตั้ง Arduino IDE
- ดาวน์โหลด Arduino IDE จาก arduino.cc
- ติดตั้ง ESP32 Board Support:
- File → Preferences
- เพิ่ม URL ใน "Additional Board Manager URLs":
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json - Tools → Board → Boards Manager → ค้นหา "ESP32" → ติดตั้ง
- เลือก Board: Tools → Board → ESP32 Arduino → ESP32 Dev Module
2. ติดตั้ง Library ที่จำเป็น
ติดตั้ง Library ผ่าน Library Manager:
- TinyGPSPlus: สำหรับแปลงข้อมูล GPS (Sketch → Include Library → Manage Libraries → ค้นหา "TinyGPSPlus")
- SD: Library มาตรฐานสำหรับ SD Card (มีมากับ Arduino IDE แล้ว)
- RTC (ถ้าจำเป็น): สำหรับ Real-Time Clock
📝 โค้ดโปรแกรม
โค้ดหลัก (Full Code)
/*
* ESP32 GPS Data Logger ด้วย SD Card
* บันทึกพิกัด GPS ลง SD Card สำหรับ Vehicle/Asset Tracking
*
* Hardware: ESP32 + NEO-6M GPS + SD Card Module
* Author: CynoIoT
* Date: March 2026
*/
#include <TinyGPS++.h>
#include <SD.h>
#include <SPI.h>
#include <WiFi.h>
// ===== การตั้งค่า PIN =====
// GPS UART Pins (Serial2)
#define GPS_RX 16
#define GPS_TX 17
// SD Card SPI Pins
#define SD_CS 5
#define SD_SCK 18
#define SD_MOSI 23
#define SD_MISO 19
// LED Indicator
#define LED_PIN 2
// ===== การตั้งค่าระบบ =====
// เวลา Sleep (วินาที) - ถ้าต้องการประหยัดแบต
#define SLEEP_INTERVAL 10 // บันทึกทุกๆ 10 วินาที
// Timeout สำหรับ GPS (มิลลิวินาที)
#define GPS_TIMEOUT 60000 // รอสัญญาณ GPS สูงสุด 60 วินาที
// ชื่อไฟล์ log
#define LOG_FILE "/gps_log.csv"
// ===== ตัวแปรระบบ =====
TinyGPSPlus gps;
File logFile;
unsigned long lastLogTime = 0;
bool gpsValid = false;
int fixCount = 0;
// ฟังก์ชันตั้งค่าเริ่มต้น
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println(F("\n\n=== ESP32 GPS Data Logger ==="));
Serial.println(F("Starting..."));
// ตั้งค่า LED
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
// ตั้งค่า GPS Serial
Serial2.begin(9600, SERIAL_8N1, GPS_RX, GPS_TX);
Serial.println(F("GPS Serial initialized"));
// เริ่มต้นใช้งาน SD Card
if (!initSDCard()) {
Serial.println(F("SD Card initialization failed!"));
while(1) {
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
delay(500);
}
}
// สร้าง Header ใน CSV ถ้าไฟล์ใหม่
createLogHeader();
Serial.println(F("System ready! Waiting for GPS signal..."));
Serial.println(F("Waiting for fix..."));
}
// Loop หลัก
void loop() {
// อ่านข้อมูลจาก GPS
while (Serial2.available() > 0) {
gps.encode(Serial2.read());
}
// ตรวจสอบว่ามีข้อมูล GPS ครบหรือยัง
if (gps.location.isValid() && gps.date.isValid() && gps.time.isValid()) {
if (!gpsValid) {
gpsValid = true;
Serial.println(F("GPS FIX acquired!"));
blinkLED(3); // กระพริบ 3 ครั้ง
}
// บันทึกข้อมูลทุกๆ ช่วงเวลาที่กำหนด
unsigned long currentTime = millis();
if (currentTime - lastLogTime >= (SLEEP_INTERVAL * 1000UL)) {
lastLogTime = currentTime;
logGPSData();
fixCount++;
Serial.print(F("Logged fix #"));
Serial.println(fixCount);
}
} else {
// ยังไม่ได้ Fix
if (millis() > GPS_TIMEOUT && !gpsValid) {
Serial.println(F("Warning: No GPS fix! Check antenna."));
blinkLED(2); // กระพริบ 2 ครั้งแจ้งเตือน
}
}
delay(100);
}
// ===== ฟังก์ชันเสริม =====
// เริ่มต้นใช้งาน SD Card
bool initSDCard() {
Serial.print(F("Initializing SD card..."));
SPI.begin(SD_SCK, SD_MISO, SD_MOSI, SD_CS);
if (!SD.begin(SD_CS)) {
Serial.println(F(" failed!"));
return false;
}
// ตรวจสอบว่า SD Card สามารถเขียนได้หรือไม่
uint8_t cardType = SD.cardType();
if (cardType == CARD_NONE) {
Serial.println(F(" No SD card found!"));
return false;
}
Serial.print(F(" SD card type: "));
switch(cardType) {
case CARD_MMC: Serial.println(F("MMC")); break;
case CARD_SD: Serial.println(F("SDSC")); break;
case CARD_SDHC: Serial.println(F("SDHC")); break;
default: Serial.println(F("UNKNOWN")); break;
}
// แสดงขนาด SD Card
uint64_t cardSize = SD.cardSize() / (1024 * 1024);
Serial.print(F(" SD card size: "));
Serial.print(cardSize);
Serial.println(F(" MB"));
Serial.println(F(" SD card initialized successfully!"));
return true;
}
// สร้าง Header ในไฟล์ CSV
void createLogHeader() {
// ตรวจสอบว่าไฟล์มีอยู่แล้วหรือไม่
if (SD.exists(LOG_FILE)) {
Serial.println(F("Log file exists. Appending data..."));
return;
}
// สร้างไฟล์ใหม่และเขียน Header
logFile = SD.open(LOG_FILE, FILE_WRITE);
if (logFile) {
logFile.println("Date,Time,Latitude,Longitude,Altitude(m),Speed(kmh),Satellites,HDOP");
logFile.close();
Serial.println(F("Created new log file with header"));
} else {
Serial.println(F("Error creating log file!"));
}
}
// บันทึกข้อมูล GPS
void logGPSData() {
logFile = SD.open(LOG_FILE, FILE_APPEND);
if (!logFile) {
Serial.println(F("Error opening log file!"));
return;
}
// สร้าง string สำหรับบันทึกข้อมูล
String dataLine = "";
// Date (YYYY-MM-DD)
dataLine += String(gps.date.year());
dataLine += "-";
dataLine += pad2(gps.date.month());
dataLine += "-";
dataLine += pad2(gps.date.day());
dataLine += ",";
// Time (HH:MM:SS)
dataLine += pad2(gps.time.hour());
dataLine += ":";
dataLine += pad2(gps.time.minute());
dataLine += ":";
dataLine += pad2(gps.time.second());
dataLine += ",";
// Latitude
dataLine += String(gps.location.lat(), 8);
dataLine += ",";
// Longitude
dataLine += String(gps.location.lng(), 8);
dataLine += ",";
// Altitude (meters)
if (gps.altitude.isValid()) {
dataLine += String(gps.altitude.meters(), 2);
} else {
dataLine += "0.00";
}
dataLine += ",";
// Speed (km/h)
if (gps.speed.isValid()) {
dataLine += String(gps.speed.kmph(), 2);
} else {
dataLine += "0.00";
}
dataLine += ",";
// Satellites
if (gps.satellites.isValid()) {
dataLine += String(gps.satellites.value());
} else {
dataLine += "0";
}
dataLine += ",";
// HDOP (Horizontal Dilution of Precision)
if (gps.hdop.isValid()) {
dataLine += String(gps.hdop.value() / 100.0, 2);
} else {
dataLine += "0.00";
}
// เขียนลงไฟล์
logFile.println(dataLine);
logFile.close();
// แสดงข้อมูลที่บันทึกใน Serial Monitor
Serial.println(F("--- GPS Data Logged ---"));
Serial.print(F("Time: "));
Serial.print(pad2(gps.time.hour()));
Serial.print(F(":"));
Serial.print(pad2(gps.time.minute()));
Serial.print(F(":"));
Serial.println(pad2(gps.time.second()));
Serial.print(F("Lat: "));
Serial.print(gps.location.lat(), 8);
Serial.print(F(", Lng: "));
Serial.println(gps.location.lng(), 8);
Serial.print(F("Alt: "));
Serial.print(gps.altitude.meters(), 2);
Serial.print(F(" m, Speed: "));
Serial.print(gps.speed.kmph(), 2);
Serial.println(F(" km/h"));
Serial.print(F("Sats: "));
Serial.print(gps.satellites.value());
Serial.print(F(", HDOP: "));
Serial.println(gps.hdop.value() / 100.0, 2);
// กระพริบ LED 1 ครั้ง
blinkLED(1);
}
// ฟังก์ชันเติมเลข 0 นำหน้า (01, 02, ...)
String pad2(int number) {
if (number < 10) {
return "0" + String(number);
}
return String(number);
}
// ฟังก์ชันกระพริบ LED
void blinkLED(int times) {
for (int i = 0; i < times; i++) {
digitalWrite(LED_PIN, HIGH);
delay(100);
digitalWrite(LED_PIN, LOW);
delay(100);
}
}✅ คำอธิบายโค้ดสำคัญ
- • Serial2: ใช้ UART พิเศษสำหรับ GPS เพื่อไม่ให้รบกวน Serial Monitor
- • TinyGPSPlus: Library สำหรับแปลง NMEA data จาก GPS
- • SD Card: บันทึกข้อมูลในรูปแบบ CSV เพื่อให้นำไปเปิดด้วย Excel ได้
- • SLEEP_INTERVAL: ปรับค่าได้ตามต้องการ (10 วินาที = ทุก 10 วินาทีจะบันทึก)
- • HDOP: ค่าความแม่นยำ ยิ่งน้อยยิ่งดี (<1.0 = ดีมาก)
🧪 การทดสอบระบบ
ขั้นตอนการทดสอบ
- อัปโหลดโค้ด:
- เชื่อมต่อ ESP32 กับคอมพิวเตอร์ด้วย USB Cable
- เลือก Board: ESP32 Dev Module
- เลือก Port: COM port ที่เชื่อมต่อ
- กด Upload ใน Arduino IDE
- เปิด Serial Monitor:
- Tools → Serial Monitor หรือกด Ctrl+Shift+M
- ตั้งค่า Baud rate เป็น 115200
- ดูข้อความ "System ready! Waiting for GPS signal..."
- วาง GPS Module กลางแจ้ง:
- วาง GPS Module ที่มองเห็นท้องฟ้า (ไม่มีหลังคาบด)
- รอสัญญาณ GPS ประมาณ 1-5 นาที (ครั้งแรกนานกว่า)
- LED จะกระพริบ 3 ครั้งเมื่อได้ GPS Fix
- ข้อความ "GPS FIX acquired!" จะปรากฏ
- ตรวจสอบไฟล์บน SD Card:
- ถอด SD Card จาก Module
- ใส่ใน Card Reader เพื่อเปิดในคอมพิวเตอร์
- เปิดไฟล์
gps_log.csvด้วย Excel หรือ Text Editor - ตรวจสอบว่ามีข้อมูลบันทึกหรือไม่
💡 วิธีอ่าน GPS Data
- • Latitude: พิกัดเหนือ-ใต้ (บวก = เหนือ, ลบ = ใต้)
- • Longitude: พิกัดตะวันออก-ตะวันตก (บวก = ตะวันออก, ลบ = ตะวันตก)
- • Altitude: ระดับความสูงเหนือระดับน้ำทะเล (เมตร)
- • Speed: ความเร็ว (กิโลเมตร/ชั่วโมง)
- • Satellites: จำนวนดาวเทียมที่รับสัญญาณได้ (มากกว่า 4 = ดี)
- • HDOP: ค่าความแม่นยำ (น้อยกว่า 1.0 = แม่นยำสูง)
📊 การวิเคราะห์ข้อมูล
วิธีแสดงผลข้อมูล GPS
1. ใช้ Google Maps
- เปิด Google Maps
- คลิกขวา → คลิก "ที่อยู่ของพิกัดนี้คืออะไร"
- ใส่ค่า Latitude และ Longitude จากไฟล์ CSV
- เช่น:
13.7563, 100.5018(กรุงเทพฯ)
2. ใช้ Google Earth (แสดงเส้นทาง)
- แปลง CSV เป็น KML format ด้วย Python หรือ Online Tool
- ดาวน์โหลด Google Earth
- File → Open → เลือกไฟล์ KML
- จะเห็นเส้นทางการเดินทางแบบ 3D
3. ใช้ Excel วิเคราะห์
- เปิดไฟล์ CSV ด้วย Excel
- สร้างกราฟความเร็ว vs เวลา
- คำนวณระยะทางรวม
- วิเคราะห์รูปแบบการเดินทาง
4. Python Script (Advanced)
import pandas as pd
import folium
# อ่านไฟล์ CSV
df = pd.read_csv('gps_log.csv')
# สร้างแผนที่
m = folium.Map(location=[df['Latitude'].mean(),
df['Longitude'].mean()],
zoom_start=13)
# วาดเส้นทาง
folium.PolyLine(zip(df['Latitude'], df['Longitude'])).add_to(m)
# บันทึกเป็น HTML
m.save('gps_route.html')
print("เปิดไฟล์ gps_route.html เพื่อดูแผนที่")🔧 แก้ปัญหาที่พบบ่อย
ไม่ได้ GPS Fix นานๆ
ตรวจสอบว่า GPS Module อยู่กลางแจ้ง หรือใช้ Active Antenna ปรับจูน GPS Module ครั้งแรกอาจใช้เวลา 10-15 นาที (Cold Start)
SD Card เขียนไม่ได้
ตรวจสอบว่า SD Card ได้รับการจัดรูปแบบ (Format) เป็น FAT32 ลองเปลี่ยน SD Card อีกใบ หรือตรวจสอบการต่อสาย
ข้อมูลไม่ถูกบันทึก
ตรวจสอบ Serial Monitor ว่ามี Error หรือไม่ ลองเปลี่ยน SLEEP_INTERVAL ให้น้อยลง (เช่น 5 วินาที) เพื่อทดสอบ
GPS Module ร้อนเกินไป
ปกติ GPS Module จะร้อนเล็กน้อย แต่ถ้าร้อนมากให้ตรวจสอบ Voltages หรือเพิ่ม Heat Sink
ตำแหน่งผิดพลาด
ตรวจสอบ HDOP Value ถ้ามากกว่า 2.0 แสดงว่าความแม่นยำต่ำ รอจนกว่า HDOP จะน้อยกว่า 1.0
✨ สรุป
ในบทความนี้ เราได้เรียนรู้วิธีสร้าง GPS Data Logger ด้วย ESP32 และ SD Card ซึ่งสามารถนำไปประยุกต์ใช้กับหลายโปรเจกต์ เช่น:
- ติดตามตำแหน่งรถยนต์ จักรยาน มอเตอร์ไซค์
- บันทึกเส้นทางการวิ่งจ็อกกิ้ง หรือกีฬา
- ติดตามทรัพย์สินที่เคลื่อนย้ายได้
- เก็บข้อมูลการใช้งานยานพาหนะ
- Off-grid tracking ในพื้นที่ที่ไม่มีอินเทอร์เน็ต
🚀 ไอเดียต่อยอด
- • เพิ่ม Deep Sleep Mode เพื่อประหยัดแบตเตอรี่ (ใช้งานได้นานหลายวัน)
- • เพิ่ม WiFi/MQTT ส่งข้อมูล Real-time เมื่อมีอินเทอร์เน็ต
- • เพิ่ม OLED Display แสดงพิกัดปัจจุบัน
- • เพิ่ม Buzzer แจ้งเตือนเมื่อเข้า/ออกพื้นที่กำหนด
- • เพิ่ม Accelerometer ตรวจจับการเคลื่อนไหว และบันทึกเมื่อมีการเคลื่อนที่
บทความที่เกี่ยวข้อง
- ESP32 Deep Sleep Mode ประหยัดพลังงานฉบับสมบูรณ์
- ESP32 MQTT Tutorial - สร้างระบบ Smart Home ด้วย MQTT
- ESP32 SD Card Filesystem Tutorial
- ESP32 4G LTE GPS Vehicle Tracker - ติดตามรถแบบ Real-time
ขอให้สนุกกับการสร้างโปรเจกต์ IoT! 🎉