Cara Memprogram GPS Neo GY-NEO6MV2 Pada ESP32

Cara Memprogram GPS Neo GY-NEO6MV2 Pada ESP32

GPS Neo GY-NEO6MV2 adalah modul penerima GPS (Global Positioning System) yang sangat populer dan banyak digunakan dalam proyek-proyek mikrokontroler seperti Arduino, Raspberry Pi, dan lain-lain.Berikut ini adalah code untuk memprogram nya :

#include <Arduino.h>

#include <SoftwareSerial.h>
#include <TinyGPS++.h>
#include <TaskScheduler.h>

SoftwareSerial gps_Serial(D2, D3); // RX, TX (ESP) | TX, RX (GPS)
TinyGPSPlus gps;
unsigned long previousMillis_gps = 0;
const long interval_gps = 5000;
Scheduler gps_runner;
void debug_gps(String text);
void koneksi_gps();
void gpsTaskCallback();
Task gpsTask(500, TASK_FOREVER, &gpsTaskCallback);


void debug_gps(String text) {
  Serial.println(text);
}
void koneksi_gps() {
  debug_gps("gps Mencari Sinyal...");
  unsigned long currentMillis_gps = millis();
  while (gps_Serial.available() > 0) {
    if (gps.encode(gps_Serial.read())) {
      float latitude_gps = gps.location.lat();
      float longitude_gps = gps.location.lng();
      if (gps.location.isUpdated()) {
        debug_gps("Read, NEW location : " + String(latitude_gps, 6) + "," + String(longitude_gps, 6)); 
      
      } else {
        debug_gps("Read, OLD location : " + String(latitude_gps, 6) + "," + String(longitude_gps, 6)); 
      }
      if (currentMillis_gps - previousMillis_gps >= interval_gps) {
        String link_gps;
        if (String(latitude_gps, 6)=="0.000000" || String(longitude_gps, 6)=="0.000000")
        {
            debug_gps("gps : 0");
        }
        else
        {
            link_gps += "&latitude=" + String(latitude_gps, 6);
            link_gps += "&longitude=" + String(longitude_gps, 6);
            link_gps += "&gps=" + String(latitude_gps, 6) + "," + String(longitude_gps, 6);
            debug_gps(link_gps);
            //proses_iot(link_gps);
            previousMillis_gps = currentMillis_gps;
        }
      }
     
    }
  }
}
void gpsTaskCallback() {
  koneksi_gps();
}


void setup()
{
Serial.begin(9600);
  Serial.begin(115200);
  gps_Serial.begin(9600);
  gps_runner.addTask(gpsTask);
  gpsTask.enable();

}
void loop(){
gps_runner.execute();
delay(1000);


}


Berikut ini adalah penjelasan dari kode di atas :

1. Inklusi Library dan Deklarasi Variabel/Objek Global

C++

#<strong>include</strong> <Arduino.h>

#<strong>include</strong> <SoftwareSerial.h>
#<strong>include</strong> <TinyGPS++.h>
#<strong>include</strong> <TaskScheduler.h>

