บทความ: สร้าง GPS Data Logger ด้วย ESP32 และ SD Card บันทึกตำแหน่งรถยนต์

เรียนรู้วิธีสร้างระบบบันทึกข้อมูล GPS ด้วย ESP32 และ SD Card เหมาะสำหรับติดตามตำแหน่งรถยนต์ จักรยาน หรือทรัพย์สินที่ต้องการเก็บข้อมูลการเดินทาง พร้อมโค้ดตัวอย่างและคำอธิบายภาษาไทย

📅 13 มีนาคม 2026⏱️ 15 นาที🎯 ระดับเริ่มต้น - กลาง

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

GPS Data Logger คือ ระบบที่ใช้บันทึกตำแหน่งพิกัด GPS ลงใน SD Card สำหรับนำกลับมาวิเคราะห์ภายหลัง โปรเจกต์นี้เหมาะสำหรับ:

  • ติดตามตำแหน่งรถยนต์ จักรยาน มอเตอร์ไซค์
  • บันทึกเส้นทางการเดินทาง/วิ่งจ็อกกิ้ง
  • ติดตามทรัพย์สินที่เคลื่อนย้ายได้
  • เก็บข้อมูลการใช้งานยานพาหนะ
  • Off-grid tracking ในพื้นที่ที่ไม่มีอินเทอร์เน็ต

✨ จุดเด่นของโปรเจกต์นี้

  • • ทำงานได้โดยไม่ต้องเชื่อมต่ออินเทอร์เน็ต
  • • ประหยัดพลังงานด้วย Deep Sleep Mode
  • • เก็บข้อมูลได้นานด้วย SD Card
  • • นำข้อมูลกลับมาวิเคราะห์ได้หลากหลายวิธี
  • • ต้นทุนต่ำ ง่ายต่อการประกอบ

หลักการทำงาน

  1. ESP32 อ่านข้อมูลพิกัดจาก GPS Module
  2. ตรวจสอบสัญญาณ GPS ว่าได้พิกัดครบถ้วน (Latitude, Longitude, Speed, Date, Time)
  3. บันทึกข้อมูลลง SD Card ในรูปแบบ CSV
  4. เข้าสู่ Deep Sleep Mode เพื่อประหยัดแบตเตอรี่
  5. ตื่นขึ้นมาเก็บข้อมูลใหม่ทุกๆ ช่วงเวลาที่กำหนด

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

Hardware Components

อุปกรณ์รุ่นที่แนะนำประมาณการณ์
MicrocontrollerESP32 DevKit / NodeMCU฿120-180
GPS ModuleNEO-6M / NEO-8M / AT6558฿80-150
SD Card ModuleMicro SD Card Module฿30-50
SD CardMicro SD 4GB-32GB (Class 10)฿80-200
External AntennaGPS Antenna (Active/Passive)฿50-100
Power SourceLi-ion Battery + TP4056฿50-100
Jumper WiresMale-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

  1. ดาวน์โหลด Arduino IDE จาก arduino.cc
  2. ติดตั้ง 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" → ติดตั้ง
  3. เลือก 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 = ดีมาก)

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

ขั้นตอนการทดสอบ

  1. อัปโหลดโค้ด:
    • เชื่อมต่อ ESP32 กับคอมพิวเตอร์ด้วย USB Cable
    • เลือก Board: ESP32 Dev Module
    • เลือก Port: COM port ที่เชื่อมต่อ
    • กด Upload ใน Arduino IDE
  2. เปิด Serial Monitor:
    • Tools → Serial Monitor หรือกด Ctrl+Shift+M
    • ตั้งค่า Baud rate เป็น 115200
    • ดูข้อความ "System ready! Waiting for GPS signal..."
  3. วาง GPS Module กลางแจ้ง:
    • วาง GPS Module ที่มองเห็นท้องฟ้า (ไม่มีหลังคาบด)
    • รอสัญญาณ GPS ประมาณ 1-5 นาที (ครั้งแรกนานกว่า)
    • LED จะกระพริบ 3 ครั้งเมื่อได้ GPS Fix
    • ข้อความ "GPS FIX acquired!" จะปรากฏ
  4. ตรวจสอบไฟล์บน 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

  1. เปิด Google Maps
  2. คลิกขวา → คลิก "ที่อยู่ของพิกัดนี้คืออะไร"
  3. ใส่ค่า Latitude และ Longitude จากไฟล์ CSV
  4. เช่น: 13.7563, 100.5018 (กรุงเทพฯ)

2. ใช้ Google Earth (แสดงเส้นทาง)

  1. แปลง CSV เป็น KML format ด้วย Python หรือ Online Tool
  2. ดาวน์โหลด Google Earth
  3. File → Open → เลือกไฟล์ KML
  4. จะเห็นเส้นทางการเดินทางแบบ 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 ตรวจจับการเคลื่อนไหว และบันทึกเมื่อมีการเคลื่อนที่

บทความที่เกี่ยวข้อง

ขอให้สนุกกับการสร้างโปรเจกต์ IoT! 🎉

CynoIoT

แพลตฟอร์ม IoT ที่ช่วยให้คุณสร้างและจัดการอุปกรณ์ IoT ได้ง่ายและมีประสิทธิภาพ

ติดต่อเรา

  • 📧 info@cynoiot.com
  • 🌐 www.cynoiot.com

© 2026 CynoIoT. All rights reserved.