Popis konstrukce jednoduché navigace s RPi Pico, Waveshare L76K GPS modulem a LCD displejem 1602 (I2c).

Toto je neúspěšná vývojová verze, která obsahuje chyby (např. sběr dat z L76K modulu po sériové lince je naprosto špatně). A pracovní verzí zůstane, protože jsem udělal lepší projekt.

L76K GPS modul se připojuje na sériovou linku (UART1) RX pin na GPIO4, TX pin na GPIO5, modul musí být napájen z 5V. Nastvení sériové linky je 9600 baudů, 8 bitů, 1 stop bit, žádná parita (9600 8N1). L76K komunikuje protokolem NMEA 0183.

Displej 1602 se připojuje na I2c1 sběrnici, SDA (data) na GPIO6 a SCK (hodiny) na GPIO7, modul musí být napájen z 5V. Použil jsem ho, protože byl po ruce. OLED displeje teď nemám.

Zapojení navigace (žlutý TX, bílý RX L76K modulu; oranžový SCL, hnědý SDA displeje; červený 5V, černý GND)

IMG 20251012 233131

Zapojení L76K modulu vlevo (v tomto pohledu anténa směřuje dolů — v reálném provozu se modul musí otočit)

L76K GPS Module win

Program

Nejtěžší bylo správně naprogramovat komunikaci po sériové lince, protože L76K sype data, jak se mu zachce. Parsování NMEA vět jsem musel udělat ručně, protože knihovnu libnmea se mi nepodařilo rozchodit. Zatím umím parsovat GNGGA větu a to docela stačí, protože získám souřadnice pro zeměpisnou šířku, zeměpisnou délku, nadmořskou výšku a aktuální světový čas (UTC). Další věty budou postupně v dalěích verzích programu.

navigace5.c
/* navigace5.c
 * (c) Jirka Chráska 2025; <jirka@lixis.cz>
 * Testovani navigacniho modulu L76K. https://www.waveshare.com/wiki/L76K_GPS_Module
 * Modul musí být napájen z 5V, jinak funguje blbě.
 * Test v kanceláři:
 */
#define VYVOJ 0

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "pico/stdlib.h"
#include "hardware/uart.h"
#include "hardware/rtc.h"
#include "pico/util/datetime.h"
#include "lcd_czech_chars.h"

#define UART_ID         uart1 
#define BAUD_RATE       9600
#define DATA_BITS       8
#define STOP_BITS       1
#define PARITY          UART_PARITY_NONE
#define UART_TX_PIN     4
#define UART_RX_PIN     5

#define BUFLEN 128

#define LED_PIN 25

// parsování věty $GNZDA,155647.000,19,10,2025,00
// tady mi to nikdy nevrátí korektní checksum
// informace o času
typedef struct {
        int year;
        int month;
        int day;
        int dotw;   // pořadí dne v týdnu 0 je neděle
        int hour;
        int min;
        int sec;
        int msec;
        int parse_ok;
} GNZDA;
/* Indexy */
#define NMEA_GNZDA_TIME                 1
#define NMEA_GNZDA_DAY                  2
#define NMEA_GNZDA_MONTH                3
#define NMEA_GNZDA_YEAR                 4
#define NMEA_GNZDA_DAYOFWEEK            5

GNZDA nmea_gnzda( char *data, int len )
{
GNZDA result = {0, 0, 0, 0, 0, 0, 0};    
int section = 0;
char *str1;
char *saveptr1;
char *token;
char buf[10];

    for(section=0, str1 = data ; section<=5; section++, str1=NULL) {
        token = strtok_r(str1,",",&saveptr1);
        if( token == NULL ) {
            break;
            }
        switch ( section ) {
            case 0: // nazev
                if( strcmp(token,"$GNZDA") == 0 ) { result.parse_ok=1; }
                break;
            case NMEA_GNZDA_TIME: // cas
                buf[0] = token[0]; buf[1]=token[1]; buf[2] = '\0';
                result.hour = atoi(buf);
                buf[0] = token[2]; buf[1]=token[3]; buf[2] = '\0';
                result.min = atoi(buf);
                buf[0] = token[4]; buf[1]=token[5]; buf[2] = '\0';
                result.sec = atoi(buf);
                result.msec = atoi(&token[7]);
                result.parse_ok++;
                break;
            case NMEA_GNZDA_DAY: // den v měsíci
                result.day = atoi(token);
                result.parse_ok++;
                break;
            case NMEA_GNZDA_MONTH: // měsíc
                result.month = atoi(token);
                result.parse_ok++;
                break;
            case NMEA_GNZDA_YEAR: // rok
                result.year = atoi(token);
                result.parse_ok++;
                break;
            case NMEA_GNZDA_DAYOFWEEK: // den v týdnu
                result.dotw = atoi(token);
                result.parse_ok++;
                break;
            default:
                result.parse_ok = -1;
                break;
        }
    }
return result;    
}
//---------------------------------------------------
// informace o zeměpisných souřadnicích
typedef struct {
    double  time;
    int     time_hour;
    int     time_min;
    int     time_sec;
    int     time_msec;
    double  latitude;
    uint8_t latitude_ch;
    int     latitude_degree;
    int     latitude_minutes;
    double  latitude_vteriny;
    double  longitude;
    uint8_t longitude_ch;
    int     longitude_degree;
    int     longitude_minutes;
    double  longitude_vteriny;
    int     fix;
    int     satelites;
    double  horizontal_dilution;
    double  altitude;
    uint8_t altitude_unit;
    double  geoid_height;
    uint8_t geoid_height_unit;
    uint8_t checksum;
    bool    checksum_ok;
    int     parse_ok;
} GNGGA;

/* Indexy */
#define NMEA_GPGGA_TIME                 1
#define NMEA_GPGGA_LATITUDE             2
#define NMEA_GPGGA_LATITUDE_CARDINAL    3
#define NMEA_GPGGA_LONGITUDE            4
#define NMEA_GPGGA_LONGITUDE_CARDINAL   5
#define NMEA_GPGGA_POSITION_FIX         6
#define NMEA_GPGGA_N_SATELLITES         7
#define NMEA_GPGGA_HORIZ_DILUTION       8
#define NMEA_GPGGA_ALTITUDE             9
#define NMEA_GPGGA_ALTITUDE_UNIT        10
#define NMEA_GPGGA_UNDULATION           11
#define NMEA_GPGGA_UNDULATION_UNIT      12

// parsování věty $GNGGA
GNGGA nmea_gngga( char *data, int len )
{
GNGGA result = {0.0, 0, 0, 0, 0, 0.0, ' ', 0.0, ' ', 0, 0, 0.0, 0.0, ' ', 0.0, ' ', '\0', false, 0};    
int section = 0;
char *str1;
char *saveptr1;
char *token;
char *buf[10];

    for(section=0, str1 = data ; section<=13; section++, str1=NULL) {
        token = strtok_r(str1,",*",&saveptr1);
        if( token == NULL ) {
            break;
            }
        switch ( section ) {
            case 0: // nazev
                if( strcmp(token,"$GNGGA") == 0 ) { result.parse_ok=1; }
                break;
            case NMEA_GPGGA_TIME: // cas
                result.time  = strtod(token, NULL);
                result.time_hour = ((int)result.time)/10000;
                result.time_min  = ((int)result.time - (result.time_hour*10000))/100;
                result.time_sec  = ((int)result.time - (result.time_hour*10000) - (result.time_min*100));
                result.time_msec = (result.time - result.time_hour*10000.0 - result.time_min*100.0 - result.time_sec)*1000;  
                result.parse_ok++;
                break;
            case NMEA_GPGGA_LATITUDE: // zeměpisná šířka ve stupních
                result.latitude = strtod(token,NULL)/100.0;
                result.latitude_degree  = atoi(token)/100;
                result.latitude_minutes = (atoi(token) - result.latitude_degree*100)*6/10; 
                result.latitude_vteriny = (result.latitude - result.latitude_degree*1.0 - result.latitude_minutes*6.0/10.0)*6.0/10.0;
                if( result.latitude_vteriny < 0.0) { result.latitude_minutes += 1; result.latitude_vteriny += 60.0; }
                result.parse_ok++;
                break;
            case NMEA_GPGGA_LATITUDE_CARDINAL: // severní N nebo jižní S
                result.latitude_ch = token[0];
                result.parse_ok++;
                break;
            case NMEA_GPGGA_LONGITUDE: // zeměpisná délka
                result.longitude = strtod(token,NULL)/100.0;
                result.longitude_degree  = atoi(token)/100;
                result.longitude_minutes = (atoi(token) - result.longitude_degree*100)*6/10;
                result.longitude_vteriny = (result.longitude - result.longitude_degree*1.0 - result.longitude_minutes*6.0/10.0)*6.0/10.0;
                if( result.longitude_vteriny < 0.0) { result.longitude_minutes += 1; result.longitude_vteriny += 60.0; }
                result.parse_ok++;
                break;
            case NMEA_GPGGA_LONGITUDE_CARDINAL: // západní W nebo východní E
                result.longitude_ch = token[0];
                result.parse_ok++;
                break;
            case NMEA_GPGGA_POSITION_FIX: // fixace
                result.fix = atoi(token);
                result.parse_ok++;
                break;
            case NMEA_GPGGA_N_SATELLITES: // počet satelitů
                result.satelites = atoi(token);
                result.parse_ok++;
                break;
            case NMEA_GPGGA_HORIZ_DILUTION: // plavání chyby
                result.horizontal_dilution = strtod(token,NULL);
            case NMEA_GPGGA_ALTITUDE: // výška nad mořem
                result.altitude = strtod(token,NULL);
                result.parse_ok++;
                break;
            case NMEA_GPGGA_ALTITUDE_UNIT: // jednotka nadmořské výšky
                result.altitude_unit = token[0];
                result.parse_ok++;
                break;
            case NMEA_GPGGA_UNDULATION: // výška nad ideálním WGS84 elipsoidem
                result.geoid_height = strtod(token,NULL);
                result.parse_ok++;
                break;
            case NMEA_GPGGA_UNDULATION_UNIT: // jednotka výšky nad WGS84 elipsoidem
                result.geoid_height_unit = token[0];
                result.parse_ok++;
                break;
            case 13: // checksum
                result.checksum = atoi(token);
                result.parse_ok++;
                break;
            default:
                result.parse_ok = -1;
                break;
        }
    }
return result;
}

