Bài 13 : Vui vẻ cùng Raspberry Pi - kết nối GPS

CHÚ Ý : Từ 2019 MLAB có thêm một website cho riêng Raspberry Pi và trở thành website chính về Raspberry Pi tại MLAB, các thông tin về sản phẩm - tin tức cập nhật về Raspberry Pi - Bài viết kỹ thuật hỗ trợ cho Raspberry Pi, ... MLAB cập nhật tại website : pivietnam.com.vn 

 

MLAB trân trọng thông báo tới quý khách hàng!!! 

Các bạn có thể tham khảo các bài viết hỗ trợ kỹ thuật và các tin tức mới nhất tại phần "tin tức"trên website PVIETNAM.COM.VN

Bài viết hỗ trợ kỹ thuật tại website PIVIETNAM.COM.VN - Bài 13: Vui vẻ cùng Raspberry Pi - kết nối GPS (Link here)

1. Giới thiệu


Hệ thống GPS (Global Positioning System) là hệ thống xác định vị trí toàn cầu dựa trên hệ thống vệ tinh. GPS được triển khai và quản lý bởi bộ quốc phòng Hoa Kỳ với mục đích ban đầu dành cho quân sự và sau đó được mở tự do cho dân sự ở một mức độ nhất định. Trên thế giới còn có những hệ thống định vị khác như của Nga (GLONASS – quân sự), trung quốc (Bei Dou- quân sự) và liên minh châu âu (Galileo – mục đích dành cho dân sự). GPS sẽ cung cấp thông tin vị trí địa lý và thời gian (UTC) tới tất cả các thiết bị bắt GPS.

Module GPS L70-R do MLAB thiết kế dựa trên module L70-R của hãng Quectel, loại module GPS mà đang được sử dụng nhiều tại các công ty làm về giám sát hành trình ở Việt Nam.

 

Hình 1: module GPS L70-R

Các đặc điểm của Module :

-      Xây dựng dựa trên L70-R. Các thông số xem trực tiếp từ tài liệu GPS l&0-R

-      Nguồn cấp 3.3VDC - 5VDC.

-      Giao tiếp UART (4800 – 115200bps)

-      Có chân điều khiển việc bật/tắt nguồn cấp cho module

-      Có chân báo tín hiệu khi bắt được tín hiệu GPS.

-      Pin 3V dự phòng dành cho bộ thời gian thực khi mất nguồn cấp chính.

-      Dây ăng ten.

Sử dụng các chân :

chân pin GPS L70-R

-      VIN: chân cấp nguồn cho module, từ 3.3VDC - 5VDC.  MCU và Module GPS L70-R cần cấp chung nguồn 5V/3.3V để 2 thiết bị tương thích mức điện áp giao tiếp UART

-      GND: 0VDC

-      RST: là chân reset module, tích cực ở mức cao

-      PPS: là chân báo tín hiệu khi bắt được tín hiệu GPS, tín hiệu này dưới dạng xung 1Hz

-      RXD: là chân xuất tín hiệu UART của  module, chân này được nối với chân RXD của MCU

-      TXD: là chân đọc tín hiệu UART của  module, chân này được nối với chân TXD của MCU

-      EN: dùng để bật/tắt nguồn cấp cho module. Mặc định, nguồn luôn được cấp cho module, với chân EN để hở hoặc được kéo xuống mức thấp . Để tắt module, đưa chân EN lên mức cao.

Tài liệu về GPS L70-R  :

-      Hardware Design

-      Protocol Specification

-      GNSS Low Power Mode Application Note

Chương trình và kết quả đạt được

kết quả demo gps-boss
 

 

2. Thực hiện


2.1. Chuẩn bị

a)  Phần cứng bao gồm :

-      Raspberry Pi

-      GPS L70-R

-      Dây chuyển USB-TTL PL2303

Kết nối giữa USB-TTL với GPS :

-      GPS : Để đơn giản có thể cắm chân Reset với chân GND.

-      Chân VCC của USB-TTL với Vin.

-      Chân GND của USB-TTL với GND.

-      Chân Tx của USB-TTL với Tx, Rx với Rx của module. Chính xác là như vậy, thiết kế chân Tx của module ý chỉ tới kết nối chân Tx vào đấy và Rx ý chỉ kết nối chân Rx (đây là cách thiết kế hơi dị của MLAB).

-      Chân EN có thể bỏ trống.

Kết nối giữa USB-TTL với Raspberry Pi : cắm vào cổng USB bất kỳ.

