Thứ Năm, 29 tháng 11, 2018

Giao tiếp GPS

Giới thiệu

G lobal P ositioning S ystem (GPS) tận dụng tín hiệu được gửi bởi các vệ tinh trong không gian và mặt đất trạm trên Trái đất để xác định chính xác vị trí của họ trên Trái Đất.
Tín hiệu tần số vô tuyến được gửi từ vệ tinh và trạm mặt đất được nhận bởi GPS. GPS sử dụng các tín hiệu này để xác định vị trí chính xác của nó.
Bản thân GPS không cần truyền bất kỳ thông tin nào.
Các tín hiệu thu được từ vệ tinh và trạm mặt đất chứa tem thời gian khi tín hiệu được truyền đi. Bằng cách tính toán chênh lệch thời gian giữa thời gian tín hiệu được truyền và thời gian nhận tín hiệu và sử dụng tốc độ của tín hiệu, khoảng cách giữa các vệ tinh và GPS có thể được xác định bằng cách sử dụng công thức đơn giản cho khoảng cách sử dụng tốc độ và thời gian.
Sử dụng thông tin từ 3 vệ tinh trở lên, vị trí chính xác của GPS có thể được triangulated.
Mô-đun bộ thu GPS sử dụng giao tiếp USART để giao tiếp với bộ điều khiển hoặc đầu cuối PC.
Để biết thông tin về USART trong PIC18F4550 và cách sử dụng nó, hãy tham khảo chủ đề USART trong PIC18F4550 trong phần bên trong PIC.
Module thu GPS

 Sơ đồ
GPS nhận interfacing với vi điều khiển PIC
GPS với PIC18F4550 

Thí dụ

Bây giờ hãy giao diện mô-đun nhận GPS với PIC18F4550 và hiển thị Thời gian, Vĩ độ, Kinh độ và Độ cao trên màn hình LCD20x4.
Trong giao tiếp này, vi điều khiển PIC18F4550 sẽ đọc dữ liệu serially từ bộ thu GPS sử dụng truyền thông USART với tốc độ 9600 Baud.
Sau đó phân tích chuỗi “$ GPGGA” để trích xuất thông tin về thời gian, vĩ độ, kinh độ và độ cao.

Chương trình

/*
    GPS Information extraction using PIC18F4550 
*/

#include<pic18f4550.h>
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#include "Configuration_Header_File.h"
#include "LCD_20x4_H_file.h"
#include "USART_Header_File.h"

unsigned long int get_gpstime();
float get_latitude(unsigned char);
float get_longitude(unsigned char);
float get_altitude(unsigned char);
void convert_time_to_UTC(unsigned long int);
float convert_to_degrees(float);

#define GGA_Buffer_Size 80
#define GGA_Pointers_Size 20

char GGA_Buffer[GGA_Buffer_Size];              /* to store GGA string */
char GGA_CODE[3];

unsigned char N_S, E_W;                        /* for getting direction polarity */
unsigned char GGA_Pointers[GGA_Pointers_Size]; /* to store instances of ',' */
char CommaCounter;
char Data_Buffer[15];
volatile unsigned int GGA_Index;
volatile unsigned char IsItGGAString = 0;

void main(void) {
 unsigned long int Time;
 float Latitude,Longitude,Altitude;
 char GPS_Buffer[15];
    
 OSCCON = 0x72;      /* use internal osc. of 8MHz Freq. */
 LCD_Init();
 INTCONbits.GIE=1;   /* enable Global Interrupt */
 INTCONbits.PEIE=1;  /* enable Peripheral Interrupt */
 PIE1bits.RCIE=1;    /* enable Receive Interrupt */
 USART_Init(9600);
 
 while(1){
 memset(GPS_Buffer,0,15);
 LCD_String_xy(1,0,"UTC Time: ");
 Time = get_gpstime();            /* Extract Time */
 convert_time_to_UTC(Time);       /* convert time to UTC */
 LCD_String(Data_Buffer);
 LCD_String("  ");
  
 LCD_String_xy(2,0,"Lat: ");
 Latitude = get_latitude(GGA_Pointers[0]);  /* Extract Latitude */
 Latitude = convert_to_degrees(Latitude);   /* convert raw latitude in degree decimal*/
 sprintf(GPS_Buffer,"%.05f",Latitude);  /* convert float value to string */
 LCD_String(GPS_Buffer);               /* display latitude in degree */
 memset(GPS_Buffer,0,15);
  
 LCD_String_xy(3,0,"Long: ");
 Longitude = get_longitude(GGA_Pointers[2]); /* Extract Latitude */
 Longitude = convert_to_degrees(Longitude); /* convert raw longitude in degree decimal*/
 sprintf(GPS_Buffer,"%.05f",Longitude);  /* convert float value to string */
 LCD_String(GPS_Buffer);               /* display latitude in degree */
 memset(GPS_Buffer,0,15);
   
 LCD_String_xy(4,0,"Alt: ");
 Altitude = get_altitude(GGA_Pointers[7]);  /* Extract Latitude */
 sprintf(GPS_Buffer,"%.2f",Altitude);  /* convert float value to string */
 LCD_String(GPS_Buffer);               /* display latitude in degree */

 }
}

