Ở bài viết này mình sẽ hướng dẫn các bạn lấy dữ liệu từ một modul GPS sử dụng TIVA C

Chuẩn bị

Phần cứng

  • TIVA C Launchpad
  • Modul GPS ( Ở đây mình sử dụng modul Neo 6M)
  • Modul USB2UART PL2303 (hoặc tương tự)

Phần mềm

  • Energia IDE
  • Terminal để hiển thị thông tin (mình dùng Teraterm)
  • Thư viện TinyGPS hoặc tải tại đây

Kiểm tra modul GPS

Trước tiên chúng ta cần kiểm tra hoạt động của GPS như thế nào, kết nối PL2303 và GPS theo sơ đồ chân như sau

PL2303 GPS
3v3 VCC
TX RX
RX TX
GND GND

Khi đã kết nối dây và cắm vào cổng USB máy tính ta sẽ thấy đèn LED của PL2303 chớp, quan sát qua terminal với baud 9600 sẽ có dữ liệu

Ta thấy có dữ liệu tức là đã giao tiếp được thành công, tuy nhiên giá trị toàn là 99.99 có nghĩa là GPS chưa lấy được tọa độ chính xác. Chúng ta phải chờ một lúc mới có tín hiệu

Khi có được kết quả như trên nghĩa là đã giao tiếp thành công và lấy được dữ liệu về vị trí tọa độ, thời gian,… Coi như yên tâm có thể lấy modul GPS này để giao tiếp với anh TIVA C mà không phải lo lắng nhiều rồi.

Lưu ý:
Một số lưu ý quan trọng khi test modul GPS mà các bạn cần lưu ý
Nguồn cấp: GPS Neo 6M hoạt động với nguồn từ 3.3V – 5V
Kết nối dây đúng: khi nào ra được tọa độ 99.99 là giao tiếp thành công
Đèn báo hiệu: khi LED trên modul GPS chớp tắt thì mới lấy được tọa độ hiện tại
Vị trí: nên test ở modul ở vị trí thoáng mát, ở ngoài trời thì càng tốt để bắt được vị trí nhanh hơn.
Kiên nhẫn: nhiều modul có thể lấy được tọa độ ngay, nhiều cái thì rất lâu, 20 30ph tới cả tiếng, nên bạn cần phải kiên nhẫn nếu có gặp phải trường hợp này thì cứ treo máy để đó làm việc khác cho nhanh.

Lấy dữ liệu GPS với TIVA C

Lấy dữ liệu thô

Ở bước này mình sẽ bỏ PL2303 ra kết nối GPS với TIVA C và lập trình để bắt dữ liệu từ GPS gửi lên, dữ liệu này là dữ liệu thô toàn là GPGxx. Chương trình mình sẽ sử dụng 2 Serial, 1 là để giao tiếp nhận dữ liệu từ GPS với baud 9600,  1 để debug hiển thị dữ liệu lên máy tính với baud 115200, cách kết nối dây mình xin ghi chú ở trong code luôn.

/*
Chương trình đọc dữ liệu thô từ GPS
HocARM.org
Kết nối:
GPS       TIVA
---------------
VCC    |   VBUS
RX     |   PB1
TX     |   PB0
GND    |   GND
*/
#define GPSSerial Serial1

void setup() {
  // Đợi thông tin từ GPS
  while (!Serial);

  // Khởi tạo Serial debug baud 115200
  Serial.begin(115200);

  // 9600 baud is the default rate for the Ultimate GPS
  GPSSerial.begin(9600);
}

void loop() {
  // Kiểm tra nếu có dữ liệu từ GPS thì in dữ liệu này ra cổng Serial debug
  if (GPSSerial.available()) {
    char c = GPSSerial.read();
    Serial.write(c);
  }
}

Kết quả

Xem như chúng ta đã lấy được dữ liệu thô từ GPS rồi, giờ làm sao để biết đâu là kinh độ, đâu là vĩ độ, đâu là thời gian, tốc độ ? Có 2 cách để làm việc này, thứ nhất là tự viết các hàm để xử lý, cách còn lại thì đơn giản và dễ dàng hơn là sử dụng thư viện sẵn có, mình chọn cách 2 cho đơn giản, tận dụng kế thừa được cái người ta đã viết khá ổn rồi. Ở đây mình chọn thư viện TinyGPS có thay đổi và chỉnh sửa để  chạy được với TIVA C