b) Phần mềm

Thư viện wiringpi serial.  Đã được đề cập trong tutorial 4 : lập trình Raspberry Pi giao tiếp Uart.

2.2 Thực hiện

Trong bài hướng dẫn này sẽ hướng dẫn các bạn xây dựng một ứng dụng cơ bản đối với module GPS là lấy tọa độ địa lý và thông tin về thời gian thực. Dựa vào tọa độ sẽ dùng google map API để biết địa chỉ (địa chỉ nhà tên đường thành phố, đất nước).

a) Dữ liệu thu được của module GPS

Khi bắt đầu bật module GPS, thường sẽ phải đợi hơn 1 phút để module ổn định, module sẽ bắt tín hiệu của 3,4 hoặc nhiều hơn vệ tinh để thu thập thông tin thời gian, ngày tháng, tính toán giá trị tọa độ. Chân PPS sẽ xuất ra tín hiệu 1Hz (mặc định) để thông báo. Sau đó tùy theo thiết lập người dùng mà module trả về các thông số tương ứng thông qua UART.

Module hỗ trợ gói tin chuẩn NMEA. Mặc định module sẽ trả về lần lượt 6 gói tin : GPRMC, GPVTG, GPGGA, GPGSA, GPGSV, GPGLL với mục đích khác nhau. Người dùng có thể gửi thông tin thiết lập module để module chỉ trả về một/vài gói tin.

Ở đây mình chỉ quan tâm tới gói tin GPRMC. Dưới đây là một ví dụ :

$GPRMC,104749.000,A,3150.7846,N,11711.9256,E,0.16,48.45,230516,,,A*5D<CR><LF>

Mỗi thông tin sẽ được phân cách nhau bằng một dấu phẩy. Trong đó :

-      Gói tin luôn được bắt đầu với dấu “$” (có thể thay đổi được).

-      GPRMC : mã tin nhắn.

-      UTC time : thời gian ở định dạng ‘hhmmss.sss’. Đây là giờ UTC.

-      Data valid : ‘V’ tức là gói tin không chính xác, bỏ qua gói tin này. ‘A’ gói tin chính xác.

-      Latitude : vĩ độ ở định dạng ‘dddmm.mmmm’ (degree và minutes).

-      N/S : ‘N’ chỉ vùng bắc bán cầu, ‘S’ chỉ nam bán cầu.

-      Longtitude : longtitude ở định dạng ‘dddmm.mmmm’ (degree và minutes).

-      E/W : ‘E’ chỉ đông bán cầu và ‘W’ chỉ tây bán cầu.

-      Speed : tốc độ dịch chuyển trên mặt đất.

-      COG : góc hướng di chuyển. Góc này thường so với phương bắc.

-      Date : ngày UTC theo định dạng ‘ddmmyy’.

-      Magnectic Variation : không sử dụng

-      E/W : không sử dụng

-      Position Mode : ‘N’ là GPS fix, ‘A’ tự động thiết lập GPS fix. ‘D’ là vi phân GPS fix

-      * : ký tự báo kết thúc vùng dữ liệu.

-      Checksum : dưới dạng hexa.

-      <CR><LF> : gói tin được kết thúc bằng ký tự carriage return và line feed (new line).

Như vậy chỉ với gói tin GPRMC đã có đầy đủ thông tin cho ứng dụng. Ta chỉ cần cắt thông tin về UTC time, latitude, longtitude và date.

Có những thông số trong gói tin mình không sử dụng, cũng chưa có điều kiện tìm hiểu và thử nghiệm vì nó không cần thiết cho ứng dụng của mình. Để hiểu rõ hơn nữa về thông số bạn nên đọc tài liệu “GPS L70-R specification”. Mọi thông tin mình đều trích xuất từ tài liệu này.

b) Cài đặt module GPS

Có rất nhiều gói tin cài đặt cho module GPS như các chế độ khởi động, chế độ tiết kiệm, gói tin mong muốn nhận được. Mặc định GPS sẽ sau 1s trả về lần lượt 6 gói tin bên trên. Mình chỉ cần sử dụng một gói tin GPRMC nên sẽ cài đật cho module gửi duy nhất một gói tin GPRMC về. Mọi thông tin về gói tin nằm trong file GPS specification.

Gói tin PMTK314 thiết lập gói tin NMEA trả về. Có tất cả 19 gói tin tuy nhiên module mới hỗ trợ 6 gói.

$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29\r\n

Trong đó :