unsigned long int get_gpstime(){
 unsigned char index;
 unsigned char Time_Buffer[15];
 unsigned long int _Time;
 
 /* parse Time in GGA string stored in buffer */
 for(index = 0;GGA_Buffer[index]!=','; index++){  
  Time_Buffer[index] = GGA_Buffer[index];
 }
 _Time= atol(Time_Buffer);        /* convert string of Time to integer */
 return _Time;                    /* return integer raw value of Time */        
}

float get_latitude(char lat_pointer){
 unsigned char lat_index = lat_pointer+1; /* index pointing to the latitude */
 unsigned char index = 0;
 char Lat_Buffer[15];
 float _latitude;

 /* parse Latitude in GGA string stored in buffer */
 for(;GGA_Buffer[lat_index]!=',';lat_index++){
  Lat_Buffer[index]= GGA_Buffer[lat_index];
  index++;
 }
 lat_index++;
 N_S = GGA_Buffer[lat_index];
 _latitude = atof(Lat_Buffer);     /* convert string of latitude to float */
 return _latitude;                 /* return float raw value of Latitude */
}

float get_longitude(unsigned char long_pointer){
 unsigned char long_index;
 unsigned char index = long_pointer+1;  /* index pointing to the longitude */
 char Long_Buffer[15];
 float _longitude;
 long_index=0;
 
 /* parse Longitude in GGA string stored in buffer */
 for( ; GGA_Buffer[index]!=','; index++){
  Long_Buffer[long_index]= GGA_Buffer[index];
  long_index++;
 }
 long_index++;
 E_W = GGA_Buffer[long_index];
 _longitude = atof(Long_Buffer);    /* convert string of longitude to float */
 return _longitude;                 /* return float raw value of Longitude */
}

float get_altitude(unsigned char alt_pointer){
 unsigned char alt_index;
 unsigned char index = alt_pointer+1;  /* index pointing to the altitude */
 char Alt_Buffer[12];
 float _Altitude;
 alt_index=0;
 
 /* parse Altitude in GGA string stored in buffer */
 for( ; GGA_Buffer[index]!=','; index++){
  Alt_Buffer[alt_index]= GGA_Buffer[index];
  alt_index++;
 }
 _Altitude = atof(Alt_Buffer);   /* convert string of altitude to float */ 
 return _Altitude;     /* return float raw value of Altitude */
}

void convert_time_to_UTC(unsigned long int UTC_Time)
{
 unsigned int hour, min, sec;
  
 hour = (UTC_Time / 10000);                   /* extract hour from integer */
 min = (UTC_Time % 10000) / 100;              /* extract minute from integer */
 sec = (UTC_Time % 10000) % 100;              /* extract second from integer*/

 sprintf(Data_Buffer, "%d:%d:%d", hour,min,sec); /* store UTC time in buffer */
 
}

float convert_to_degrees(float NMEA_lat_long){
 
 float minutes, dec_deg, decimal;
 int degrees;
 float position;

 degrees = (int)(NMEA_lat_long/100.00);
 minutes = NMEA_lat_long - degrees*100.00;
 dec_deg = minutes / 60.00;
 decimal = degrees + dec_deg;
 if (N_S == 'S' || E_W == 'W') { // return negative
  decimal *= -1;
    } 
 /* convert raw latitude/longitude into degree format */
 return decimal;
}

void interrupt Serial_ISR()   
{
  
 if(RCIF){
  GIE  = 0;       /* Disable global interrupt */
  unsigned char received_char = RCREG;
        if(RCSTAbits.OERR){                 /* check if any overrun occur due to continuous reception */           
            CREN = 0;
            NOP();
            CREN=1;
        }
        
  if(received_char =='$'){          /* check for '$' */
   GGA_Index = 0;
   IsItGGAString = 0;
   CommaCounter = 0;
  }
  else if(IsItGGAString == 1){        /* if true save GGA info. into buffer */
   if(received_char == ',' ) GGA_Pointers[CommaCounter++] = GGA_Index;    /* store instances of ',' in buffer */
   GGA_Buffer[GGA_Index++] = received_char;
        }
  else if(GGA_CODE[0] == 'G' && GGA_CODE[1] == 'G' && GGA_CODE[2] == 'A'){ /* check for GGA string */
   IsItGGAString = 1;
   GGA_CODE[0] = 0; GGA_CODE[1] = 0; GGA_CODE[2] = 0; 
  }
  else{
   GGA_CODE[0] = GGA_CODE[1];  GGA_CODE[1] = GGA_CODE[2]; GGA_CODE[2] = received_char; 
  } 
 }
}

Cách tính toán vĩ độ và kinh độ ở dạng tọa độ GPS

Chúng tôi nhận được Latitude và Kinh độ từ chuỗi GGA có dạng ddmm.mmmm và dddmm.mmmm tương ứng.
Ở đâu,
D - độ
M - phút
Bây giờ, chúng ta có thể chuyển đổi chuỗi vĩ độ và kinh độ đã nhận trong DMS (Độ Phút Bằng) và Độ thập phân.
DMS - [dd] độ, [mm] phút, [(.mmmm) * 60] giây
Độ thập phân độ - [dd] độ + (mm.mmmm / 60)
Ví dụ: Chúng tôi có dữ liệu Lat / Long theo định dạng NMEA
Vĩ độ - 1829.9639
Kinh độ - 07347.6174
Bây giờ, chuyển đổi chúng theo định dạng sau -
DMS - 18 ° độ 29 phút 57.834 giây = 18.499398
       Code
Tập tin đính kèm


Không có nhận xét nào:

Đăng nhận xét