typedef struct {
        double  latitude;
        char    latitude_ch;
        double  longitude;
        char    longitude_ch;
        char    valid;
        double  time;
        int     time_hour;
        int     time_min;
        int     time_sec;
        int     time_msec;
        int     parse_ok;
} GLL;
/* Indexy */
#define NMEA_GPGLL_LATITUDE             1
#define NMEA_GPGLL_LATITUDE_CARDINAL    2
#define NMEA_GPGLL_LONGITUDE            3
#define NMEA_GPGLL_LONGITUDE_CARDINAL   4
#define NMEA_GPGLL_TIME                 5
#define NMEA_GPGLL_VALID_DATA           6

GLL nmea_gpgll( char *data, int len )
{
GLL result = {0.0, ' ', 0.0, ' ', 'N', 0.0, 0, 0, 0 };
int section = 0;
char *str1;
char *saveptr1;
char *token;
//char buf[10];

    for(section=0, str1 = data ; section<=6; section++, str1=NULL) {
        token = strtok_r(str1,",*",&saveptr1);
        if( token == NULL ) {
            break;
            }
        switch ( section ) {
            case 0: // nazev
                if( strcmp(token,"$GPGLL") == 0 ) { result.parse_ok=1; }
                break;
            case NMEA_GPGLL_LATITUDE: // zeměpisná délka
                result.latitude = strtod(token,NULL)/100.0;
                result.parse_ok++;
                break;
            case NMEA_GPGLL_LATITUDE_CARDINAL: // N - severní, S - jižní
                result.latitude_ch = token[0];
                result.parse_ok++;
                break;
            case NMEA_GPGLL_LONGITUDE: // zeměpisná délka
                result.longitude = strtod(token,NULL)/100.0;
                result.parse_ok++;
                break;
            case NMEA_GPGLL_LONGITUDE_CARDINAL: // N - severní, S - jižní
                result.longitude_ch = token[0];
                result.parse_ok++;
                break;
            case NMEA_GPGLL_TIME: // toto je volitelné
                result.time = strtod(token,NULL);
                result.time_hour = ((int)result.time)/10000;
                result.time_min  = ((int)result.time - (result.time_hour*10000))/100;
                result.time_sec  = ((int)result.time - (result.time_hour*10000) - (result.time_min*100));
                result.time_msec = (result.time - result.time_hour*10000.0 - result.time_min*100.0 - result.time_sec)*1000;  
                result.parse_ok++;
                break;
            case NMEA_GPGLL_VALID_DATA: // A - data jsou platná
                result.valid = token[0];
                result.parse_ok++;
                break;
        }
                
    }
return result;
}
    
// porovná checksum NMEA věty
bool nmea_checksum(const char *data, int len )
{
uint8_t checksum = 0;
uint8_t checksum_calculated = 0;
     
    if(len < 7 ) return false; // příliš krátká věta
 //   printf("data[1] == '%c' data[len-5] == '%c'\n",data[1],data[len-5]);
    if(data[len-5] != '*') return false;
    if( ((data[len-4] >= '0' && data[len-4] <= '9') || (data[len-4] >= 'A' && data[len-4] <= 'F')) 
        && ((data[len-3] >= '0' && data[len-3] <= '9') || (data[len-3] >= 'A' && data[len-3] <= 'F')) ) {
         checksum = strtol(&data[len-4],NULL,16);
         checksum_calculated = (uint8_t) data[1];
         for( int i=2; i<len-5; i++) {
             checksum_calculated ^= (uint8_t) data[i];
         }
    }
   // printf("Porovnani: %c%c == %02x vypočtene: %02x \n", data[len-4], data[len-3], checksum, checksum_calculated);
return checksum == checksum_calculated ? true : false;
}

bool muj_checksum( char *data, int len )
{
uint8_t checksum_calculated = 0;
     
    if(len < 7 ) return false; // příliš krátká věta
    checksum_calculated = (uint8_t) data[1];
    for( int i=2; data[i] != '*' && i<len; i++) {
        checksum_calculated ^= (uint8_t) data[i];
        }
    sprintf(&data[len],"%02X\r\n",checksum_calculated);
   // printf("Checksum vypočteny: %02x \n", checksum_calculated);
return true;
}

