Breadboard held outdoors with ESP32-C3 SuperMini, NEO-6M GPS module, and OLED display showing GPS coordinates

ผู้เริ่มต้น

สร้างเครื่องแสดงตำแหน่ง GPS

เซ็นเซอร์จอแสดงผลIoT

รู้ตำแหน่งของคุณอย่างแม่นยำภายในไม่กี่เมตร จากสัญญาณดาวเทียมจริง ไม่ต้องใช้โทรศัพท์ ไม่ต้องเชื่อมต่ออินเทอร์เน็ต

รวมชิ้นส่วนจริง 6 รายการ

ราคารวมชุดนี้: 1,685.00 ฿

ยังไม่รวมส่วนลดคำสั่งซื้อที่คุณอาจได้รับตอนชำระเงิน

สิ่งที่คุณต้องใช้

เป้าหมายของโครงการ

โครงการนี้สร้างอุปกรณ์แสดงตำแหน่งแบบสแตนด์อะโลน: ตัวควบคุมจะอ่านค่าตำแหน่งดาวเทียมจริงจากโมดูล GPS โดยเฉพาะ และแสดงละติจูดและลองจิจูดปัจจุบันของคุณบนหน้าจอขนาดเล็ก โดยทำงานแบบออฟไลน์ทั้งหมด ไม่มีการใช้โทรศัพท์ สัญญาณโทรศัพท์มือถือ หรือการเชื่อมต่ออินเทอร์เน็ตเมื่อโค้ดทำงานแล้ว – ตำแหน่งจะมาจากดาวเทียม GPS โดยตรง

สิ่งที่ตัวควบคุมทำ

ESP32-C3 SuperMini จะอ่านกระแสข้อมูลต่อเนื่องจากโมดูล GPS ผ่านการเชื่อมต่อแบบอนุกรม (UART) แยกข้อมูลที่สำคัญ เช่น ละติจูด ลองจิจูด และระดับความสูง และวาดจอแสดงผล OLED ใหม่ด้วยตำแหน่งปัจจุบันในช่วงเวลาปกติ

สิ่งที่โมดูล GPS ทำ

โมดูล GPS NEO-6M ทำงานเกี่ยวกับดาวเทียมจริง: มันติดตามดาวเทียม GPS คำนวณค่าตำแหน่ง และส่งผลลัพธ์ออกมาอย่างต่อเนื่องในรูปแบบประโยค NMEA มาตรฐานผ่าน UART NMEA เป็นรูปแบบข้อความที่ได้รับการยอมรับและรองรับอย่างกว้างขวาง ซึ่งเป็นเหตุผลที่มีไลบรารีการแยกวิเคราะห์ที่มีประสิทธิภาพสำหรับแพลตฟอร์มไมโครคอนโทรลเลอร์เกือบทุกชนิด – คุณไม่จำเป็นต้องแยกวิเคราะห์ประโยคดิบด้วยตนเอง

สิ่งที่จอแสดงผล OLED ทำ

OLED ขนาด 0.96 นิ้วเพียงแค่แสดงผลสิ่งที่ตัวควบคุมแยกวิเคราะห์ล่าสุดจาก GPS – ละติจูด ลองจิจูด และอาจเป็นระดับความสูงหรือสถานะการแก้ไข – ซึ่งจะรีเฟรชทุกรอบเพื่อให้หน้าจอแสดงข้อมูลล่าสุดที่โมดูลรายงานเสมอ

พื้นฐานการเดินสาย UART

โมดูล GPS สื่อสารผ่าน UART ซึ่งเป็นการเชื่อมต่อแบบอนุกรมสองสายง่ายๆ: พิน TX (ส่ง) ของโมดูลเชื่อมต่อกับพิน RX (รับ) ของตัวควบคุม และในทางกลับกัน การเชื่อมต่อ TX และ RX ผิดพลาด – การเชื่อมต่อ TX กับ TX – เป็นข้อผิดพลาดที่พบได้บ่อยมากสำหรับผู้เริ่มต้น และเป็นสิ่งแรกที่ต้องตรวจสอบหากไม่มีข้อมูลเข้ามา