SoftwareSerial gps_Serial(D2, D3); // RX, TX (ESP) | TX, RX (GPS)
TinyGPSPlus gps;
unsigned long previousMillis_gps = 0;
const long interval_gps = 5000;
Scheduler gps_runner;
void debug_gps(String text);
void koneksi_gps();
void gpsTaskCallback();
Task gpsTask(500, TASK_FOREVER, &gpsTaskCallback);
  • #include <Arduino.h>: Library dasar untuk fungsionalitas Arduino.
  • #include <SoftwareSerial.h>: Memungkinkan penggunaan pin digital sebagai port serial tambahan untuk berkomunikasi dengan modul GPS. Ini penting karena pin serial hardware (0 dan 1) sering digunakan oleh Serial Monitor.
  • #include <TinyGPS++.h>: Library yang sangat efisien untuk mengurai (parse) data NMEA dari modul GPS. Ia membuat proses membaca lintang, bujur, ketinggian, kecepatan, dll., menjadi sangat mudah.
  • #include <TaskScheduler.h>: Library untuk mengelola tugas-tugas secara non-blocking. Ini memungkinkan Anda untuk menjalankan beberapa fungsi pada interval yang berbeda tanpa menggunakan delay() yang memblokir.
  • SoftwareSerial gps_Serial(D2, D3); // RX, TX (ESP) | TX, RX (GPS): Membuat objek SoftwareSerial bernama gps_Serial.
    • D2: Ini adalah pin RX (Receive) pada mikrokontroler (kemungkinan ESP8266 atau ESP32, karena penamaan D2, D3 umum pada board ini). Pin ini akan dihubungkan ke pin TX (Transmit) dari modul GPS.
    • D3: Ini adalah pin TX (Transmit) pada mikrokontroler. Pin ini akan dihubungkan ke pin RX (Receive) dari modul GPS.
    • Komentar // RX, TX (ESP) | TX, RX (GPS) mengingatkan pada skema koneksi silang serial.
  • TinyGPSPlus gps;: Membuat objek dari kelas TinyGPSPlus bernama gps. Objek ini akan digunakan untuk mengurai data GPS yang diterima.
  • unsigned long previousMillis_gps = 0;: Variabel untuk menyimpan waktu terakhir kali data GPS dikirim/diproses, digunakan untuk logika non-blocking (millis()).
  • const long interval_gps = 5000;: Mendefinisikan interval waktu (dalam milidetik) untuk mengirim/memproses data GPS tertentu, yaitu 5000 ms atau 5 detik.
  • Scheduler gps_runner;: Membuat objek dari kelas Scheduler. Ini adalah “mesin” yang akan menjalankan tugas-tugas terjadwal.
  • void debug_gps(String text);, void koneksi_gps();, void gpsTaskCallback();: Deklarasi fungsi-fungsi yang akan digunakan dalam kode.
  • Task gpsTask(500, TASK_FOREVER, &gpsTaskCallback);: Membuat sebuah objek Task bernama gpsTask.
    • 500: Interval tugas (500 ms). Ini berarti gpsTaskCallback akan dipanggil setiap 500 milidetik.
    • TASK_FOREVER: Tugas akan berjalan terus-menerus tanpa batas.
    • &gpsTaskCallback: Pointer ke fungsi yang akan dijalankan oleh tugas ini.

2. Fungsi debug_gps()

C++

void debug_gps(String text) {
  Serial.println(text);
}
  • Fungsi sederhana untuk mencetak pesan debug ke Serial Monitor. Ini membantu dalam melacak apa yang terjadi di program.

3. Fungsi koneksi_gps()

C++

void koneksi_gps() {
  debug_gps("gps Mencari Sinyal...");
  unsigned long currentMillis_gps = millis();
  while (gps_Serial.available() > 0) {
    if (gps.encode(gps_Serial.read())) {
      float latitude_gps = gps.location.lat();
      float longitude_gps = gps.location.lng();
      if (gps.location.isUpdated()) {
        debug_gps("Read, NEW location : " + String(latitude_gps, 6) + "," + String(longitude_gps, 6));
      } else {
        debug_gps("Read, OLD location : " + String(latitude_gps, 6) + "," + String(longitude_gps, 6));
      }
      if (currentMillis_gps - previousMillis_gps >= interval_gps) {
        String link_gps;
        if (String(latitude_gps, 6)=="0.000000" || String(longitude_gps, 6)=="0.000000")
        {
          debug_gps("gps : 0");
        }
        else
        {
          link_gps += "&latitude=" + String(latitude_gps, 6);
          link_gps += "&longitude=" + String(longitude_gps, 6);
          link_gps += "&gps=" + String(latitude_gps, 6) + "," + String(longitude_gps, 6);
          debug_gps(link_gps);
          //proses_iot(link_gps); // Fungsi ini dikomentari, berarti tidak dieksekusi
          previousMillis_gps = currentMillis_gps;
        }
      }
    }
  }
}

Fungsi ini bertanggung jawab untuk membaca data dari modul GPS dan memprosesnya.

  • debug_gps("gps Mencari Sinyal...");: Mencetak pesan awal bahwa GPS sedang mencari sinyal.
  • unsigned long currentMillis_gps = millis();: Menyimpan waktu saat ini untuk digunakan dalam logika non-blocking.
  • while (gps_Serial.available() > 0): Loop ini berjalan selama ada byte data yang tersedia di buffer serial dari modul GPS.
  • if (gps.encode(gps_Serial.read())): Ini adalah bagian inti dari TinyGPS++.
    • gps_Serial.read(): Membaca satu byte data dari port serial gps_Serial.
    • gps.encode(): Mengumpankan byte yang dibaca ke library TinyGPS++. Library ini akan secara internal memproses byte-byte tersebut untuk mengurai kalimat NMEA dan mengekstrak informasi GPS. Fungsi ini akan mengembalikan true jika sebuah kalimat NMEA lengkap telah diuraikan dan data GPS diperbarui.
  • float latitude_gps = gps.location.lat();, float longitude_gps = gps.location.lng();: Mendapatkan nilai lintang dan bujur dari objek gps.
  • if (gps.location.isUpdated()) { ... } else { ... }: Memeriksa apakah lokasi GPS telah diperbarui dengan data baru. Ini membantu membedakan antara pembacaan yang sama dan pembacaan yang benar-benar baru. Pesan Read, NEW location atau Read, OLD location akan dicetak ke Serial Monitor.
  • if (currentMillis_gps - previousMillis_gps >= interval_gps): Ini adalah implementasi non-blocking delay untuk mencetak data atau memicu proses IoT setiap 5 detik.
    • if (String(latitude_gps, 6)=="0.000000" || String(longitude_gps, 6)=="0.000000"): Memeriksa apakah nilai lintang atau bujur adalah “0.000000”. Ini sering terjadi jika modul GPS belum mendapatkan fix (kunci) satelit yang valid. Jika ya, akan mencetak “gps : 0”.
    • else: Jika koordinat bukan 0.000000, berarti ada fix yang valid.
      • link_gps += ...: Membangun sebuah string link_gps yang berisi parameter lintang, bujur, dan koordinat gabungan. String ini tampaknya dirancang untuk dikirim ke suatu platform IoT (misalnya melalui HTTP GET request).
      • debug_gps(link_gps);: Mencetak string link_gps ke Serial Monitor.
      • //proses_iot(link_gps);: Ada pemanggilan fungsi proses_iot() yang dikomentari. Ini menunjukkan bahwa di sini seharusnya ada logika untuk mengirim data GPS ke server atau layanan IoT, tetapi saat ini dinonaktifkan.
      • previousMillis_gps = currentMillis_gps;: Memperbarui previousMillis_gps untuk memulai perhitungan interval 5 detik lagi.

4. Fungsi gpsTaskCallback()

C++

void gpsTaskCallback() {
  koneksi_gps();
}
  • Ini adalah fungsi callback untuk gpsTask. Ketika gpsTask dieksekusi oleh gps_runner (setiap 500 ms), fungsi koneksi_gps() akan dipanggil.

5. Fungsi setup()

C++

void setup()
{
  Serial.begin(9600);
  Serial.begin(115200); // INI KEMUNGKINAN KESALAHAN, HANYA SATU Serial.begin() YANG EFEKTIF
  gps_Serial.begin(9600);
  gps_runner.addTask(gpsTask);
  gpsTask.enable();
}
  • Serial.begin(9600);: Menginisialisasi komunikasi Serial Monitor pada baud rate 9600.
  • Serial.begin(115200);: Perhatian! Anda memiliki dua kali pemanggilan Serial.begin() untuk objek Serial yang sama (Serial adalah port serial hardware bawaan). Hanya pemanggilan terakhir yang akan berlaku. Jadi, Serial Monitor Anda akan berkomunikasi pada baud rate 115200. Anda mungkin ingin menghapus baris Serial.begin(9600); yang pertama.
  • gps_Serial.begin(9600);: Menginisialisasi port SoftwareSerial untuk komunikasi dengan modul GPS pada baud rate 9600 (ini adalah baud rate umum untuk modul GPS NEO-6M).
  • gps_runner.addTask(gpsTask);: Menambahkan gpsTask ke penjadwal (gps_runner).
  • gpsTask.enable();: Mengaktifkan gpsTask agar mulai dieksekusi oleh penjadwal.

6. Fungsi loop()

C++

void loop(){
  gps_runner.execute();
  delay(1000);
}
  • gps_runner.execute();: Ini adalah baris terpenting saat menggunakan TaskScheduler. Fungsi ini harus dipanggil sesering mungkin di loop() tanpa pemblokiran. Ia akan memeriksa tugas-tugas yang telah dijadwalkan dan mengeksekusinya jika sudah waktunya.
  • delay(1000);: Perhatian! Penambahan delay(1000); di dalam loop() saat menggunakan TaskSchedulermengalahkan tujuan utama dari TaskScheduler itu sendiri, yaitu non-blocking multitasking. delay() ini akan memblokir eksekusi semua tugas lain dan fungsi loop() selama 1 detik penuh.
    • Karena gpsTask diatur untuk berjalan setiap 500 ms, tetapi loop() diblokir 1000 ms, gpsTaskCallback akan dipanggil setiap 1 detik, bukan 0.5 detik.
    • Jika Anda memiliki tugas lain yang lebih sensitif terhadap waktu, delay() ini akan merusaknya.
    • Solusi: Hapus delay(1000); dari loop(). Biarkan loop() sesederhana gps_runner.execute();. Jika Anda ingin menunggu sesuatu, gunakan logika millis() atau fitur TaskScheduler lainnya.

Cara Kerja Keseluruhan

Kode ini bertujuan untuk:

  1. Membaca Data GPS: Secara terus-menerus membaca byte data dari modul GPS melalui SoftwareSerial dan mengumpankannya ke library TinyGPS++.
  2. Mengurai Data NMEA: TinyGPS++ secara cerdas mengurai kalimat-kalimat NMEA yang datang dan memperbarui properti seperti lokasi (lintang, bujur).
  3. Mendeteksi Update: Memeriksa apakah lokasi GPS baru telah diterima.
  4. Mencetak Data Terjadwal: Menggunakan TaskScheduler untuk menjalankan fungsi koneksi_gps() setiap 500 milidetik (meskipun delay(1000) di loop() akan membuatnya menjadi setiap 1000 ms).
  5. Memfilter Lokasi 0.0: Menghindari pencetakan atau pengiriman data lokasi jika GPS belum mendapatkan fix (ditunjukkan oleh lintang/bujur 0.000000).
  6. Membangun String untuk IoT (Opsional): Membuat string parameter yang siap untuk dikirim ke layanan IoT, meskipun fungsi pengirimannya saat ini dikomentari.

Saran Perbaikan:

  • Perbaiki Serial.begin(): Hapus salah satu Serial.begin() di setup(). Pertahankan yang 115200 jika itu yang Anda inginkan untuk Serial Monitor.
  • Hapus delay() di loop(): Ini adalah kunci untuk memanfaatkan TaskScheduler secara efektif. loop() seharusnya berjalan secepat mungkin.
  • Perhatikan Pin D2/D3: Pastikan ini adalah pin yang valid dan tersedia untuk SoftwareSerial pada mikrokontroler Anda (khususnya untuk ESP family). Untuk ESP8266, pin D2 dan D3 adalah GPIO4 dan GPIO0.
  • Koneksi GPS: Pastikan TX GPS terhubung ke RX Arduino (D2) dan RX GPS terhubung ke TX Arduino (D3). Ingat untuk menghubungkan GND.

untuk diskusi bisa kontak dibawah ini :

Sosial media :

Apa itu ESP32?