GPS (Global Positioning Sytem)

Bu projede basit bir GPS (Global Positioning System) cihazı yapacağız. GPS cihazları dünya etrafında gezen 24 uydudan gelen sinyallerin kendilerine varış süreleri arasındaki farkı hesaplayarak dünya üzerindeki konumlarını oldukça yüksek bir hassasiyetle hesaplayabilirler. GPS cihazları elde ettikleri seyrüsefer (navigasyon) bilgilerini belli bir standart (NMEA 0183 - Download kısmına bakınız) dahilinde RS232 protokolünde sürekli olarak gönderirler. Projemizde GPS sensöründen GPGGA cümlesini okuyup bu cümledeki seyrüsefer bilgilerini karakter LCD ekrana yazdıracağız. Bir karakter LCD nin nasıl kullanıldığını ve RS232 üzerinden nasıl veri alınıp verildiğini daha önceki projelerde öğrenmiştik.

Bir GPGGA cümlesi şuna benzer:
$GPGGA,161229.487,3723.2475,N,12158.3416,W,1,07,1.0,9.0,M,,,,0000*18
Bu cümleyi deşifre ettiğimizde şu bilgileri elde ederiz:

Başlık MessageID GPGGA
Atomik Saat UTC 161229.487
Enlem Latitude 3723.2475
Kuzey / Güney NS N
Boylam Longitude 12158.3416
Doğu / Batı EW W
Yer Belirleme PosFix 1
Kullanılan Uydu Sayısı Satellites 7
Yatay Çözünürlük HDOP 1.0
Rakım Altitude 9.0
Birim Unit M (Metre)

Öncelikle GPS alıcısının arka arkaya gönderdiği farklı cümleler içinden GPGGA başlıklı olanı yakalamamız gerek. Bunu GetGPSStr fonksiyonunda yapıyoruz, bunu yaparken Atmega8 'in program hafızası yetmediği için pahalı scanf fonksiyonunu kullanamayacağız. Bu yüzden tek tek karakterleri yakalayarak cümlenin tamamını Buffer değişkenine yerleştirmek zorundayız. Daha sonra bu cümlenin içinden verileri ayıklayıp her bir veriyi değişkenlere atamamız gerekir. Bu noktada her bir veri için ayrı bir değişken yaratmak yerine C dilinin güçlü yanlarından biri olan Yapıları (Structures) kullanarak kendi veri tipimizi yaratacağız.

/*
* Cem Berik
* www.berik.net
*/

#include <stdio.h>
#include <avr/io.h>
#include <string.h>
#include "lcd.h"
#include "nmea.h"

#define BUFFER_SIZE 100

extern TGPSData NavData; //TGPSData yapisal degiskeni
char Buffer[BUFFER_SIZE]; //GPS cumlesi icin degisken
char datareceived=0;
uint8_t RxIndex=0;
uint8_t record=0;

//LCD yi cikti olarak kullanmak icin
FILE lcd_str = FDEV_SETUP_STREAM(lcd_putchar, NULL, _FDEV_SETUP_WRITE);

void GetGPSStr(void) { //RS232'den cumle okur
char Temp;
loop_until_bit_is_set(UCSRA,RXC);
Temp = UDR;
if(Temp=='$')record=1;
if(record){
Buffer[RxIndex] = Temp;
RxIndex++;

if((Temp==0x0d)||(RxIndex==BUFFER_SIZE)){

Buffer[RxIndex] = '\0';
datareceived=1;
RxIndex=0;
RxIndex = 0;
record=0;
}
}
}

TDMS ConvertToDegrees(double a){ //ondalik koordinati
uint8_t xdeg,xmin; //derece dakika saniye
double xsec; //formatina cevirir
TDMS Result;
xdeg=(uint8_t)(a/100);
Result.Degree=xdeg;
xmin=(uint8_t)(a-(xdeg*100));
Result.Minute=xmin;
xsec=a-((xdeg*100)+xmin);
xsec*=60;
Result.Second=xsec;
return Result;
}

void mcu_init(void){
// USART kurulumu
// 8 Data, 1 Stop, No Parity
// Baud rate: 4800
UCSRA=0x00;
UCSRB=0x18;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x0C;
}