แนวคิดซอฟต์แวร์และไลบรารี

เริ่มต้นจากไลบรารีการแยกวิเคราะห์ NMEA ที่ได้รับการทดสอบอย่างดีสำหรับแพลตฟอร์มตัวควบคุมของคุณ แทนที่จะเขียนการแยกวิเคราะห์ประโยคตั้งแต่เริ่มต้น – NMEA มีโครงสร้างตรวจสอบและโครงสร้างฟิลด์ที่กำหนดไว้ ซึ่งง่ายต่อการทำผิดพลาดเล็กน้อยด้วยมือ เมื่อไลบรารีรายงานว่าได้รับประโยคที่ถูกต้องแล้ว การดึงละติจูดและลองจิจูดมักจะเป็นการเรียกใช้ฟังก์ชันเพียงไม่กี่ครั้ง

การทดสอบและการแก้ไขปัญหา

  • ไม่พบตำแหน่งเลย แม้จะรอไปแล้ว – ให้ย้ายไปยังตำแหน่งที่มีมุมมองท้องฟ้าที่ชัดเจนและไม่มีสิ่งกีดขวาง การรับสัญญาณ GPS จะไม่ทำงานในอาคารหรือภายใต้การปกคลุมหนาแน่น และนี่คือสาเหตุที่พบบ่อยที่สุดที่ทำให้โมดูล GPS 'ไม่ทำงาน'
  • การเริ่มต้นแบบเย็นใช้เวลานานในการรับตำแหน่งแรก – นี่เป็นพฤติกรรม GPS ปกติ ไม่ใช่ข้อบกพร่อง เวลาในการรับตำแหน่งแรกอาจใช้เวลาประมาณ 30 วินาทีถึงหลายนาทีในการเริ่มต้นแบบเย็น ขึ้นอยู่กับการมองเห็นดาวเทียม
  • ข้อมูลอนุกรมดูสับสนหรือไม่ปรากฏเลยในการเชื่อมต่อ UART – ตรวจสอบอีกครั้งว่า TX และ RX ไม่ได้สลับกันระหว่างโมดูลและตัวควบคุม นี่เป็นข้อผิดพลาดในการเดินสายที่พบบ่อยที่สุดกับอุปกรณ์เสริม UART ใดๆ
  • หน้าจอแสดง 0,0 เป็นพิกัด – นี่หมายความว่ายังไม่ได้รับตำแหน่งที่ถูกต้อง ไม่ใช่ข้อบกพร่องในโค้ดของคุณ รอนานขึ้นและ/หรือย้ายไปยังที่ที่มีมุมมองท้องฟ้าที่ชัดเจนกว่าก่อนที่จะสรุปว่ามีบางอย่างเสีย

การอัปเกรดเสริมในอนาคต: การบันทึกเส้นทางเมื่อเวลาผ่านไป

เมื่อตำแหน่งปัจจุบันแสดงผลได้อย่างน่าเชื่อถือ ขั้นตอนต่อไปคือการบันทึกชุดของตำแหน่งเมื่อเวลาผ่านไป – ไม่ว่าจะบันทึกลงในหน่วยเก็บข้อมูลภายใน หรือรวมกับแนวคิดจากโครงการบันทึกข้อมูลไร้สาย ส่งออกผ่านเครือข่าย – เพื่อสร้างเส้นทางการเคลื่อนที่ที่เรียบง่ายแทนที่จะแสดงเพียงตำแหน่งปัจจุบัน

การเดินสาย

  • NEO-6M VCC → ESP32-C3 SuperMini 5V (โมดูลมีตัวควบคุมในตัว, ทนต่อ 5V)
  • NEO-6M GND → GND
  • NEO-6M TX → GPIO20 (`GPS_RX_PIN`) — TX ของโมดูลเข้าสู่ RX ของตัวควบคุม
  • NEO-6M RX → GPIO21 (`GPS_TX_PIN`) — RX ของโมดูลจาก TX ของตัวควบคุม (การไขว้ UART มาตรฐาน)
  • OLED VCC → 3.3V
  • OLED GND → GND
  • OLED SDA → GPIO8 (`SDA_PIN`)
  • OLED SCL → GPIO9 (`SCL_PIN`)