-      $ : ký tự bắt đầu gói tin.

-      PMTK : mã ký tự cho biết nó thuộc chuẩn gói tin MTK

-      Mã gói tin : 314.

-      GLL : thiết lập gói tin GPGLL

-      RMC: thiết lập gói tin GPRMC.

-      VTG : thiết lập gói tin GPVTG.

-      GGA : thiết lập gói tin GPGGA.

-      GSA : thiết lập gói tin GPGSA.

-      GSV : thiết lập gói tin GPGSV.

-      11 thiết lập tiếp theo vẫn chưa được sử dụng và giá trị của nó luôn là 0.

-      ZDA : thiết lập gói tin GPZDA.

-      Thiết lập chưa được sử dụng. Giá trị của nó bằng 0.

-      * : ký tự báo kết thúc chuỗi dữ liệu.

-      Checksum : dạng mã hex.

-      <CR><LF> : gói tin được kết thúc bằng ký tự carriage return và line feed (new line).

Các giá trị có thể thiết lập là :

-      0 : không trả về gói tin.

-      1 : trả về khi khi 1 vị trí được fix.

-      2 : trả về khi khi 2 vị trí được fix.

-      3 : trả về khi khi 3 vị trí được fix.

-      4 : trả về khi khi 4 vị trí được fix.

-      5 : trả về khi khi 5 vị trí được fix.

Ngay sau khi gửi lệnh này tơi module, kết quả trả về có dạng . Nếu không trả về có nghĩa là thiết lập không được thực hiện.

$PMTK001,314,3*36<CR><LF>

c) Thuật toán chương trình

Thuật toán có thể chia làm 2 phần. Phần đầu từ lúc bắt đầu chương trình tới khi nhận được gói tin trả về và phần sau là chương trình xử lý với gói tin đó. Dưới đây là thuật toán cho phần đầu. Bên trái là lưu đồ và bên phải là hàm tương ứng trong chương trình. Để tiện theo dõi có thể xem toàn bộ chương trình trên github của mình.

Sơ đồ thuật toán gps 1

 

Bước 1 : kết nối tới cổng USB nơi có PL2303 cắm vào. Để kiểm tra thiết bị đang nằm trên cổng USB nào dùng lệnh :

dmesg | grep tty

Kết quả sẽ trả về các Serial trên Pi. Trong đó sẽ có kết quả dạng như bên dưới:

pl2303 converter now attached to ttyUSB0

Tức là PL2303 đang kết nối tới cổng ttyUSB0.

Chú ý hàm serialOpen ("/dev/ttyUSB0", 9600) trong đó ttyUSB0 sẽ là cổng USB, đổi tên cổng tương ứng với cổng bên trên tìm được. Baudrate = 9600.

Bước 2 : Gửi lệnh thiết lập GPS. Nếu không gửi tin thì nó trả về các gói tin mặc định.

Bước 3 : Chờ đợi dữ liệu GPS trả về. Lưu dữ liệu và phân tích xem thuộc gói tin nào. Trong code mình làm sẵn phân trường hợp cho cả 6 gói tin qua cấu trúc switch-case. Mỗi gói tin sẽ có hàm xử lý riêng tưng ứng. Trong code có nhiều dòng prinf() được comment lại, các bạn bật lên để hiển thị nhiều thông tin hơn.

Có thể sử dụng chân PPS làm chân báo khi GPS đã bắt được tín hiệu gps. Ở đây mình không sử dụng, chỉ đơn thuần là đợi gói tin qua Uart. Vì thế sau khi khởi động tới lúc module ổn định (mất khoảng 1 phút) sẽ có rất nhiều gói tin sai truyền tới Raspberry. Việc này cũng không gây ảnh hưởng gì vì mình có cách xử lý với nó. Hãy chú ý tới phần Data valid của gói tin GPRMC, nếu nó là ‘V’ tức là gói tin sai còn ‘A’ tức gói tin đã chính xác.

Phần thuật toán thứ hai sẽ giải quyết gói tin GPRMC và lấy thông tin địa điểm từ google map.

sơ đồ thuật toán gps 2

 

Thời gian trong gói tin GPRMC ở vị trí số 1, ngày tháng ở vị trí số 9, vĩ độ ở vị trí số 3, kinh độ ở vị trí số 5 (vị trí ở đây không tính dấu ‘$’). Chương trình sẽ cắt dữ liệu nhờ bằng dấu phẩy ngăn cách giữa dữ liệu, và dấu ‘*’ cuối cùng.