void EkranA(void){ //birinci ekran
char p;
if(NavData.Posfix!=0)p='+';else p='-';
TDMS Kord;
lcd_clr();
lcd_goto(1,0);
parse_GGA(Buffer);
Kord=ConvertToDegrees(NavData.Latitude);
printf("%02d %02d %02.1f%c U%dP%c",Kord.Degree,Kord.Minute,\
Kord.Second,NavData.NS,NavData.Satellites,p);
lcd_goto(2,0);
Kord=ConvertToDegrees(NavData.Longitude);
printf("%02d %02d %02.1f%c",Kord.Degree,Kord.Minute,\
Kord.Second,NavData.EW);
}

void EkranB(void){ //ikinci ekran
lcd_clr();
lcd_goto(1,0);
parse_GGA(Buffer);
printf("A%04d S%06lu",NavData.Altitude,(uint32_t)NavData.UTC);
lcd_goto(2,0);
printf("H%02.1f",NavData.HDOP);
}

//Ana Program Fonksiyonu
int main(void){
mcu_init();
lcd_init(); //LCD yi hazirla
stdout = &lcd_str; //standart cikti LCD

DDRB&=~_BV(PB7); //B7 input
PORTB|=_BV(PB7); //B7 pull-up

while(1){ //sonsuz dongu
while(datareceived==0) GetGPSStr();

if(!(strncmp("$GPGGA",Buffer,6))){
//eger PB7 1 ise birinci ekrani
//0 ise ikinci ekrani goster
if(bit_is_set(PINB,7)) EkranA(); else EkranB();
}
datareceived=0;
}
}

extern TGPSData NavData ifadesi TGPSData tipinde NavData isimli bir değişkenin projenin başka bir yerinde tanımlandığını ifade eder, bu tür durumlarda extern ifadesi kullanılır. "nmea.c" dosyasında böyle bir tanımlama yapıldığını görürsünüz. TGPSData veri tipinin standart bir veri tipi olmadığı aşikardır, bu veri tipini biz tanımladık ve tanımlama "nmea.h" dosyasında şu şekilde yapılmıştır:

typedef struct _GGAData {
char MessageID[10];
double UTC;
double Latitude;
char NS;
double Longitude;
char EW;
uint8_t Posfix;
uint8_t Satellites;
double HDOP;
uint16_t Altitude;
}TGPSData;

Gördüğünüz gibi typedef ve struct deyimleri birlikte kullanılarak yapı şeklinde yeni bir değişken tipi oluşturulmuştur, artık bu veri tipinde istediğimiz kadar değişken yaratabiliriz. Bir yapının elemanlarına . (nokta) ile ulaşılır: NavData.UTC = 123456.125).

Nmea.c dosyasında bulunan parse_GGA fonksiyonu GPGGA cümlesini parçalara ayırıp NavData yapı değişkeninin ilgili alt elemanlarına atamaktadır. Bu fonksiyonun nasıl çalıştığını, karakter katarı tipindeki verilerin nasıl farklı veri tiplerine çevrildiğini iyice öğrendikten sonra, bu fonksiyonu GPRMC gibi diğer cümle tiplerini ayıklayacak şekilde değiştirebilir, projenize hızınız ve gittiğiniz yön ile ilgili bilgileri de ekleyebilirsiniz. GPSGGA cümlesinden elde edilen bilgiler 2X20 karakter ekranımıza sığmayacağı için PB7 'yi giriş olarak tanımlayıp, ana fonksiyon içinde PB7 'ye bağlı bir butonun basılı olup olmamasına göre iki ekrandan birinin gösterilmesi pratik bir çözümdür (Resim1 ve 2).

GPS cihazları genellikle 4800 baud hızında çıktı verirler, sizin kullandığınız GPS sensörünüz eğer farklı bir hıza ayarlıysa USART ayarlarınızı değiştirmeyi unutmamalısınız. Projemizde kristal kullanmadığımız halde sorunsuz çalıştı ancak hassas zamanlamanın önemli olduğu RS232 gibi unsurların kullanıldığı projelerde kristal kullanılması ortaya çıkabilecek iletişim sorunlarını önleyecektir (Resim4).

Son olarak projemizde karakter ekranımızı B portuna bağladığımızı hatırlatmak isterim, siz projenizde başka bir bağlantıyı tercih ederseniz, "defines.h" dosyasında gerekli değişiklikleri yapmayı unutmamalısınız.

Proje Dosyaları

Proje Dosyaları