Xử lý thông tin GPS

#include <TinyGPS.h>

/* Chương trình hiển thị thông tin GPS đơn giản
   Tạo bởi Mikal Hart
   Chỉnh sửa cho TIVA C Launchpad bởi hocARM.org
   Sử dụng TIVA với modul GPS Neo6M
   Sơ đồ kết nối chân:
  GPS       TIVA
  ---------------
  VCC    |   VBUS
  RX     |   PB1
  TX     |   PB0
  GND    |   GND
*/

TinyGPS gps;
#define ss Serial1

void setup()
{
  //Cấu hình baud debug là 115200 và baud để giao tiếp GPS là 9600
  Serial.begin(115200);
  ss.begin(9600);
  // In thông tin thư viện
  Serial.print("Simple TinyGPS library v. "); Serial.println(TinyGPS::library_version());
  Serial.println("by Mikal Hart");
  Serial.println("Modified for TIVA C Launchpad by hocARM.org");
  Serial.println();
}

void loop()
{
  bool newData = false;
  unsigned long chars;
  unsigned short sentences, failed;

  // Lấy thông tin từ GPS mỗi 1s
  for (unsigned long start = millis(); millis() - start < 1000;)
  {
    while (ss.available())
    {
      char c = ss.read();
      // Serial.write(c); // Nếu bạn muốn xem dữ liệu thô thì mở dòng này ra
      if (gps.encode(c)) // Kiểm tra thông tin từ GPS có đúng không
        newData = true;
    }
  }

  //Kiểm tra khi có dữ liệu mới đúng chuẩn thì in thông tin kinh độ, vĩ độ,...
  if (newData)
  {
    float flat, flon;
    unsigned long age;
    gps.f_get_position(&flat, &flon, &age);
    Serial.print("LAT=");
    Serial.print(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flat, 6);
    Serial.print(" LON=");
    Serial.print(flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flon, 6);
    Serial.print(" SAT=");
    Serial.print(gps.satellites() == TinyGPS::GPS_INVALID_SATELLITES ? 0 : gps.satellites());
    Serial.print(" PREC=");
    Serial.print(gps.hdop() == TinyGPS::GPS_INVALID_HDOP ? 0 : gps.hdop());
  }

  gps.stats(&chars, &sentences, &failed);
  Serial.print(" CHARS=");
  Serial.print(chars);
  Serial.print(" SENTENCES=");
  Serial.print(sentences);
  Serial.print(" CSUM ERR=");
  Serial.println(failed);
  if (chars == 0)
    Serial.println("** No characters received from GPS: check wiring **");
}

Kết quả chúng ta sẽ có được thông tin về tọa độ

Hiển thị tất cả thông tin của GPS

Coi như phần hiển thị thông tin cơ bản đã xong, giờ xử lý tiếp và hiện toàn bộ thông tin xem thế nào

#include <TinyGPS.h>

/* Chương trình hiển thị thông tin GPS đầy đủ
   Tạo bởi Mikal Hart
   Chỉnh sửa cho TIVA C Launchpad bởi hocARM.org
   Sử dụng TIVA với modul GPS Neo6M
   Sơ đồ kết nối chân:
  GPS       TIVA
  ---------------
  VCC    |   VBUS
  RX     |   PB1
  TX     |   PB0
  GND    |   GND
*/

#define ss Serial1
TinyGPS gps;

static void smartdelay(unsigned long ms);
static void print_float(float val, float invalid, int len, int prec);
static void print_int(unsigned long val, unsigned long invalid, int len);
static void print_date(TinyGPS &gps);
static void print_str(const char *str, int len);

void setup()
{
  // Cấu hình Serial
  Serial.begin(115200);
  // In thông tin thư viện
  Serial.print("Testing TinyGPS library v. "); Serial.println(TinyGPS::library_version());
  Serial.println("by Mikal Hart");
  Serial.println("Modified for TIVA C Launchpad by hocARM.org");
  Serial.println();
  Serial.println("Sats HDOP Latitude  Longitude  Fix  Date       Time     Date Alt    Course Speed Card  Distance Course Card  Chars Sentences Checksum");
  Serial.println("          (deg)     (deg)      Age                      Age  (m)    --- from GPS ----  ---- to London  ----  RX    RX        Fail");
  Serial.println("-------------------------------------------------------------------------------------------------------------------------------------");
  // Cấu hình baud đọc dữ liệu GPS 9600
  ss.begin(9600);
}