int main( void )
{
bool led_stav = true;
bool chsum = false;
GNGGA gngga;
GLL gpgll;
char dbuf[BUFLEN];
int sat = 1;
int len = 0;
datetime_t current_time = {0,0,0,0,0,0,0};
char datetime_buf[256];
char *datetime_str = &datetime_buf[0];

    char data[BUFLEN];
    stdio_init_all();
    gpio_init( LED_PIN );
    gpio_set_function( LED_PIN, GPIO_FUNC_SIO );
    gpio_set_dir( LED_PIN, true );
    gpio_put(LED_PIN, led_stav);
    
    sleep_ms(1500);
#if VYVOJ
    printf("Testovani navigacniho modulu 5.\n");
#endif
    // inicializace LCD dipleje
    printf("LCD init.\n");
    init_gpio();
    lcd_characters_init();
    lcd_init();
    lcd_clear();
    printf("LCD OK.\n");
    
    // inicializace UART
    uart_init(UART_ID,2400);
    printf("UART init.\n");
    
    gpio_set_function( UART_TX_PIN, UART_FUNCSEL_NUM(UART_ID, UART_TX_PIN ));
    gpio_set_function( UART_RX_PIN, UART_FUNCSEL_NUM(UART_ID, UART_RX_PIN ));
    int actual = uart_set_baudrate(UART_ID, BAUD_RATE );
    uart_set_hw_flow( UART_ID, false, false );
    uart_set_fifo_enabled( UART_ID, true );
    printf("UART OK %d.\n", actual);
#if 0
    if( uart_is_readable_within_us(UART_ID,5000) == true ) {
        int i = 0;
        uint8_t ch;
        do {
            ch = uart_getc(UART_ID);
            data[i] = ch;
            if(i<BUFLEN-1) i++;
            else break;
            data[i] = '\0';
        } while ( ch != '\n' && uart_is_readable_within_us(UART_ID, 2000) ) ;
    }    
    // nastavíme co chceme prijímat
    char pcas_message[BUFLEN];
    strcpy(pcas_message,"$PCAS03,1,1,1,1,1,0,0,0,0,0,,,0,0*");
    len = strlen(pcas_message);
    muj_checksum(pcas_message,len);
    strcat(pcas_message,"\r\n");
    printf("%s resp: %s",pcas_message,data);
    uart_write_blocking(UART_ID,pcas_message,len);
    uart_tx_wait_blocking(UART_ID);
    // nastavíme GPS a GLONASS
    strcpy(pcas_message,"$PCAS04,4*");
    len = strlen(pcas_message);
    muj_checksum(pcas_message,len);
    strcat(pcas_message,"\r\n");
    printf("%s",pcas_message);
    uart_write_blocking(UART_ID,pcas_message,len);
    uart_tx_wait_blocking(UART_ID);
    
    // linka na 115200
    //
    // strcpy(pcas_message,"$PCAS01,5*");
    // len = strlen(pcas_message);
    // muj_checksum(pcas_message,len);
    // strcat(pcas_message,"\r\n");
    // printf("%s",pcas_message);
    // uart_write_blocking(UART_ID,pcas_message,len);
    // uart_tx_wait_blocking(UART_ID);
    strcpy(pcas_message,"$PQBAUD,W,115200*43\r\n");
    len = strlen(pcas_message);
//     muj_checksum(pcas_message,len);
    strcat(pcas_message,"\r\n");
    printf("Prikaz na zmenu rychlosti: %s",pcas_message);
    uart_write_blocking(UART_ID,pcas_message,len);
    uart_tx_wait_blocking(UART_ID);
//     
    // tohle nechce fungovat GRRR.
    actual = 115200;
    printf("Setting UART baudrate %d\n",actual);
    uart_write_blocking(UART_ID,"  \r\n",4);
    uart_tx_wait_blocking(UART_ID);
    if( uart_is_readable_within_us(UART_ID,5000) == true ) {
        int i = 0;
        uint8_t ch;
        do {
            ch = uart_getc(UART_ID);
            data[i] = ch;
            if(i<17) i++;
            else break;
            data[i] = '\0';
        } while ( ch != '\n' && uart_is_readable_within_us(UART_ID, 2000) ) ;
    }    
    data[18] = '\0';
    printf("Odpoved na zmenu rychlosti: %s\n",data);
    if( strcmp(data,"$PQBAUD,W,OK*40\r\n") == 0 ) {
        printf("Success 115200\n");
        actual = uart_set_baudrate(UART_ID, 115200);
    } else {
        printf("Return to 9600\n");
        actual = uart_set_baudrate(UART_ID, 9600);
        
    }
    sleep_ms(500);
    // // LCD
    lcd_home();
    lcd_set_cursor(0,0);
    cz_print(data);
    sleep_ms(2000);
#endif
    lcd_home();
    lcd_set_cursor(0,0);
    sat = 1;
    sprintf(dbuf,"Nastavuji čas. ");
    cz_print(dbuf);
    // synchronizace času
    rtc_init();
    memset(data,'\0',BUFLEN);
    while( current_time.year == 0 ) {
        if( uart_is_readable_within_us(UART_ID,5000) == true ) {
            int i = 0;
            uint8_t ch;
            do {
                ch = uart_getc(UART_ID);
                data[i] = ch;
                if(i<BUFLEN-1) i++;
                else break;
                data[i] = '\0';
            } while ( ch != '\n' && uart_is_readable_within_us(UART_ID, 2000) ) ;
            
            len = i;
            // $GNZDA -- checsum bude nekorektni
            
            if( len > 0 && data[0] == '$' && data[1] == 'G' && data[2] == 'N' && data[3] == 'Z' && data[4] == 'D' && data[5] == 'A' ) {
                printf("Nastavení času GNZDA: len=%3d; data='%s' \n",len,data );
                GNZDA gnzda = nmea_gnzda(data,len);
                if( gnzda.parse_ok == 6 ) {
                    current_time.year  = gnzda.year;
                    current_time.month = gnzda.month;
                    current_time.day   = gnzda.day;
                    current_time.dotw  = gnzda.dotw;
                    current_time.hour  = gnzda.hour;
                    current_time.min   = gnzda.min;
                    current_time.sec   = gnzda.sec;
                    rtc_set_datetime(&current_time);
                } else {
                    printf("parse_ok == %d\n", gnzda.parse_ok);
                }
                
            } 
            if(len > 0 && data[0] == '$' && data[1] == 'G' && data[2] == 'N'  && data[3] == 'G' && data[4] == 'G' && data[5] == 'A' && nmea_checksum(data,len) ) {
                printf("Global GNSS location data ----- len= %d; data ='%s'\n",len,data);
                gngga = nmea_gngga(data,len);
                if( gngga.parse_ok == 14 ) {
                    lcd_home();
                    lcd_set_cursor(0,0);
                    sprintf(dbuf,"%c%f\xb0%02d:%02d",gngga.latitude_ch, gngga.latitude, gngga.time_hour, gngga.time_min);
                    cz_print(dbuf);
                    lcd_set_cursor(1,0);
                    sprintf(dbuf,"%c%f\xb0%02d|%02d",gngga.longitude_ch, gngga.longitude, gngga.time_sec, gngga.satelites);
                    cz_print(dbuf);
                } 
            }
        }
        sleep_ms(50);
    }
    

    while( true ) {
        memset(data,'\0',BUFLEN);
            
        if( uart_is_readable_within_us(UART_ID,5000) == true ) {
            int i = 0;
            uint8_t ch;
            do {
                ch = uart_getc(UART_ID);
                data[i] = ch;
                if(i<BUFLEN-1) i++;
                else break;
                data[i] = '\0';
            } while ( ch != '\n' && uart_is_readable_within_us(UART_ID, 2000) ) ;
            
            len = i;
            chsum = nmea_checksum(data,len);

            // if( !chsum ) printf("len=%3d; data='%s' checksum=%s\n",len,data, chsum==false ? "false" : "true" );

            lcd_set_cursor(0,15);
            // switch (sat) {
            //     case 1: sprintf(dbuf,"|");  sat++; break;
            //     case 2: sprintf(dbuf,"/");  sat++; break;
            //     case 3: sprintf(dbuf,"-");  sat++; break;
            //     case 4: sprintf(dbuf,"\\"); sat++; break;
            //     case 5: sprintf(dbuf,"|");  sat++; break;
            //     case 6: sprintf(dbuf,"/");  sat++; break;
            //     case 7: sprintf(dbuf,"-");  sat++; break;
            //     case 8: sprintf(dbuf,"\\"); sat=1; break;
            // }
            // cz_print(dbuf);
            
            // $GNGGA Global GNSS location data
                  
            if(len > 0 && data[0] == '$' && data[1] == 'G' && data[2] == 'N'  && data[3] == 'G' && data[4] == 'G' && data[5] == 'A' && chsum == true) {
                //printf("Global GNSS location data ----- len= %d; data ='%s'\n",len,data);
                gngga = nmea_gngga(data,len);
                if( gngga.parse_ok == 14 ) {

                    printf("Světový čas (UTC): %02d:%02d:%02d\n", gngga.time_hour, gngga.time_min, gngga.time_sec);
                    printf("Zeměpisné souřadnice: šířka %f %c, délka %f %c\n", gngga.latitude, gngga.latitude_ch, gngga.longitude, gngga.longitude_ch);  
                    // printf("Zeměpisné souřadnice: šířka %2d˚ %2d' %4.1f\" %c,  délka %2d˚ %2d' %4.1f\" %c\n", 
                    //        (int) gngga.latitude_degree, (int) gngga.latitude_minutes, gngga.latitude_minutes, gngga.latitude_vteriny, gngga.latitude_ch, 
                    //        (int) gngga.longitude_degree, (int) gngga.longitude_minutes, gngga.longitude_vteriny, gngga.longitude_ch);  
                    printf("Nadmořská výška: %5.1f %c nad mořem\n", gngga.altitude, gngga.altitude_unit);
                    printf("Počet viditelných satelitů: %d\n", gngga.satelites);
                    printf("Počet položek věty $GNGGA: %d fix %d chksum %s\n", gngga.parse_ok, gngga.fix, chsum==true?"OK":"ER");
                    
                    lcd_home();
                    lcd_set_cursor(0,0);
                    sprintf(dbuf,"%c%f\xb0%02d:%02d",gngga.latitude_ch, gngga.latitude, gngga.time_hour, gngga.time_min);
                    cz_print(dbuf);
                    lcd_set_cursor(1,0);
                    sprintf(dbuf,"%c%f\xb0%02d|%02d",gngga.longitude_ch, gngga.longitude, gngga.time_sec, gngga.satelites);
                    cz_print(dbuf);
                } else {
#if VYVOJ
                    printf("Chyba parsování věty $GNGGA %d\n", gngga.parse_ok);
                    lcd_set_cursor(1,15);
                    sprintf(dbuf,"%c",'O');
                    cz_print(dbuf);
#endif
                }
            }
            // GPGLL -- zeměpisná šířka a délka
            if(len > 0 && data[0] == '$' && data[1] == 'G' && data[2] == 'P'  && data[3] == 'G' && data[4] == 'L' && data[5] == 'L') {
#if VYVOJ
                printf("Global GLL location data ----- len= %d; data ='%s'\n",len,data);
#endif
                gpgll = nmea_gpgll(data,len);
                if( gpgll.parse_ok == 5 ) {
#if VYVOJ
                    printf("Zeměpisné souřadnice: šířka %f %c, délka %f %c\n", gpgll.latitude, gpgll.latitude_ch, gpgll.longitude, gpgll.longitude_ch);  
                    printf("Počet položek věty $GPGLL: %d chksum %s\n", gpgll.parse_ok, chsum==true?"OK":"ER");
#endif
                    lcd_home();
                    lcd_set_cursor(0,0);
                    sprintf(dbuf,"%c%f\xb0",gpgll.latitude_ch, gpgll.latitude);
                    cz_print(dbuf);
                    lcd_set_cursor(1,0);
                    sprintf(dbuf,"%c%f\xb0",gpgll.longitude_ch, gpgll.longitude );
                    cz_print(dbuf);
                } else if(gpgll.parse_ok == 7) {
#if VYVOJ
                    printf("Zeměpisné souřadnice: šířka %f %c, délka %f %c\n", gpgll.latitude, gpgll.latitude_ch, gpgll.longitude, gpgll.longitude_ch);  
                    printf("Čas: %02d:%02d:%02d\n",gpgll.time_hour, gpgll.time_min, gpgll.time_sec);
                    printf("Počet položek věty $GPGLL: %d chksum %s\n", gpgll.parse_ok, chsum==true?"OK":"ER");
#endif
                    lcd_home();
                    lcd_set_cursor(0,0);
                    sprintf(dbuf,"%c%f",gpgll.latitude_ch, gpgll.latitude);
                    cz_print(dbuf);
                    lcd_set_cursor(1,0);
                    sprintf(dbuf,"%c%f",gpgll.longitude_ch, gpgll.longitude);
                    cz_print(dbuf);
                }
                else {
#if VYVOJ
                    printf("Chyba parsování věty $GPGLL %d\n", gngga.parse_ok);
#endif
                    lcd_set_cursor(1,15);
                    sprintf(dbuf,"%c",'e');
                    cz_print(dbuf);
                }
            }
            rtc_get_datetime(&current_time);
            datetime_to_str(datetime_str, sizeof(datetime_buf), &current_time);
            printf("\r%s      ", datetime_str);
            lcd_set_cursor(1,11);
            sprintf(dbuf,"%02d",current_time.sec);
            cz_print(dbuf);
        }
        led_stav = led_stav ? false : true;
        gpio_put( LED_PIN, led_stav );
        sleep_ms(80);
    }
}
// -------------------------------------------------------------------------------------------------
CMakeLists.txt
cmake_minimum_required(VERSION 3.12)

