Programování GPS modulu NEO7-M

V rámci přípravy na stavbu čítače jsem chtěl ověřit, zda budu umět naprogramovat GPS modul, který chceme použít jako zdroj přesného kmitočtu pro časovou základnu. Princip získání kmitočtu popsal např OK1DXD. Já popíšu nastavení modulu NEO7-M a jeho komunikaci s procesorem řady ATmega.

Samozřejmě, mohl bych použít některou z volně dostupných knihoven, např. pro Arduino, ale v budoucnu budu chtít vlastní řešení s procesorem ATXmega, takže pár řádků nové funkce napíšu podle PDF dokumentu na stránkách společnosti U-Blox.

Modul komunikuje po sériové lince rychlostí 9600 baudů, je přenášeno 8 bitů, jeden stop bit, bez parity. Tak je potřeba nastavit UART procesoru, v mém případě ATmega162:

 UBRR1H = 0;
 UBRR1L = 210;        // 16MHz rychlost prenosu 9600 baudu 
 UCSR1A = 0b00000010; // dvojnasobna rychlost
 UCSR1B = 0b00011000; // povoleni vysilace a prijimace,
                      // preruseni pri vysilani i prijimani zakazano
 UCSR1C = 0b10000110; // bez parity, osm bitu

Modul jsem zapájel do univerzální desky (předtím sloužila k jiným pokusům, tak je na ní víc věcí, než je nutné)

Modul sám, na svém vývodu TX periodicky vysílá informace, které získává ze satelitů. Mě zajímá způsob, jak dostat na vývod modulu Timepulse požadovaný kmitočet, např. 1MHz. Vývod Timepulse je připojen na zelenou LED, která je připájena na modulu. Z ní je připájeným drátkem odebrán signál k dalšímu použití.

Zpráva, kterou je potřeba poslat na pin RX modulu, je popsána v kapitole CFG-TP5, souboru u-blox7.

Funkce, která nastaví kmitočet a střídu je zde:

void NEO7M_CGF_TP5( uint32_t Freq, uint32_t Period, uint32_t FreqLock, 
uint32_t PeriodLock, uint16_t CableDelay, uint32_t UserDelay )
{
 uint32_t NeoData[40]; // data pro odeslani
 uint32_t NeoCounter;  // pocitadlo dat
 
 Period *= 42949672;     // procenta stridy prepocita na 0.00000... procent
 PeriodLock *= 42949672; // procenta stridy prepocita na 0.00000... procent
 
 NeoData[ 0] = 0xB5;
 NeoData[ 1] = 0x62;
 NeoData[ 2] = 0x06;
 NeoData[ 3] = 0x31; // hlavicka
 NeoData[ 4] = 0x20; // bude odeslano 32 bajtu
 NeoData[ 5] = 0x00;
 NeoData[ 6] = 0x00;
 NeoData[ 7] = 0x00;
 NeoData[ 8] = 0x00;
 NeoData[ 9] = 0x00;

 NeoData[10] = CableDelay & 0x00FF; // nejnizsi bajt jde jako prvni
 CableDelay >>= 8;
 NeoData[11] = CableDelay & 0x00FF; // zpozdeni na kabelu

 NeoData[12] = 0x00;
 NeoData[13] = 0x00;

 NeoData[14] = Freq & 0x000000FF;   // nejnizsi bajt jde jako prvni
 Freq >>= 8;
 NeoData[15] = Freq & 0x000000FF;
 Freq >>= 8;
 NeoData[16] = Freq & 0x000000FF;
 Freq >>= 8;
 NeoData[17] = Freq & 0x000000FF;     // frekvence, kdyz nejsou data z GPS

 NeoData[18] = FreqLock & 0x000000FF; // nejnizsi bajt jde jako prvni
 FreqLock >>= 8;
 NeoData[19] = FreqLock & 0x000000FF;
 FreqLock >>= 8;
 NeoData[20] = FreqLock & 0x000000FF;
 FreqLock >>= 8;
 NeoData[21] = FreqLock & 0x000000FF; // frekvence podle GPS

 NeoData[22] = Period & 0x000000FF;   // nejnizsi bajt jde jako prvni
 Period >>= 8;
 NeoData[23] = Period & 0x000000FF;
 Period >>= 8;
 NeoData[24] = Period & 0x000000FF;
 Period >>= 8;
 NeoData[25] = Period & 0x000000FF;     // strida signalu, kdyz nejsou data

 NeoData[26] = PeriodLock & 0x000000FF; // nejnizsi bajt jde jako prvni
 PeriodLock >>= 8;
 NeoData[27] = PeriodLock & 0x000000FF;
 PeriodLock >>= 8;
 NeoData[28] = PeriodLock & 0x000000FF;
 PeriodLock >>= 8;
 NeoData[29] = PeriodLock & 0x000000FF; // strida signalu podle GPS

 NeoData[30] = UserDelay & 0x000000FF;  // nejnizsi bajt jde jako prvni
 UserDelay >>= 8;
 NeoData[31] = UserDelay & 0x000000FF;
 UserDelay >>= 8;
 NeoData[32] = UserDelay & 0x000000FF;
 UserDelay >>= 8;
 NeoData[33] = UserDelay & 0x000000FF;

 NeoData[34] = 0x6F; // ovladaci bity
 NeoData[35] = 0x00;
 NeoData[36] = 0x00;
 NeoData[37] = 0x00;

 for ( NeoCounter = 2; NeoCounter < 38; NeoCounter++ ) // pocita kontrolni soucet
 {
   NeoData[38] += NeoData[NeoCounter];
   NeoData[39] += NeoData[38];
 }

 for ( NeoCounter = 0; NeoCounter < 40; NeoCounter++ ) // odesila data na seriovy kanal
 {
   while( !( UCSR1A & ( 1 << UDRE1 )));
   UDR1 = NeoData[NeoCounter];
 }
}

Protože zprávu budu před odesláním potřebovat pro výpočet kontrolního součtu, připravím ji v poli dat. Podle specifikace u-blox7 je možno v jednotlivých proměnných zadat periodu, nebo kmitočet. Já nastavil řídící bity tak, abych mohl nastavovat kmitočet a střídu v procentech. Kmitočet je v Hz, uložen do 32-bitového čísla. Střída je v nějakých miliontinách procent uložena do 32-bitového čísla. Já tak přesné rozlišení nepotřebuji, proto jsem jednotky procent vynásobil číslem 42 949 672.

Nakonec se vypočítá kontrolní součet z celé zprávy, není zahrnuta hlavička. Jak jej vypočítat je popsáno v kapitole UBX Checksum souboru u-blox7 a pak je zpráva odeslána na UART.

No a tady je screenshot osciloskopu, který je připojen na pin Timepulse:

Napsat komentář

Vaše emailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *