GPS 1PPS on nRF9151 DK

Hello, my application requires very precise timing to trigger an action on the edge of the GPS time. I just need to get this time once in a while to synchronize the system, and afterwards, I can trigger a timer interrupt every 1s following the event of the GPS time trigger. After some time searching in the documentation, I found that the nRF9151 DK has a COEX1 interface, quoting from these 2 sources (source 1 and source 2):

COEX1 – Output from the LTE modem to the external device. When internal GPS is used, COEX1 delivers the GPS 1PPS (one pulse per second) time mark pulse. The 1PPS feature must not be used when LTE is enabled.

I'm trying to find a way to access GPS PPS signal, but unsure how. The closest forum post I found is this: https://devzone.nordicsemi.com/f/nordic-q-a/75137/getting-access-to-the-gps-pps-signal-on-the-nrf9160, but the question is about nRF9160 and it's over 2 years old, so I'm not sure if this is still relevant for the new nRF9151 DK. From this document, it seems that I can configure 1PPS, but I don't know how to get this. Is it via an interrupt? Do I need to make any hardware wiring? I'd appreciate it if there is a sample application or general guidance on how to approach it. Thank you.

Parents
  • I tried to enable 1PPS but I have no luck so far. 

    I followed one of the sample from Nordic Cellular IoT Course (Lesson 6 Exercise 1) to enable GPS only. I use the same code as this exercise, and I added 1 PPS:

    /* 1PPS pulse on COEX1 */
    struct nrf_modem_gnss_1pps_config config = {
        .pulse_interval = 120,
        .pulse_width = 500,
        .apply_start_time = false
    };
    
    /* In main right before nrf_modem_gnss_start */
    err = nrf_modem_gnss_1pps_enable(&config);
    if (err != 0) {
        LOG_ERR("Failed to enable 1 PPS, error %d", err);
        return -1;
    }
    
    

    I attached the main.c file here as well.

    /*
     * Copyright (c) 2022 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    
    #include <stdio.h>
    #include <ncs_version.h>
    #include <zephyr/kernel.h>
    
    #include <zephyr/logging/log.h>
    #include <modem/nrf_modem_lib.h>
    #include <modem/lte_lc.h>
    #include <dk_buttons_and_leds.h>
    
    /* STEP 4 - Include the header file for the GNSS interface */
    #include <nrf_modem_gnss.h>
    
    /* 1PPS pulse on COEX1 */
    struct nrf_modem_gnss_1pps_config config = {
        .pulse_interval = 120,
        .pulse_width = 500,
        .apply_start_time = false
    };
    
    /* STEP 5 - Define the PVT data frame variable */
    static struct nrf_modem_gnss_pvt_data_frame pvt_data;
    
    /* STEP 12.1 - Declare helper variables to find the TTFF */
    static int64_t gnss_start_time;
    static bool first_fix = false;
    
    static K_SEM_DEFINE(lte_connected, 0, 1);
    
    LOG_MODULE_REGISTER(Lesson6_Exercise1, LOG_LEVEL_INF);
    
    
    static int modem_configure(void)
    {
    	int err;
    
    	LOG_INF("Initializing modem library");
    
    	err = nrf_modem_lib_init();
    	if (err) {
    		LOG_ERR("Failed to initialize the modem library, error: %d", err);
    		return err;
    	}
    
    	return 0;
    }
    
    /* STEP 6 - Define a function to log fix data in a readable format */
    static void print_fix_data(struct nrf_modem_gnss_pvt_data_frame *pvt_data)
    {
    	LOG_INF("Latitude:       %.06f", pvt_data->latitude);
    	LOG_INF("Longitude:      %.06f", pvt_data->longitude);
    	LOG_INF("Altitude:       %.01f m", (double)pvt_data->altitude);
    	LOG_INF("Time (UTC):     %02u:%02u:%02u.%03u",
    	       pvt_data->datetime.hour,
    	       pvt_data->datetime.minute,
    	       pvt_data->datetime.seconds,
    	       pvt_data->datetime.ms);
    }
    
    
    static void gnss_event_handler(int event)
    {
    	int err;
    
    	switch (event) {
    	/* STEP 7 - On a PVT event, confirm if PVT data is a valid fix */
    	case NRF_MODEM_GNSS_EVT_PVT:
    		LOG_INF("Searching...");
    		/* STEP 15 - Print satellite information */
    		int num_satellites = 0;
    		for (int i = 0; i < 12 ; i++) {
    			if (pvt_data.sv[i].signal != 0) {
    				LOG_INF("sv: %d, cn0: %d, signal: %d", pvt_data.sv[i].sv, pvt_data.sv[i].cn0, pvt_data.sv[i].signal);
    				num_satellites++;
    			}
    		}
    		LOG_INF("Number of current satellites: %d", num_satellites);
    		err = nrf_modem_gnss_read(&pvt_data, sizeof(pvt_data), NRF_MODEM_GNSS_DATA_PVT);
    		if (err) {
    			LOG_ERR("nrf_modem_gnss_read failed, err %d", err);
    			return;
    		}
    		if (pvt_data.flags & NRF_MODEM_GNSS_PVT_FLAG_FIX_VALID) {
    			dk_set_led_on(DK_LED1);
    			print_fix_data(&pvt_data);
    			/* STEP 12.3 - Print the time to first fix */
    			if (!first_fix) {
    				LOG_INF("Time to first fix: %2.1lld s", (k_uptime_get() - gnss_start_time)/1000);
    				first_fix = true;
    			}
    			return;
    		}
    		break;
    	/* STEP 7.2 - Log when the GNSS sleeps and wakes up */
    	case NRF_MODEM_GNSS_EVT_PERIODIC_WAKEUP:
    		LOG_INF("GNSS has woken up");
    		break;
    	case NRF_MODEM_GNSS_EVT_SLEEP_AFTER_FIX:
    		LOG_INF("GNSS enter sleep after fix");
    		break;
    	default:
    		break;
    	}
    }
    
    int main(void)
    {
    	int err;
    
    	if (dk_leds_init() != 0) {
    		LOG_ERR("Failed to initialize the LEDs Library");
    	}
    
    	err = modem_configure();
    	if (err) {
    		LOG_ERR("Failed to configure the modem");
    		return 0;
    	}
    
    	/* STEP 8 - Activate only the GNSS stack */
    	if (lte_lc_func_mode_set(LTE_LC_FUNC_MODE_ACTIVATE_GNSS) != 0) {
    		LOG_ERR("Failed to activate GNSS functional mode");
    		return 0;
    	}
    
    	/* STEP 9 - Register the GNSS event handler */
    	if (nrf_modem_gnss_event_handler_set(gnss_event_handler) != 0) {
    		LOG_ERR("Failed to set GNSS event handler");
    		return 0;
    	}
    
    	/* STEP 10 - Set the GNSS fix interval and GNSS fix retry period */
    	if (nrf_modem_gnss_fix_interval_set(CONFIG_GNSS_PERIODIC_INTERVAL) != 0) {
    		LOG_ERR("Failed to set GNSS fix interval");
    		return 0;
    	}
    
    	if (nrf_modem_gnss_fix_retry_set(CONFIG_GNSS_PERIODIC_TIMEOUT) != 0) {
    		LOG_ERR("Failed to set GNSS fix retry");
    		return 0;
    	}
    
        err = nrf_modem_gnss_1pps_enable(&config);
        if (err != 0) {
            LOG_ERR("Failed to enable 1 PPS, error %d", err);
            return -1;
        }
    
    	/* STEP 11 - Start the GNSS receiver*/
    	LOG_INF("Starting GNSS");
    	if (nrf_modem_gnss_start() != 0) {
    		LOG_ERR("Failed to start GNSS");
    		return 0;
    	}
    
    	/* STEP 12.2 - Log the current system uptime */
    	gnss_start_time = k_uptime_get();
    
    	return 0;
    }

    I'm able to get a fix from GPS, but the COEX1 pin is not pulsing. I open the board configurator and enable this option:

    Then I connect the COEX1 pin from the nRF9151 DK to the oscilloscope, and there is no pulse. I don't know what I'm supposed to do to make the COEX1 pin to start pulsing. Any suggestions or help would be greatly appreciated. Thank you.