include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)

project(navigace5 C CXX ASM)

pico_sdk_init()

# pridani zdrojovych kodu
add_executable(navigace5
    navigace5.c
    lcd_czech_chars.c

)

# enable usb output, disable uart output
pico_enable_stdio_usb(navigace5 1)
pico_enable_stdio_uart(navigace5 0)

# create map/bin/hex/uf2 file etc.
pico_add_extra_outputs(navigace5)

target_link_libraries(navigace5 pico_stdlib hardware_uart hardware_i2c hardware_rtc)

Konfigurace displeje se provádí v hlavičkovém souboru lcd_czech_chars.h

#define DISPLAY_SDA 6
#define DISPLAY_SCL 7
#define I2C         i2c1

Použití displeje:

#include "lcd_czech_chars.h"
#define BUFLEN 128

// na začátku ve funkci main()
    init_gpio(); // nastavení pinů a I2C
    lcd_characters_init(); // nastavení českých znaků
    lcd_init(); // inicializace displeje
    lcd_clear(); // výmaz displeje

// kdekoliv v programu
char dbuf[BUFLEN];

    lcd_home(); // nastavení displeje do domáci pozice
    lcd_set_cursor(1,0); // nastavení kurzoru na 1. řádek a 0. sloupec
    sprintf(dbuf,"Hledam satelity"); // do bufferu si dám, co chci
    cz_print(dbuf); // zobrazení na displeji
lcd_czech_chars.h
/** lcd_czech_char.h version 1.01

 * Copyright (c) 2024 Jirka Chráska <jirka@lixis.cz> All rigths reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are
 * permitted provided that the following conditions are met:

 * 1. Redistributions of source code must retain the above copyright notice, this list of
 *    conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice, this
 *    list of conditions and the following disclaimer in the documentation and/or
 *    other materials provided with the distribution.
 * 3. Neither the name of the copyright holder nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#define DISPLAY_SDA 6
#define DISPLAY_SCL 7
#define I2C         i2c1

// inicializace GPIO
int init_gpio();

// inicializace displeje
void lcd_init();

// go to location on LCD
void lcd_set_cursor(int line, int position);


// inicializace českých znaků
void lcd_characters_init();

// tisk znakù na LCD displej
int cz_print(const char *str);

// šoupání s displejem
void twist(int chars, int pause, int repeat);

// výmaz dipleje
void lcd_clear(void);

// na první pozici
void lcd_home(void);
lcd_czech_chars.c
/** lcd_czech_chars.c version 1.01
 *
 * Copyright (c) 2024 Jirka Chráska <jirka@lixis.cz> All rigths reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are
 * permitted provided that the following conditions are met:

 * 1. Redistributions of source code must retain the above copyright notice, this list of
 *    conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice, this
 *    list of conditions and the following disclaimer in the documentation and/or
 *    other materials provided with the distribution.
 * 3. Neither the name of the copyright holder nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Český překlad
 * Copyright (c) 2024 Jirka Chráska <jirka@lixis.cz>. Všechna práva vyhrazena.
 *
 * Redistribuce a použití zdrojových i binárních forem díla, v původním i upravovaném tvaru, jsou
 * povoleny za následujících podmínek:
 *
 * 1. Šířený zdrojový kód musí obsahovat výše uvedenou informaci o copyrightu, tento seznam
 *    podmínek a níže uvedené zřeknutí se odpovědnosti.
 * 2. Šířený binární tvar musí nést výše uvedenou informaci o copyrightu, tento seznam
 *    podmínek a níže uvedené zřeknutí se odpovědnosti ve své dokumentaci a/nebo dalších
 *    poskytovaných materiálech.
 * 3. Ani jméno vlastníka práv, ani jména přispěvatelů nemohou být použita při podpoře nebo
 *    právních aktech souvisejících s produkty odvozenými z tohoto softwaru bez výslovného
 *    písemného povolení.
 *
 * TENTO SOFTWARE JE POSKYTOVÁN DRŽITELEM LICENCE A JEHO PŘISPĚVATELI "JAK STOJÍ A LEŽÍ" A JAKÉKOLIV
 * VÝSLOVNÉ NEBO PŘEDPOKLÁDANÉ ZÁRUKY VČETNĚ, ALE NEJEN, PŘEDPOKLÁDANÝCH OBCHODNÍCH ZÁRUK A ZÁRUKY
 * VHODNOSTI PRO JAKÝKOLIV ÚČEL JSOU POPŘENY. DRŽITEL, ANI PŘISPĚVATELÉ NEBUDOU V ŽÁDNÉM PŘÍPADĚ
 * ODPOVĚDNI ZA JAKÉKOLIV PŘÍMÉ, NEPŘÍMÉ, NÁHODNÉ, ZVLÁŠTNÍ, PŘÍKLADNÉ NEBO VYPLÝVAJÍCÍ ŠKODY
 * (VČETNĚ, ALE NEJEN, ŠKOD VZNIKLÝCH NARUŠENÍM DODÁVEK ZBOŽÍ NEBO SLUŽEB; ZTRÁTOU POUŽITELNOSTI,
 * DAT NEBO ZISKŮ; NEBO PŘERUŠENÍM OBCHODNÍ ČINNOSTI) JAKKOLIV ZPŮSOBENÉ NA ZÁKLADĚ JAKÉKOLIV TEORIE
 * O ZODPOVĚDNOSTI, AŤ UŽ PLYNOUCÍ Z JINÉHO SMLUVNÍHO VZTAHU, URČITÉ ZODPOVĚDNOSTI NEBO PŘEČINU
 * (VČETNĚ NEDBALOSTI) NA JAKÉMKOLIV ZPŮSOBU POUŽITÍ TOHOTO SOFTWARE, I V PŘÍPADĚ, ŽE DRŽITEL PRÁV
 * BYL UPOZORNĚN NA MOŽNOST TAKOVÝCH ŠKOD.
 */

#include <stdio.h>
#include <string.h>
#include "pico/stdlib.h"
#include "hardware/i2c.h"
#include "pico/binary_info.h"
#include "lcd_czech_chars.h"

// commands
const int LCD_CLEARDISPLAY 	        = 0x01;
const int LCD_RETURNHOME 	        = 0x02;
const int LCD_ENTRYMODESET 	        = 0x04;
const int LCD_DISPLAYCONTROL 	    = 0x08;
const int LCD_CURSORSHIFT 	        = 0x10;
const int LCD_FUNCTIONSET 	        = 0x20;
const int LCD_SETCGRAMADDR 	        = 0x40;
const int LCD_SETDDRAMADDR 	        = 0x80;

// flags for display entry mode
const int LCD_ENTRYSHIFTINCREMENT   = 0x01;
const int LCD_ENTRYLEFT 	        = 0x02;

// flags for display and cursor control
const int LCD_BLINKON 		        = 0x01;
const int LCD_CURSORON 		        = 0x02;
const int LCD_DISPLAYON 	        = 0x04;

// flags for display and cursor shift
const int LCD_MOVERIGHT 	        = 0x04;
const int LCD_DISPLAYMOVE 	        = 0x08;

// flags for function set
const int LCD_5x10DOTS 		        = 0x04;
const int LCD_2LINE 		        = 0x08;
const int LCD_8BITMODE 		        = 0x10;

// flag for backlight control
const int LCD_BACKLIGHT             = 0x08;

const int LCD_ENABLE_BIT            = 0x04;

// By default these LCD display drivers are on bus address 0x27
static int addr = 0x27;

// Modes for lcd_send_byte
#define LCD_CHARACTER  1
#define LCD_COMMAND    0

#define MAX_LINES      2
#define MAX_CHARS      16