void loop()
{
  float flat, flon;
  unsigned long age, date, time, chars = 0;
  unsigned short sentences = 0, failed = 0;
  static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002;	//thông tin tọa độ London
  // Lấy thông tin gps và in ra màn hình
  print_int(gps.satellites(), TinyGPS::GPS_INVALID_SATELLITES, 5);
  print_int(gps.hdop(), TinyGPS::GPS_INVALID_HDOP, 5);
  gps.f_get_position(&flat, &flon, &age);
  print_float(flat, TinyGPS::GPS_INVALID_F_ANGLE, 10, 6);
  print_float(flon, TinyGPS::GPS_INVALID_F_ANGLE, 11, 6);
  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
  print_date(gps);
  print_float(gps.f_altitude(), TinyGPS::GPS_INVALID_F_ALTITUDE, 7, 2);
  print_float(gps.f_course(), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
  print_float(gps.f_speed_kmph(), TinyGPS::GPS_INVALID_F_SPEED, 6, 2);
  print_str(gps.f_course() == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(gps.f_course()), 6);
  print_int(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0xFFFFFFFF : (unsigned long)TinyGPS::distance_between(flat, flon, LONDON_LAT, LONDON_LON) / 1000, 0xFFFFFFFF, 9);
  print_float(flat == TinyGPS::GPS_INVALID_F_ANGLE ? TinyGPS::GPS_INVALID_F_ANGLE : TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
  print_str(flat == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON)), 6);

  gps.stats(&chars, &sentences, &failed);
  print_int(chars, 0xFFFFFFFF, 6);
  print_int(sentences, 0xFFFFFFFF, 10);
  print_int(failed, 0xFFFFFFFF, 9);
  Serial.println();
  
  smartdelay(1000);
}
// Hàm delay chờ nhận thông tin từ GPS
static void smartdelay(unsigned long ms)
{
  unsigned long start = millis();
  do 
  {
    while (ss.available())
      gps.encode(ss.read());
  } while (millis() - start < ms);
}
// Hàm in số thực
static void print_float(float val, float invalid, int len, int prec)
{
  if (val == invalid)
  {
    while (len-- > 1)
      Serial.print('*');
    Serial.print(' ');
  }
  else
  {
    Serial.print(val, prec);
    int vi = abs((int)val);
    int flen = prec + (val < 0.0 ? 2 : 1); // . and -
    flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
    for (int i=flen; i<len; ++i)
      Serial.print(' ');
  }
  smartdelay(0);
}
// Hàm in số nguyên
static void print_int(unsigned long val, unsigned long invalid, int len)
{
  char sz[32];
  if (val == invalid)
    strcpy(sz, "*******");
  else
    sprintf(sz, "%ld", val);
  sz[len] = 0;
  for (int i=strlen(sz); i<len; ++i)
    sz[i] = ' ';
  if (len > 0) 
    sz[len-1] = ' ';
  Serial.print(sz);
  smartdelay(0);
}
// Hàm in ngày tháng
static void print_date(TinyGPS &gps)
{
  int year;
  byte month, day, hour, minute, second, hundredths;
  unsigned long age;
  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
  if (age == TinyGPS::GPS_INVALID_AGE)
    Serial.print("********** ******** ");
  else
  {
    char sz[32];
    sprintf(sz, "%02d/%02d/%02d %02d:%02d:%02d ",
        month, day, year, hour, minute, second);
    Serial.print(sz);
  }
  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
  smartdelay(0);
}
// Hàm in chuỗi
static void print_str(const char *str, int len)
{
  int slen = strlen(str);
  for (int i=0; i<len; ++i)
    Serial.print(i<slen ? str[i] : ' ');
  smartdelay(0);
}

Kết quả sẽ có rất nhiều thông tin được hiển thị như hình

Tạm kết

Mình đã hướng dẫn các bạn cách test một modul GPS, đọc dữ liệu từ GPS sử dụng TIVA C và hiển thị toàn bộ thông tin từ GPS theo cách đơn giản nhất, với cách này bạn cs thể đọc được tất cả các loại GPS có trên thị trường dùng chuẩn NMEA,chuẩn dữ liệu NMEA của GPS, về những phần như cấu trúc của GPS như thế nào,cách người ta tạo ra thư viện TinyGPS xin hẹn các bạn ở một bài viết khác.