Reply
  • I tried to enable 1PPS but I have no luck so far. 

    I followed one of the sample from Nordic Cellular IoT Course (Lesson 6 Exercise 1) to enable GPS only. I use the same code as this exercise, and I added 1 PPS:

    /* 1PPS pulse on COEX1 */
    struct nrf_modem_gnss_1pps_config config = {
        .pulse_interval = 120,
        .pulse_width = 500,
        .apply_start_time = false
    };
    
    /* In main right before nrf_modem_gnss_start */
    err = nrf_modem_gnss_1pps_enable(&config);
    if (err != 0) {
        LOG_ERR("Failed to enable 1 PPS, error %d", err);
        return -1;
    }
    
    

    I attached the main.c file here as well.

    /*
     * Copyright (c) 2022 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    
    #include <stdio.h>
    #include <ncs_version.h>
    #include <zephyr/kernel.h>
    
    #include <zephyr/logging/log.h>
    #include <modem/nrf_modem_lib.h>
    #include <modem/lte_lc.h>
    #include <dk_buttons_and_leds.h>
    
    /* STEP 4 - Include the header file for the GNSS interface */
    #include <nrf_modem_gnss.h>
    
    /* 1PPS pulse on COEX1 */
    struct nrf_modem_gnss_1pps_config config = {
        .pulse_interval = 120,
        .pulse_width = 500,
        .apply_start_time = false
    };
    
    /* STEP 5 - Define the PVT data frame variable */
    static struct nrf_modem_gnss_pvt_data_frame pvt_data;
    
    /* STEP 12.1 - Declare helper variables to find the TTFF */
    static int64_t gnss_start_time;
    static bool first_fix = false;
    
    static K_SEM_DEFINE(lte_connected, 0, 1);
    
    LOG_MODULE_REGISTER(Lesson6_Exercise1, LOG_LEVEL_INF);
    
    
    static int modem_configure(void)
    {
    	int err;
    
    	LOG_INF("Initializing modem library");
    
    	err = nrf_modem_lib_init();
    	if (err) {
    		LOG_ERR("Failed to initialize the modem library, error: %d", err);
    		return err;
    	}
    
    	return 0;
    }
    
    /* STEP 6 - Define a function to log fix data in a readable format */
    static void print_fix_data(struct nrf_modem_gnss_pvt_data_frame *pvt_data)
    {
    	LOG_INF("Latitude:       %.06f", pvt_data->latitude);
    	LOG_INF("Longitude:      %.06f", pvt_data->longitude);
    	LOG_INF("Altitude:       %.01f m", (double)pvt_data->altitude);
    	LOG_INF("Time (UTC):     %02u:%02u:%02u.%03u",
    	       pvt_data->datetime.hour,
    	       pvt_data->datetime.minute,
    	       pvt_data->datetime.seconds,
    	       pvt_data->datetime.ms);
    }
    
    
    static void gnss_event_handler(int event)
    {
    	int err;
    
    	switch (event) {
    	/* STEP 7 - On a PVT event, confirm if PVT data is a valid fix */
    	case NRF_MODEM_GNSS_EVT_PVT:
    		LOG_INF("Searching...");
    		/* STEP 15 - Print satellite information */
    		int num_satellites = 0;
    		for (int i = 0; i < 12 ; i++) {
    			if (pvt_data.sv[i].signal != 0) {
    				LOG_INF("sv: %d, cn0: %d, signal: %d", pvt_data.sv[i].sv, pvt_data.sv[i].cn0, pvt_data.sv[i].signal);
    				num_satellites++;
    			}
    		}
    		LOG_INF("Number of current satellites: %d", num_satellites);
    		err = nrf_modem_gnss_read(&pvt_data, sizeof(pvt_data), NRF_MODEM_GNSS_DATA_PVT);
    		if (err) {
    			LOG_ERR("nrf_modem_gnss_read failed, err %d", err);
    			return;
    		}
    		if (pvt_data.flags & NRF_MODEM_GNSS_PVT_FLAG_FIX_VALID) {
    			dk_set_led_on(DK_LED1);
    			print_fix_data(&pvt_data);
    			/* STEP 12.3 - Print the time to first fix */
    			if (!first_fix) {
    				LOG_INF("Time to first fix: %2.1lld s", (k_uptime_get() - gnss_start_time)/1000);
    				first_fix = true;
    			}
    			return;
    		}
    		break;
    	/* STEP 7.2 - Log when the GNSS sleeps and wakes up */
    	case NRF_MODEM_GNSS_EVT_PERIODIC_WAKEUP:
    		LOG_INF("GNSS has woken up");
    		break;
    	case NRF_MODEM_GNSS_EVT_SLEEP_AFTER_FIX:
    		LOG_INF("GNSS enter sleep after fix");
    		break;
    	default:
    		break;
    	}
    }
    
    int main(void)
    {
    	int err;
    
    	if (dk_leds_init() != 0) {
    		LOG_ERR("Failed to initialize the LEDs Library");
    	}
    
    	err = modem_configure();
    	if (err) {
    		LOG_ERR("Failed to configure the modem");
    		return 0;
    	}
    
    	/* STEP 8 - Activate only the GNSS stack */
    	if (lte_lc_func_mode_set(LTE_LC_FUNC_MODE_ACTIVATE_GNSS) != 0) {
    		LOG_ERR("Failed to activate GNSS functional mode");
    		return 0;
    	}
    
    	/* STEP 9 - Register the GNSS event handler */
    	if (nrf_modem_gnss_event_handler_set(gnss_event_handler) != 0) {
    		LOG_ERR("Failed to set GNSS event handler");
    		return 0;
    	}
    
    	/* STEP 10 - Set the GNSS fix interval and GNSS fix retry period */
    	if (nrf_modem_gnss_fix_interval_set(CONFIG_GNSS_PERIODIC_INTERVAL) != 0) {
    		LOG_ERR("Failed to set GNSS fix interval");
    		return 0;
    	}
    
    	if (nrf_modem_gnss_fix_retry_set(CONFIG_GNSS_PERIODIC_TIMEOUT) != 0) {
    		LOG_ERR("Failed to set GNSS fix retry");
    		return 0;
    	}
    
        err = nrf_modem_gnss_1pps_enable(&config);
        if (err != 0) {
            LOG_ERR("Failed to enable 1 PPS, error %d", err);
            return -1;
        }
    
    	/* STEP 11 - Start the GNSS receiver*/
    	LOG_INF("Starting GNSS");
    	if (nrf_modem_gnss_start() != 0) {
    		LOG_ERR("Failed to start GNSS");
    		return 0;
    	}
    
    	/* STEP 12.2 - Log the current system uptime */
    	gnss_start_time = k_uptime_get();
    
    	return 0;
    }

    I'm able to get a fix from GPS, but the COEX1 pin is not pulsing. I open the board configurator and enable this option:

    Then I connect the COEX1 pin from the nRF9151 DK to the oscilloscope, and there is no pulse. I don't know what I'm supposed to do to make the COEX1 pin to start pulsing. Any suggestions or help would be greatly appreciated. Thank you.

Children
No Data
Related