// czech characters ISO-8859-2
const unsigned char znak_a_acute  =  '\xE1';    // á
const unsigned char znak_A_acute  =  '\xC1';    // Á
const unsigned char znak_c_caron  =  '\xE8';    // č
const unsigned char znak_C_caron  =  '\xC8';    // Č
const unsigned char znak_d_caron  =  '\xEF';    // ď
const unsigned char znak_D_caron  =  '\xCF';    // Ď
const unsigned char znak_e_acute  =  '\xE9';    // é
const unsigned char znak_E_acute  =  '\xC9';    // É
const unsigned char znak_e_caron  =  '\xEC';    // ě
const unsigned char znak_E_caron  =  '\xCC';    // Ě
const unsigned char znak_i_acute  =  '\xED';    // í
const unsigned char znak_I_acute  =  '\xCD';    // Í
const unsigned char znak_n_caron  =  '\xF2';    // ň
const unsigned char znak_N_caron  =  '\xD2';    // Ň
const unsigned char znak_o_acute  =  '\xF3';    // ó
const unsigned char znak_O_acute  =  '\xD3';    // Ó
const unsigned char znak_r_caron  =  '\xF8';    // ř
const unsigned char znak_R_caron  =  '\xD8';    // Ř
const unsigned char znak_s_caron  =  '\xB9';    // š
const unsigned char znak_S_caron  =  '\xA9';    // Š
const unsigned char znak_t_caron  =  '\xBB';    // ť
const unsigned char znak_T_caron  =  '\xAB';    // Ť
const unsigned char znak_u_acute  =  '\xFA';    // ú
const unsigned char znak_U_acute  =  '\xDA';    // Ú
const unsigned char znak_u_ogonek =  '\xF9';    // ů
const unsigned char znak_U_ogonek =  '\xD9';    // Ů
const unsigned char znak_y_acute  =  '\xFD';    // ý
const unsigned char znak_Y_acute  =  '\xDD';    // Ý
const unsigned char znak_z_caron  =  '\xBE';    // ž
const unsigned char znak_Z_caron  =  '\xAE';    // Ž
const unsigned char degree_symbol =  '\xB0';    // °

// Custom characters
static unsigned char c_char[256];
static unsigned char cz_char[8]; // custom chars definitions
static uint8_t volna_pozice = 0;
static uint8_t cursor_x         = 0;
static uint8_t cursor_y         = 0;
static uint8_t num_columns      = 40;
static uint8_t num_lines        = 2;

typedef struct cchar {
    unsigned char znak;
    char map[8];
    char location;
} CZCHAR;

#define pismenek    31
static CZCHAR czech_chars[pismenek] = {
{
    znak_a_acute, // 1
    {
    0b00000010,
    0b00000100,
    0b00001110,
    0b00000001,
    0b00001111,
    0b00010001,
    0b00001111,
    0b00000000
    },
    0
},
{
    znak_A_acute, // 2
    {
    0b00000010,
    0b00000100,
    0b00001010,
    0b00010001,
    0b00011111,
    0b00010001,
    0b00010001,
    0b00000000
    },
    0
},
{
    znak_c_caron, // 3
    {
    0b00001010,
    0b00000100,
    0b00001110,
    0b00010001,
    0b00010000,
    0b00010001,
    0b00001110,
    0b00000000
    },
    0
},
{
    znak_C_caron, // 4
    {
    0b00001010,
    0b00001110,
    0b00010001,
    0b00010000,
    0b00010000,
    0b00010001,
    0b00001110,
    0b00000000
    },
    0
},
{
    znak_d_caron, // 5
    {
    0b00010101,
    0b00001001,
    0b00001101,
    0b00010011,
    0b00010001,
    0b00010001,
    0b00001110,
    0b00000000
    },
    0
},
{
    znak_D_caron, // 6
    {
    0b00011101,
    0b00010010,
    0b00010001,
    0b00010001,
    0b00010001,
    0b00010010,
    0b00011100,
    0b00000000
    },
    0
},
{
    znak_e_acute, // 7
    {
    0b00000010,
    0b00000100,
    0b00001110,
    0b00010001,
    0b00011111,
    0b00010000,
    0b00001110,
    0b00000000
    },
    0
},
{
    znak_E_acute, // 8
    {
    0b00000010,
    0b00000100,
    0b00011111,
    0b00010000,
    0b00011111,
    0b00010000,
    0b00011111,
    0b00000000
    },
    0
},
{
    znak_e_caron, // 9
    {
    0b00001010,
    0b00000100,
    0b00001110,
    0b00010001,
    0b00011111,
    0b00010000,
    0b00001110,
    0b00000000
    },
    0
},
{
    znak_E_caron, // 10
    {
    0b00001010,
    0b00000100,
    0b00011111,
    0b00010000,
    0b00011111,
    0b00010000,
    0b00011111,
    0b00000000
    },
    0
},
{
    znak_i_acute, // 11
    {
    0b00000010,
    0b00000100,
    0b00000000,
    0b00001100,
    0b00000100,
    0b00000100,
    0b00001110,
    0b00000000
    },
    0
},
{
    znak_I_acute, // 12
    {
    0b00000010,
    0b00000101,
    0b00000000,
    0b00001110,
    0b00000100,
    0b00000100,
    0b00001110,
    0b00000000
    },
    0
},
{
    znak_n_caron, // 13
    {
    0b00001010,
    0b00000100,
    0b00010110,
    0b00011101,
    0b00010001,
    0b00010001,
    0b00010001,
    0b00000000
    },
    0
},
{
    znak_N_caron, // 14
    {
    0b00001010,
    0b00000100,
    0b00010001,
    0b00011001,
    0b00010101,
    0b00010011,
    0b00010001,
    0b00000000
    },
    0
},
{
    znak_o_acute, // 15
    {
    0b00000010,
    0b00000100,
    0b00001110,
    0b00010001,
    0b00010001,
    0b00010001,
    0b00001110,
    0b00000000
    },
    0
},
{
    znak_O_acute, // 16
    {
    0b00000001,
    0b00001110,
    0b00010001,
    0b00010001,
    0b00010001,
    0b00010001,
    0b00001110,
    0b00000000
    },
    0
},
{
    znak_r_caron, // 17
    {
    0b00001010,
    0b00000100,
    0b00010110,
    0b00011001,
    0b00010000,
    0b00010000,
    0b00010000,
    0b00000000
    },
    0
},
{
    znak_R_caron, // 18
    {
    0b00001010,
    0b00011110,
    0b00010001,
    0b00010001,
    0b00011110,
    0b00010010,
    0b00010001,
    0b00000000
    },
    0
},
{
    znak_s_caron, // 19
    {
    0b00001010,
    0b00000100,
    0b00001111,
    0b00010000,
    0b00001110,
    0b00000001,
    0b00011110,
    0b00000000
    },
    0
},
{
    znak_S_caron, // 20
    {
    0b00001010,
    0b00001111,
    0b00010000,
    0b00010000,
    0b00001110,
    0b00000001,
    0b00011110,
    0b00000000
    },
    0
},
{
    znak_t_caron, // 21
    {
    0b00001101,
    0b00001010,
    0b00011100,
    0b00001000,
    0b00001000,
    0b00001001,
    0b00000110,
    0b00000000
    },
    0
},
{
    znak_T_caron, // 22
    {
    0b00001010,
    0b00011111,
    0b00000100,
    0b00000100,
    0b00000100,
    0b00000100,
    0b00000100,
    0b00000000
    },
    0
},
{
    znak_u_acute, // 23
    {
    0b00000010,
    0b00000100,
    0b00010001,
    0b00010001,
    0b00010001,
    0b00010011,
    0b00001101,
    0b00000000
    },
    0
},
{
    znak_U_acute, // 24
    {
    0b00000010,
    0b00010101,
    0b00010001,
    0b00010001,
    0b00010001,
    0b00010001,
    0b00001110,
    0b00000000
    },
    0
},
{
    znak_u_ogonek, // 25
    {
    0b00000100,
    0b00001010,
    0b00010101,
    0b00010001,
    0b00010001,
    0b00010011,
    0b00001101,
    0b00000000
    },
    0
},
{
    znak_U_ogonek, // 26
    {
    0b00000100,
    0b00001010,
    0b00010101,
    0b00010001,
    0b00010001,
    0b00010001,
    0b00001110,
    0b00000000
    },
    0
},
{
    znak_y_acute, // 27
    {
    0b00000010,
    0b00000100,
    0b00010001,
    0b00010001,
    0b00001111,
    0b00000001,
    0b00001110,
    0b00000000
    },
    0
},
{
    znak_Y_acute, // 28
    {
    0b00000010,
    0b00010101,
    0b00010001,
    0b00001010,
    0b00000100,
    0b00000100,
    0b00001110,
    0b00000000
    },
    0
},
{
    znak_z_caron, // 29
    {
    0b00001010,
    0b00000100,
    0b00011111,
    0b00000010,
    0b00000100,
    0b00001000,
    0b00011111,
    0b00000000
    },
    0
},
{
    znak_Z_caron, // 30
    {
    0b00001010,
    0b00010101,
    0b00000001,
    0b00000010,
    0b00000100,
    0b00001000,
    0b00011111,
    0b00000000
    },
    0
},
{
    degree_symbol, // 31
    {
    0b00000110,
    0b00001001,
    0b00000110,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000
    },
    0
}
};