GPS ต้องการมุมมองท้องฟ้าที่ชัดเจน – ในอาคาร คาดว่า 'ไม่มีการแก้ไข' และจำนวนดาวเทียมเป็น 0 เป็นเวลานาน หรือตลอดไป; นั่นเป็นเรื่องปกติ ไม่ใช่ข้อบกพร่องในการเดินสาย การแก้ไขครั้งแรก ('cold start') มักใช้เวลา 30 วินาทีถึงสองสามนาที; การแก้ไขครั้งต่อๆ ไปหลังจากการสูญเสียพลังงานชั่วคราวมักจะเร็วกว่ามาก เมทริกซ์พินของ ESP32-C3 ช่วยให้สามารถแมป `HardwareSerial` ไปยัง GPIO แทบทุกพินได้ ดังนั้น GPS_RX_PIN/GPS_TX_PIN จึงไม่ใช่พิน UART ฮาร์ดแวร์ที่ตายตัว – ปรับ `#define`s หากคุณเดินสายไปยัง GPIO อื่นๆ

แผนภาพการต่อสาย

VCC → 5V GND TX → GPIO20 RX → GPIO21 VCC GND SDA → GPIO8 SCL → GPIO9 ESP32-C3 SuperMini NEO-6M OLED GND 3.3V

โค้ดเริ่มต้น

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <TinyGPSPlus.h>

#define SDA_PIN 8       // ESP32-C3 default I2C SDA - adjust if your board differs
#define SCL_PIN 9       // ESP32-C3 default I2C SCL - adjust if your board differs

#define GPS_RX_PIN 20   // to GPS module TX - any free GPIO (remapped via pin matrix)
#define GPS_TX_PIN 21   // to GPS module RX - adjust to match your wiring if different
#define GPS_BAUD 9600   // NEO-6M default NMEA output baud rate

#define OLED_ADDRESS 0x3C

Adafruit_SSD1306 display(128, 64, &Wire, -1);
TinyGPSPlus gps;
HardwareSerial gpsSerial(1); // use UART1

unsigned long lastFixTime = 0;

void setup() {
  Serial.begin(115200);
  gpsSerial.begin(GPS_BAUD, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN);

  Wire.begin(SDA_PIN, SCL_PIN);
  if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDRESS)) {
    Serial.println("SSD1306 init failed");
    while (true) delay(1000);
  }

  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);
  display.setTextSize(1);
  display.setCursor(0, 0);
  display.println("Waiting for GPS fix...");
  display.println("(needs clear sky view,");
  display.println("can take a few minutes)");
  display.display();
}

void loop() {
  while (gpsSerial.available() > 0) {
    gps.encode(gpsSerial.read());
  }

  if (gps.location.isUpdated() && gps.location.isValid()) {
    lastFixTime = millis();

    display.clearDisplay();
    display.setTextSize(1);
    display.setCursor(0, 0);
    display.println("GPS Fix");
    display.setCursor(0, 14);
    display.printf("Lat: %.6f\n", gps.location.lat());
    display.printf("Lon: %.6f\n", gps.location.lng());

    if (gps.altitude.isValid()) {
      display.printf("Alt: %.1f m\n", gps.altitude.meters());
    }
    if (gps.satellites.isValid()) {
      display.printf("Sats: %d\n", gps.satellites.value());
    }
    display.display();

    Serial.printf("Lat: %.6f  Lon: %.6f  Sats: %d\n",
                  gps.location.lat(), gps.location.lng(), gps.satellites.value());
  } else if (lastFixTime == 0 && millis() % 2000 < 20) {
    // still searching for first fix - a normal wait indoors or under poor sky view
    Serial.println("Searching for GPS fix...");
  }
}

ไม่แน่ใจขั้นตอนไหน? ถามเรา