/*
* GPS Tracker ด้วย Raspberry Pi Pico
* โค้ด Arduino สำหรับติดตามตำแหน่งแบบเรียลไทม์
*
* ฟีเจอร์:
* - รับข้อมูล GPS จากโมดูล Neo-6M
* - ส่งข้อมูลผ่าน GSM (SIM800L)
* - แสดงสถานะผ่าน LED
* - จัดการข้อผิดพลาดอัตโนมัติ
*/
#include <SoftwareSerial.h>
#include <TinyGPS++.h>
// กำหนดขา Pin สำหรับการเชื่อมต่อ
#define GPS_RX_PIN 1 // รับข้อมูลจาก GPS
#define GPS_TX_PIN 0 // ส่งข้อมูลไป GPS
#define GSM_RX_PIN 5 // รับข้อมูลจาก GSM
#define GSM_TX_PIN 4 // ส่งข้อมูลไป GSM
#define LED_GPS 14 // LED แสดงสถานะ GPS (เหลือง)
#define LED_GSM 13 // LED แสดงสถานะ GSM (เขียว)
#define LED_ERROR 15 // LED แสดงข้อผิดพลาด (แดง)
// สร้าง Object สำหรับการสื่อสาร
SoftwareSerial gpsSerial(GPS_RX_PIN, GPS_TX_PIN);
SoftwareSerial gsmSerial(GSM_RX_PIN, GSM_TX_PIN);
TinyGPSPlus gps;
// *** การตั้งค่า - แก้ไขตรงนี้ ***
const char* apn = "airtelgprs.com"; // APN ของผู้ให้บริการ (เปลี่ยนตามเครือข่าย)
const char* apiEndpoint = "your-geolinker-endpoint.com"; // URL เซิร์ฟเวอร์
const char* apiKey = "YOUR_API_KEY_HERE"; // API Key จาก GeoLinker
const char* deviceId = "YOUR_DEVICE_ID_HERE"; // Device ID ของคุณ
// ตัวแปรสำหรับเก็บสถานะ
bool gpsFixed = false; // สถานะการรับสัญญาณ GPS
bool gsmConnected = false; // สถานะการเชื่อมต่อ GSM
float latitude, longitude; // ตำแหน่งปัจจุบัน
unsigned long lastSend = 0; // เวลาส่งข้อมูลครั้งล่าสุด
const unsigned long sendInterval = 30000; // ส่งข้อมูลทุก 30 วินาที
void setup() {
// เริ่มต้นการสื่อสาร Serial
Serial.begin(115200);
gpsSerial.begin(9600);
gsmSerial.begin(9600);
// ตั้งค่า LED เป็น Output
pinMode(LED_GPS, OUTPUT);
pinMode(LED_GSM, OUTPUT);
pinMode(LED_ERROR, OUTPUT);
// กระพริบ LED เมื่อเริ่มต้น
flashLEDs();
Serial.println("=== GPS Tracker เริ่มทำงาน ===");
Serial.println("กำลังเริ่มต้นระบบ...");
// เริ่มต้น GSM Module
initializeGSM();
}
void loop() {
// อ่านข้อมูลจาก GPS
while (gpsSerial.available() > 0) {
if (gps.encode(gpsSerial.read())) {
// ตรวจสอบว่าได้ตำแหน่งที่ถูกต้องหรือไม่
if (gps.location.isValid()) {
latitude = gps.location.lat();
longitude = gps.location.lng();
// อัปเดตสถานะ GPS
if (!gpsFixed) {
gpsFixed = true;
digitalWrite(LED_GPS, HIGH);
Serial.println("✅ รับสัญญาณ GPS สำเร็จ!");
}
// แสดงตำแหน่งปัจจุบัน
Serial.print("📍 ตำแหน่ง: ");
Serial.print(latitude, 6);
Serial.print(", ");
Serial.print(longitude, 6);
Serial.print(" | ดาวเทียม: ");
Serial.println(gps.satellites.value());
// ส่งข้อมูลตำแหน่งตามช่วงเวลาที่กำหนด
if (millis() - lastSend > sendInterval) {
sendLocationData();
lastSend = millis();
}
}
}
}
// ตรวจสอบสถานะ GPS
if (millis() > 10000 && gps.charsProcessed() < 10) {
Serial.println("❌ ไม่พบสัญญาณ GPS");
digitalWrite(LED_ERROR, HIGH);
gpsFixed = false;
digitalWrite(LED_GPS, LOW);
}
// กระพริบ LED แสดงข้อผิดพลาดหากไม่มี GPS นาน
if (millis() > 300000 && !gpsFixed) {
digitalWrite(LED_ERROR, !digitalRead(LED_ERROR));
}
delay(1000);
}
// ฟังก์ชันเริ่มต้น GSM Module
void initializeGSM() {
Serial.println("🔧 กำลังเริ่มต้น GSM Module...");
// ส่งคำสั่ง AT พื้นฐาน
if (!sendATCommand("AT", 2000)) {
Serial.println("❌ GSM Module ไม่ตอบสนong");
digitalWrite(LED_ERROR, HIGH);
return;
}
// ตรวจสอบ SIM Card และเครือข่าย
sendATCommand("AT+CPIN?", 2000); // สถานะ SIM Card
sendATCommand("AT+CREG?", 2000); // การลงทะเบียนเครือข่าย
sendATCommand("AT+CGATT=1", 2000); // เปิดใช้ GPRS
sendATCommand("AT+CIPSHUT", 2000); // ปิดการเชื่อมต่อเก่า
sendATCommand("AT+CIPSTATUS", 2000); // ตรวจสอบสถานะ
sendATCommand("AT+CIPMUX=0", 2000); // โหมดการเชื่อมต่อเดี่ยว
// ตั้งค่า APN
String apnCmd = "AT+CSTT=\"" + String(apn) + "\"";
sendATCommand(apnCmd, 2000);
// เชื่อมต่อ GPRS
sendATCommand("AT+CIICR", 5000);
// รับ IP Address
if (sendATCommand("AT+CIFSR", 2000)) {
gsmConnected = true;
digitalWrite(LED_GSM, HIGH);
Serial.println("✅ GSM เชื่อมต่อสำเร็จ!");
} else {
Serial.println("❌ การเชื่อมต่อ GSM ล้มเหลว");
digitalWrite(LED_ERROR, HIGH);
}
}
// ฟังก์ชันส่งข้อมูลตำแหน่ง
void sendLocationData() {
if (!gpsFixed || !gsmConnected) {
Serial.println("⚠️ ไม่สามารถส่งข้อมูลได้ - GPS หรือ GSM ไม่พร้อม");
return;
}
Serial.println("📤 กำลังส่งข้อมูลตำแหน่ง...");
// เตรียมข้อมูล JSON
String jsonData = "{";
jsonData += "\"device_id\":\"" + String(deviceId) + "\",";
jsonData += "\"latitude\":" + String(latitude, 6) + ",";
jsonData += "\"longitude\":" + String(longitude, 6) + ",";
jsonData += "\"timestamp\":" + String(millis()) + ",";
jsonData += "\"satellites\":" + String(gps.satellites.value()) + ",";
jsonData += "\"api_key\":\"" + String(apiKey) + "\"";
jsonData += "}";
// เชื่อมต่อ TCP
String httpCmd = "AT+CIPSTART=\"TCP\",\"" + String(apiEndpoint) + "\",80";
if (sendATCommand(httpCmd, 5000)) {
// สร้าง HTTP Request
String httpRequest = "POST /api/location HTTP/1.1\r\n";
httpRequest += "Host: " + String(apiEndpoint) + "\r\n";
httpRequest += "Content-Type: application/json\r\n";
httpRequest += "Content-Length: " + String(jsonData.length()) + "\r\n\r\n";
httpRequest += jsonData;
// ส่งข้อมูล
String sendCmd = "AT+CIPSEND=" + String(httpRequest.length());
if (sendATCommand(sendCmd, 3000)) {
gsmSerial.print(httpRequest);
delay(3000);
Serial.println("✅ ส่งข้อมูลตำแหน่งสำเร็จ!");
} else {
Serial.println("❌ ส่งข้อมูล HTTP ล้มเหลว");
}
// ปิดการเชื่อมต่อ
sendATCommand("AT+CIPCLOSE", 2000);
} else {
Serial.println("❌ เชื่อมต่อ TCP ล้มเหลว");
}
}
// ฟังก์ชันส่งคำสั่ง AT
bool sendATCommand(String command, int timeout) {
gsmSerial.println(command);
long int time = millis();
String response = "";
// รอรับ Response
while ((time + timeout) > millis()) {
while (gsmSerial.available()) {
char c = gsmSerial.read();
response += c;
}
}
// แสดงผลลัพธ์
Serial.println("CMD: " + command + " | RSP: " + response.substring(0, 50));
// ตรวจสอบความสำเร็จ
return (response.indexOf("OK") != -1) || (response.indexOf("CONNECT") != -1);
}
// ฟังก์ชันกระพริบ LED เมื่อเริ่มต้น
void flashLEDs() {
for (int i = 0; i < 3; i++) {
digitalWrite(LED_GPS, HIGH);
digitalWrite(LED_GSM, HIGH);
digitalWrite(LED_ERROR, HIGH);
delay(200);
digitalWrite(LED_GPS, LOW);
digitalWrite(LED_GSM, LOW);
digitalWrite(LED_ERROR, LOW);
delay(200);
}
}
/*
* 📝 หมายเหตุการตั้งค่า:
*
* 1. แก้ไข YOUR_API_KEY_HERE ด้วย API Key จาก GeoLinker
* 2. แก้ไข YOUR_DEVICE_ID_HERE ด้วย Device ID ของคุณ
* 3. เปลี่ยน APN ให้ตรงกับผู้ให้บริการของคุณ:
* - AIS: "internet"
* - DTAC: "www.dtac.co.th"
* - True: "internet"
* - Airtel: "airtelgprs.com"
* 4. แก้ไข apiEndpoint ด้วย URL เซิร์ฟเวอร์จริง
*
* 🔍 การแก้ไขปัญหา:
* - LED แดง: มีข้อผิดพลาด
* - LED เหลือง: สถานะ GPS
* - LED เขียว: สถานะ GSM
* - ดู Serial Monitor สำหรับข้อมูลโดยละเอียด
*/