/* Quick helper function for single byte transfers */
void i2c_write_byte(uint8_t val)
{
    i2c_write_blocking(I2C, addr, &val, 1, false);
}

/* Quick helper function for single byte transfers */
uint8_t i2c_read_byte()
{
uint8_t val = 0;
    i2c_read_blocking(I2C, addr, &val, 1, false);
return val;
}

void lcd_toggle_enable(uint8_t val)
{
// Toggle enable pin on LCD display
// We cannot do this too quickly or things don't work
#define DELAY_US 600
    sleep_us(DELAY_US);
    i2c_write_byte(val | LCD_ENABLE_BIT);
    sleep_us(DELAY_US);
    i2c_write_byte(val & ~LCD_ENABLE_BIT);
    sleep_us(DELAY_US);
}

// The display is sent a byte as two separate nibble transfers
void lcd_send_byte(uint8_t val, int mode)
{
    uint8_t high = mode | (val & 0xF0) | LCD_BACKLIGHT;
    uint8_t low  = mode | ((val << 4) & 0xF0) | LCD_BACKLIGHT;

    i2c_write_byte(high);
    lcd_toggle_enable(high);
    i2c_write_byte(low);
    lcd_toggle_enable(low);
}

// vymaže display včetně na definovaných znaků
void lcd_clear(void)
{
    lcd_send_byte(LCD_CLEARDISPLAY, LCD_COMMAND);

    for(int i=0; i<8; i++) {
        cz_char[i] = '\x00';
    }
    volna_pozice = 0;
}

void lcd_home(void)
{
    lcd_send_byte(LCD_RETURNHOME, LCD_COMMAND);
    cursor_x = 0;
    cursor_y = 0;
}

void lcd_move_left(void) // pohyb doleva
{
    lcd_send_byte(LCD_CURSORSHIFT|LCD_DISPLAYMOVE, LCD_COMMAND);
//    printf("lcd_move_left ");
}
void lcd_move_right(void) // pohyb doprava
{
    lcd_send_byte(LCD_CURSORSHIFT|LCD_DISPLAYMOVE|LCD_MOVERIGHT, LCD_COMMAND);
//    printf("lcd_move_right ");
}

// go to location on LCD
void lcd_set_cursor(int line, int position)
{
    int val = (line == 0) ? 0x80 + position : 0xC0 + position;
    cursor_x = position;
    cursor_y = line;
    lcd_send_byte(val, LCD_COMMAND);
}

static void inline lcd_char(char val)
{
    lcd_send_byte(val, LCD_CHARACTER);
    cursor_x += 1;
    if(cursor_x >= num_columns) {
        cursor_x  = 0;
        cursor_y += 1;
    }
    if(cursor_y >= num_lines) {
        cursor_y = 0;
    }
//    printf("x=%d,y=%d ",cursor_x,cursor_y);
}

void lcd_string(const char *s)
{
    while (*s) {
        lcd_char(*s++);
    }
}

// inicializace displeje
void lcd_init()
{
    lcd_send_byte(0x03, LCD_COMMAND);
    lcd_send_byte(0x03, LCD_COMMAND);
    lcd_send_byte(0x03, LCD_COMMAND);
    lcd_send_byte(0x02, LCD_COMMAND);

    lcd_send_byte(LCD_ENTRYMODESET   | LCD_ENTRYLEFT, LCD_COMMAND);
    lcd_send_byte(LCD_FUNCTIONSET    | LCD_2LINE,     LCD_COMMAND);
    lcd_send_byte(LCD_DISPLAYCONTROL | LCD_DISPLAYON, LCD_COMMAND);
    lcd_clear();
}

// custom character definition
void lcd_create_custom_char(uint8_t location, const char map[] )
{
    location = location << 3;
//    printf("location=%x ", LCD_SETCGRAMADDR | location);
    lcd_send_byte(LCD_SETCGRAMADDR | location, LCD_COMMAND);
    for(int i=0; i<8; i++) {
	    lcd_send_byte(map[i],LCD_CHARACTER);
	    sleep_us(40);
	    }
    uint8_t adr = (cursor_y == 0) ? 0x80 + cursor_x : 0xC0 + cursor_x;
    lcd_send_byte(LCD_SETDDRAMADDR | adr, LCD_COMMAND);
}

void lcd_characters_init()
{
    for(int i=0; i<256; i++) {
        if(i <  0x20)               c_char[i] = '\x20';
        if(i >= 0x20 && i< 0x80)    c_char[i] = (unsigned char) i;
        if(i >= 0x80)               c_char[i] = '\x80';
    }

    for(int i=0; i<8; i++) {
        cz_char[i] = '\x00';
    }
    volna_pozice = 0;

    c_char[znak_a_acute]  = '\xFF';
    c_char[znak_A_acute]  = '\xFF';
    c_char[znak_c_caron]  = '\xFF';
    c_char[znak_C_caron]  = '\xFF';
    c_char[znak_d_caron]  = '\xFF';
    c_char[znak_D_caron]  = '\xFF';
    c_char[znak_e_acute]  = '\xFF';
    c_char[znak_E_acute]  = '\xFF';
    c_char[znak_e_caron]  = '\xFF';
    c_char[znak_E_caron]  = '\xFF';
    c_char[znak_i_acute]  = '\xFF';
    c_char[znak_I_acute]  = '\xFF';
    c_char[znak_n_caron]  = '\xFF';
    c_char[znak_N_caron]  = '\xFF';
    c_char[znak_o_acute]  = '\xFF';
    c_char[znak_O_acute]  = '\xFF';
    c_char[znak_r_caron]  = '\xFF';
    c_char[znak_R_caron]  = '\xFF';
    c_char[znak_s_caron]  = '\xFF';
    c_char[znak_S_caron]  = '\xFF';
    c_char[znak_t_caron]  = '\xFF';
    c_char[znak_T_caron]  = '\xFF';
    c_char[znak_u_acute]  = '\xFF';
    c_char[znak_U_acute]  = '\xFF';
    c_char[znak_u_ogonek] = '\xFF';
    c_char[znak_U_ogonek] = '\xFF';
    c_char[znak_y_acute]  = '\xFF';
    c_char[znak_Y_acute]  = '\xFF';
    c_char[znak_z_caron]  = '\xFF';
    c_char[znak_Z_caron]  = '\xFF';
    c_char[degree_symbol] = '\xFF';

}


// tisk znaků na LCD displej
int cz_print(const char *str)
{
char c;
uint8_t nadefinovano = 8;
    while(*str) {
        c = *str;
//        printf("c=%c,'0x%x' ",c,c);
        nadefinovano = 8;
        if(c > '\x7F' && c < '\xFF' && c_char[c] == '\xFF') { // musíme použít custom znak:  podíváme, zda už ho máme nadefinovaný anebo ho budeme definovat
            for(unsigned int k = 0; k<8; k++) {
                if(cz_char[k] == c) { // máme nadefinováno
                    nadefinovano = k;
                }
            }
            if(nadefinovano == 8) { // nemáme nadefinováno
                // vyhledame volnou pozici k definici
                if(volna_pozice > 7) {
                    volna_pozice = 0;
                }
                for(unsigned int j=0; j < pismenek; j++) { // vyhledame definici
                    if(czech_chars[j].znak == c) { // definice noveho znaku
                        lcd_create_custom_char(volna_pozice, czech_chars[j].map);
                        cz_char[volna_pozice] = c;
                        nadefinovano = volna_pozice;
                        volna_pozice++;
                    }
                }
            }
            // máme nadefinováno
            c = nadefinovano + 8;
        } // nemusíme použít custom znak
        lcd_char(c);
        str++;
    } // for str
}

// inicializace GPIO
int init_gpio()
{
    i2c_init(I2C, 400 * 1000);
    gpio_set_function(DISPLAY_SDA, GPIO_FUNC_I2C);
    gpio_set_function(DISPLAY_SCL, GPIO_FUNC_I2C);
    gpio_pull_up(DISPLAY_SCL);
    gpio_pull_up(DISPLAY_SDA);
}

void twist(int chars, int pause, int repeat)
{
int i=0;
while(repeat) {
    sleep_ms(pause*2);
    for(i=0; i<chars;i++) {
        lcd_move_left();
        sleep_ms(pause);
        }
    sleep_ms(pause*2);
    for(i=0; i<chars;i++) {
        lcd_move_right();
        sleep_ms(pause);
        }
    sleep_ms(pause*2);
    repeat--;
    }
}
Sestavení programu
cd navigace
mkdir build
cd build
cmake ..
make -j8

Spustitelný soubor pro nahrání na Pico (ano je to 5. pokus, přechozí nechtěly chodit). navigace5.uf2

Výstup z minicom -b 115200 -D /dev/ttyACM0
Světový čas (UTC): 21:26:59  212659.000000
Zeměpisné souřadnice: šířka 50.209310 N, délka 15.553547, E
Nadmořská výška: 263.2 M nad mořem
Počet viditelných satelitů: 14
Počet položek věty $GNGGA: 14 fix 1 chksum OK
Světový čas (UTC): 21:27:00  212700.000000
Zeměpisné souřadnice: šířka 50.209310 N, délka 15.553547, E
Nadmořská výška: 263.2 M nad mořem
Počet viditelných satelitů: 14
Počet položek věty $GNGGA: 14 fix 1 chksum OK
Světový čas (UTC): 21:27:01  212701.000000
Zeměpisné souřadnice: šířka 50.209310 N, délka 15.553546, E
Nadmořská výška: 263.3 M nad mořem
Počet viditelných satelitů: 14
Počet položek věty $GNGGA: 14 fix 1 chksum OK
Světový čas (UTC): 21:27:02  212702.000000
Zeměpisné souřadnice: šířka 50.209310 N, délka 15.553546, E
Nadmořská výška: 263.3 M nad mořem
Počet viditelných satelitů: 14
Počet položek věty $GNGGA: 14 fix 1 chksum OK
Světový čas (UTC): 21:27:03  212703.000000
Zeměpisné souřadnice: šířka 50.209309 N, délka 15.553546, E
Nadmořská výška: 263.4 M nad mořem
Počet viditelných satelitů: 14
Počet položek věty $GNGGA: 14 fix 1 chksum OK
Světový čas (UTC): 21:27:04  212704.000000
Zeměpisné souřadnice: šířka 50.209309 N, délka 15.553546, E
Nadmořská výška: 263.4 M nad mořem
Počet viditelných satelitů: 14
Počet položek věty $GNGGA: 14 fix 1 chksum OK
Světový čas (UTC): 21:27:05  212705.000000
Zeměpisné souřadnice: šířka 50.209309 N, délka 15.553545, E
Nadmořská výška: 263.5 M nad mořem
Počet viditelných satelitů: 14
Počet položek věty $GNGGA: 14 fix 1 chksum OK
Světový čas (UTC): 21:27:06  212706.000000
Zeměpisné souřadnice: šířka 50.209309 N, délka 15.553545, E
Nadmořská výška: 263.6 M nad mořem
Počet viditelných satelitů: 14
Počet položek věty $GNGGA: 14 fix 1 chksum OK
Světový čas (UTC): 21:27:07  212707.000000
Zeměpisné souřadnice: šířka 50.209309 N, délka 15.553545, E
Nadmořská výška: 263.6 M nad mořem
Počet viditelných satelitů: 14
Počet položek věty $GNGGA: 14 fix 1 chksum OK
Světový čas (UTC): 21:27:08  212708.000000
Zeměpisné souřadnice: šířka 50.209308 N, délka 15.553544, E
Nadmořská výška: 263.6 M nad mořem
Počet viditelných satelitů: 14
Počet položek věty $GNGGA: 14 fix 1 chksum OK
Chyba parsování věty $GNGGA 13
location_formatting (str): Style For Presenting Longitude/Latitude:
                                   Decimal Degree Minute (ddm) - 40° 26.767′ N
                                   Degrees Minutes Seconds (dms) - 40° 26′ 46″ N
                                   Decimal Degrees (dd) - 40.446° N

Formátování zeměpisné šířky a délky je Decimal Degrees (dd).

Funkční jednoduchá navigace

Program pro MicroPython

Knihovna l76x.py pro komunikaci s modulem L76K.

l76x.py
# -*- coding:utf-8 -*-

from machine import UART,Pin
import math
import time

Temp = '0123456789ABCDEF*'
BUFFSIZE = 1100

pi = 3.14159265358979324
a = 6378245.0
ee = 0.00669342162296594323
x_pi = 3.14159265358979324 * 3000.0 / 180.0

class L76X(object):
    FORCE_PIN  = 14
    STANDBY_PIN= 17
    
    Lon = 0.0
    Lat = 0.0
    Lon_area = 'E'
    Lat_area = 'W'
    Time_H = 0
    Time_M = 0
    Time_S = 0
    Status = 0
    Lon_Baidu = 0.0
    Lat_Baidu = 0.0
    Lon_Google = 0.0
    Lat_Google = 0.0
    
    GPS_Lon = 0
    GPS_Lat = 0
    
    #Startup mode
    SET_HOT_START       = '$PMTK101'
    SET_WARM_START      = '$PMTK102'
    SET_COLD_START      = '$PMTK103'
    SET_FULL_COLD_START = '$PMTK104'

    #Standby mode -- Exit requires high level trigger
    SET_PERPETUAL_STANDBY_MODE      = '$PMTK161'
    SET_STANDBY_MODE                = '$PMTK161,0'

    SET_PERIODIC_MODE               = '$PMTK225'
    SET_NORMAL_MODE                 = '$PMTK225,0'
    SET_PERIODIC_BACKUP_MODE        = '$PMTK225,1,1000,2000'
    SET_PERIODIC_STANDBY_MODE       = '$PMTK225,2,1000,2000'
    SET_PERPETUAL_BACKUP_MODE       = '$PMTK225,4'
    SET_ALWAYSLOCATE_STANDBY_MODE   = '$PMTK225,8'
    SET_ALWAYSLOCATE_BACKUP_MODE    = '$PMTK225,9'

    #Set the message interval,100ms~10000ms
    SET_POS_FIX         = '$PMTK220'
    SET_POS_FIX_100MS   = '$PMTK220,100'
    SET_POS_FIX_200MS   = '$PMTK220,200'
    SET_POS_FIX_400MS   = '$PMTK220,400'
    SET_POS_FIX_800MS   = '$PMTK220,800'
    SET_POS_FIX_1S      = '$PMTK220,1000'
    SET_POS_FIX_2S      = '$PMTK220,2000'
    SET_POS_FIX_4S      = '$PMTK220,4000'
    SET_POS_FIX_8S      = '$PMTK220,8000'
    SET_POS_FIX_10S     = '$PMTK220,10000'

    #Switching time output
    SET_SYNC_PPS_NMEA_OFF   = '$PMTK255,0'
    SET_SYNC_PPS_NMEA_ON    = '$PMTK255,1'

    #To restore the system default setting
    SET_REDUCTION               = '$PMTK314,-1'

    SET_NMEA_OUTPUT = '$PMTK314,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,0'
    #Baud rate
    SET_NMEA_BAUDRATE          = '$PMTK251'
    SET_NMEA_BAUDRATE_115200   = '$PMTK251,115200'
    SET_NMEA_BAUDRATE_57600    = '$PMTK251,57600'
    SET_NMEA_BAUDRATE_38400    = '$PMTK251,38400'
    SET_NMEA_BAUDRATE_19200    = '$PMTK251,19200'
    SET_NMEA_BAUDRATE_14400    = '$PMTK251,14400'
    SET_NMEA_BAUDRATE_9600     = '$PMTK251,9600'
    SET_NMEA_BAUDRATE_4800     = '$PMTK251,4800'
    
    _uart0 = 0
    _uart1 = 1
    
    def __init__(self,uartx=_uart0,_baudrate = 9600 ):
        if uartx==self._uart1:
            self.ser = UART(uartx,baudrate=_baudrate,tx=Pin(4),rx=Pin(5))
        else:
            self.ser = UART(uartx,baudrate=_baudrate,tx=Pin(0),rx=Pin(1))

        self.StandBy = Pin(self.STANDBY_PIN,Pin.OUT)
        self.Force = Pin(self.FORCE_PIN,Pin.IN)
        self.StandBy.value(0)
        self.Force.value(0)
    
    def l76x_send_command(self, data):
        Check = ord(data[1]) 
        for i in range(2, len(data)):
            Check = Check ^ ord(data[i]) 
        data = data + Temp[16]
        data = data + Temp[int(Check/16)]
        data = data + Temp[int(Check%16)]
        self.uart_send_string(data.encode())
        self.uart_send_byte('\r'.encode())
        self.uart_send_byte('\n'.encode())
        print (data)    

    def gcj02_to_bd09(self,lng, lat):
        z = math.sqrt(lng * lng + lat * lat) + 0.00002 * math.sin(lat * x_pi)
        theta = math.atan2(lat, lng) + 0.000003 * math.cos(lng * x_pi)
        bd_lng = z * math.cos(theta) + 0.0065
        bd_lat = z * math.sin(theta) + 0.006
        return [bd_lng, bd_lat]

    def bd09_to_gcj02(self,bd_lon, bd_lat):
        x = bd_lon - 0.0065
        y = bd_lat - 0.006
        z = math.sqrt(x * x + y * y) - 0.00002 * math.sin(y * x_pi)
        theta = math.atan2(y, x) - 0.000003 * math.cos(x * x_pi)
        gg_lng = z * math.cos(theta)
        gg_lat = z * math.sin(theta)
        return [gg_lng, gg_lat]

    def wgs84_to_gcj02(self,lng, lat):
        if self.out_of_china(lng, lat): 
            return [lng, lat]
        dlat = self._transformlat(lng - 105.0, lat - 35.0)
        dlng = self._transformlng(lng - 105.0, lat - 35.0)
        radlat = lat / 180.0 * pi
        magic = math.sin(radlat)
        magic = 1 - ee * magic * magic
        sqrtmagic = math.sqrt(magic)
        dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi)
        dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * pi)
        mglat = lat + dlat
        mglng = lng + dlng
        return [mglng, mglat]


    def gcj02_to_wgs84(self,lng, lat):
        if self.out_of_china(lng, lat):
            return [lng, lat]
        dlat = self._transformlat(lng - 105.0, lat - 35.0)
        dlng = self._transformlng(lng - 105.0, lat - 35.0)
        radlat = lat / 180.0 * pi
        magic = math.sin(radlat)
        magic = 1 - ee * magic * magic
        sqrtmagic = math.sqrt(magic)
        dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi)
        dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * pi)
        mglat = lat + dlat
        mglng = lng + dlng
        return [lng * 2 - mglng, lat * 2 - mglat]

    def bd09_to_wgs84(self,bd_lon, bd_lat):
        lon, lat = self.bd09_to_gcj02(bd_lon, bd_lat)
        return self.gcj02_to_wgs84(lon, lat)

    def wgs84_to_bd09(self,lon, lat):
        lon, lat = self.wgs84_to_gcj02(lon, lat)
#         return gcj02_to_bd09(lon, lat)
        self.Lon_Baidu,self.Lat_Baidu = self.gcj02_to_bd09(lon, lat)

    def _transformlat(self,lng, lat):
        ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + \
            0.1 * lng * lat + 0.2 * math.sqrt(math.fabs(lng))
        ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 *
                math.sin(2.0 * lng * pi)) * 2.0 / 3.0
        ret += (20.0 * math.sin(lat * pi) + 40.0 *
                math.sin(lat / 3.0 * pi)) * 2.0 / 3.0
        ret += (160.0 * math.sin(lat / 12.0 * pi) + 320 *
                math.sin(lat * pi / 30.0)) * 2.0 / 3.0
        return ret


    def _transformlng(self,lng, lat):
        ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + \
            0.1 * lng * lat + 0.1 * math.sqrt(math.fabs(lng))
        ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 *
                math.sin(2.0 * lng * pi)) * 2.0 / 3.0
        ret += (20.0 * math.sin(lng * pi) + 40.0 *
                math.sin(lng / 3.0 * pi)) * 2.0 / 3.0
        ret += (150.0 * math.sin(lng / 12.0 * pi) + 300.0 *
                math.sin(lng / 30.0 * pi)) * 2.0 / 3.0
        return ret

    def out_of_china(self,lng, lat):
        return not (lng > 73.66 and lng < 135.05 and lat > 3.86 and lat < 53.55)

    def l76x_set_baudrate(self, _baudrate, uartx=_uart0):
        if self._uart1==uartx:
            self.ser = UART(uartx,baudrate=_baudrate,tx=Pin(4),rx=Pin(5))
        else:
            self.ser = UART(uartx,baudrate=_baudrate,tx=Pin(0),rx=Pin(1))

    def l76x_exit_backup_mode(self):
        self.Force.value(1)
        time.sleep(1)
        self.Force.value(0)
        time.sleep(1)
        self.Force = Pin(self.FORCE_PIN,Pin.IN)
        
    def uart_send_byte(self, value): 
        self.ser.write(value) 

    def uart_send_string(self, value): 
        self.ser.write(value)

    def uart_receive_byte(self): 
        return self.ser.read(1)

    def uart_receiveString(self, value): 
        data = self.ser.read(value)
        return data
    
    def uart_any(self):
        return self.ser.any()

Příklady

Přiklady dodané výrobcem modulu. Zde jsem musel opravit chyby, převážně velká a malá písmenka a zapojení UARTu.

Příklad navigace.

coordinates_converted.py
# -*- coding:utf-8 -*-

import time
from pico import l76x
import math
import hashlib
from pico.micropyGPS.micropyGPS import MicropyGPS

# define the UART number and its baudrate , when UARTx is 1 please solder the UART1 0R resistor on Pico-GPS-L76B board
# UARTx = 1
UARTx = 1

# define the rp2040 uart baudrate , the default baudrate is 9600 of L76B 
BAUDRATE = 9600

# make an object of gnss device , the default uart is UART0 and its baudrate is 9600bps
gnss_l76b=l76x.L76X(uartx=UARTx,_baudrate = BAUDRATE)

# exit the backup mode when start
gnss_l76b.l76x_exit_backup_mode()

# enable/disable sync PPS when NMEA output
'''
optional:
SET_SYNC_PPS_NMEA_ON
SET_SYNC_PPS_NMEA_OFF
'''
gnss_l76b.l76x_send_command(gnss_l76b.SET_SYNC_PPS_NMEA_ON)


# make an object of NMEA0183 sentence parser
"""
Setup GPS Object Status Flags, Internal Data Registers, etc
local_offset (int): Timzone Difference to UTC
location_formatting (str): Style For Presenting Longitude/Latitude:
                           Decimal Degree Minute (ddm) - 40° 26.767′ N
                           Degrees Minutes Seconds (dms) - 40° 26′ 46″ N
                           Decimal Degrees (dd) - 40.446° N
"""
parser = MicropyGPS(location_formatting='dd')

sentence = ''

while True:
    if gnss_l76b.uart_any():
        sentence = parser.update(chr(gnss_l76b.uart_receive_byte()[0]))
        if sentence:
            
            print('WGS84 zeměpisné souřadnice: šířka(%c), délka(%c) %.9f,%.9f'%(parser.latitude[1],parser.longitude[1],parser.latitude[0],parser.longitude[0]))
            #print('copy WGS84 coordinates and paste it on Google map web https://www.google.com/maps')

            #gnss_l76b.wgs84_to_bd09(parser.longitude[0],parser.latitude[0])
            #print('Baidu Coordinate: longitude(%c),latitudes(%c) %.9f,%.9f'%(parser.longitude[1],parser.latitude[1],gnss_l76b.Lon_Baidu,gnss_l76b.Lat_Baidu))
            #print('copy Baidu Coordinate and paste it on the baidu map web https://api.map.baidu.com/lbsapi/getpoint/index.html')
            
            print('Světový čas (UTC): %02d:%02d:%02d'%(parser.timestamp[0],parser.timestamp[1],parser.timestamp[2]))
            
#           print fix status
            '''
            1 : NO FIX
            2 : FIX 2D
            3 : FIX_3D
            '''
            print('Fix Status:', parser.fix_stat)
            
            print('Nadmořská výška: %d m'%(parser.altitude))
            print('Výška nad geoidem:', parser.geoid_height)
            print('Horizontální odchylka přesnosti:', parser.hdop)
            print('Počet použitých satelitů:', parser.satellites_in_use)
            print('')            

Nastavení GNSS.

gnss_settings.py
# -*- coding:utf-8 -*-

import time
from pico import l76x
import math

# define the UART number and its baudrate , when UARTx is 1 please solder the UART1 0R resistor on Pico-GPS-L76B board
# UARTx = 1
UARTx = 1
# define the rp2040 uart baudrate , the default baudrate is 9600 of L76B 
BAUDRATE = 9600

# make an object of gnss device , the default uart is UART0 and its baudrate is 9600bps
gnss_l76b=l76x.L76X(uartx=UARTx,_baudrate = BAUDRATE)

# set L76B baudrate
'''
optional:
SET_NMEA_BAUDRATE_115200
SET_NMEA_BAUDRATE_57600
SET_NMEA_BAUDRATE_38400
SET_NMEA_BAUDRATE_19200
SET_NMEA_BAUDRATE_14400
SET_NMEA_BAUDRATE_9600
SET_NMEA_BAUDRATE_4800
'''
gnss_l76b.l76x_send_command(gnss_l76b.SET_NMEA_BAUDRATE_9600)
time.sleep(2)

# set rp2040 UARTx baudrate , it should be same as L76B baudrate , otherwise GPS NMEA sentence parser doesnt work
gnss_l76b.l76x_set_baudrate(_baudrate=BAUDRATE, uartx=UARTx)

# set NMEA0183 sentence output frequence
'''
optional:
SET_POS_FIX_100MS
SET_POS_FIX_200MS
SET_POS_FIX_400MS
SET_POS_FIX_800MS
SET_POS_FIX_1S
SET_POS_FIX_2S
SET_POS_FIX_4S
SET_POS_FIX_8S
SET_POS_FIX_10S
'''
gnss_l76b.l76x_send_command(gnss_l76b.SET_POS_FIX_1S)

# exit the backup mode when start
gnss_l76b.l76x_exit_backup_mode()

# enable/disable sync PPS when NMEA output
'''
optional:
SET_SYNC_PPS_NMEA_ON
SET_SYNC_PPS_NMEA_OFF
'''
gnss_l76b.l76x_send_command(gnss_l76b.SET_SYNC_PPS_NMEA_ON)

# L76B will enter STANDBY mode, the NMEA0183 sentence stop output
gnss_l76b.l76x_send_command(gnss_l76b.SET_STANDBY_MODE)
time.sleep(10)

# wake up L76B 
gnss_l76b.l76x_send_command(gnss_l76b.SET_NORMAL_MODE)
gnss_l76b.StandBy.value(1)

# enable NMEA0183 sentence output
gnss_l76b.l76x_send_command(gnss_l76b.SET_NMEA_OUTPUT) 

Výpis NMEA0183 vět.

Zdroje a odkazy