Tọa độ từ moduel GPS trả về dưới dạng “ddmm.mmmm’ trong khi định dạng cần gửi cho google map là decimal degree (). Công thức để chuyển đổi rất đơn giản :

Decimal = degree + minutes*60 = dd + mm.mmmm*60

Ví dụ vĩ độ : 1024.1234 chuyển sang dạng decimal sẽ bằng :

decimal = 10 + 24.1234*60 = 1457.404.

 Google map hỗ trợ API cho việc chuyển đổi tọa độ sang vị trí địa lý thật bao gồm địa chỉ tên đường, quận huyện, thành phố đất nước. Nó giống hệt như tra google map vậy. Hãy sao chép dòng địa chỉ dưới đây và điền vào thanh địa chỉ URL trình duyệt.

http://maps.googleapis.com/maps/api/geocode/json?latlng=21.032293, 105.853156

Nhấn enter và kết quả trả về sẽ hiển thị trên màn hình. Chuỗi json bao gồm rất nhiều thông tin được chia nhỏ. Ta sẽ chú ý tới “formatted_address” : “38 Cầu Gỗ, Hàng Bạc, Hoàn Kiếm, Hà Nội, Vietnam”. Địa chỉ tọa độ của dòng địa chỉ là 21.032293, 105.853156 và quy đổi ra địa chỉ thật là “38 Cầu Gỗ, Hàng Bạc, Hoàn Kiếm, Hà Nội, Vietnam”.

Như vậy chương trình chỉ cần thay đổi tọa độ của chuỗi địa chỉ bên trên, gửi tới google map API qua phương thức GET HTTP là sẽ có chuỗi json trả về. Ta sẽ cắt lấy địa chỉ từ chuỗi json đó. Chương trình để gửi thông tin bằng phương thức HTTP khá giống với chương trình cho TCP/IP. Chỉ cần thay đổi thiết lập socket(AF_INET, SOCK_STREAM, 0) và serv_addr.sin_family = AF_INET. Xem bài hướng dẫn lập trình giao thức mạng TCP/IP của mình để biết thêm hoặc đơn giản bạn chỉ cần dùng hàm của mình là đủ.

Google map có nhiều địa chỉ IP, mình chọn IP là "172.217.4.170".

Để biên dịch chương trình dùng lệnh sau 

g++ -std=c++11 gps.cc -o gps -lwiringPi

Cắm kết nối PL2303, có thể đợi 1 phút cho module bắt được tín hiệu gps ổn định (hoặc không cần cũng được, bên dưới mình đợi 40s) sau đó chạy chương trình gps. Bạn nên cắm dây ăng ten lên cao để bắt được tín hiệu gps tốt hơn.

Kết quả :

kết quả demo gps

 

Chương trình gps-boss.cc được cải tiến từ chương trình gps.cc . Với mục đích vui vẻ là chính, chương trình sẽ trả về thời gian và địa chỉ khi người dùng đặt câu hỏi trong đó có chứa “whats time” và “where is this”. Cơ chế hỏi đáp này cũng rất đơn giản vì số lượng câu hỏi nhỏ và cố định nên ta chỉ cần so sánh chuỗi ký tự nhập vào với hai lệnh trên là được.

Kết quả là hình trên đầu bài.

2.3. Tham khảo

[1]       http://thegioidinhvi.vn/dinh-vi-toan-cau-va-ung-dung/tim-hieu-ve-he-thong-dinh-vi-toan-cau-gps

[2]       https://en.wikipedia.org/wiki/Global_Positioning_System

[3]       https://en.wikipedia.org/wiki/NMEA_0183

[4]       http://techslides.com/convert-latitude-and-longitude-to-a-street-address

 

3.  Những hạn chế cần cải tiến


Chương trình GPS trên đây mới tập trung vào việc thử nghiệm tính năng cơ bản của hệ thống GPS. Để phát triển tốt hơn với module cần đào sâu hơn về kiến thức GPS, đọc tài liệu datasheet mà module cung cấp. Vẫn còn nhiều gói tin chưa được đề cập với các thông số hữu ích khác như tốc độ hướng quay v.vv hay thiết lập chế độ tiết kiệm cho mdule GPS. 

 

 

 

 

 

 

 

 

 

 

 

 

 

Viết đánh giá

Họ và tên:


Đánh giá của bạn: Lưu ý: Không hỗ trợ HTML!

Bình chọn: Dở            Hay

Nhập mã bảo vệ: