This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

MQTT blocks restarting GPS?

Hi,

I'm writing a program that swaps between LTE and GPS to send the device's location to AWS over MQTT. I am able to connect to LTE and AWS, then swap to GPS and get a fix, and swap back to LTE. However, when I then try to go back to GPS, I get a bsd recoverable error 3, and it appears I cannot communicate over the GPS socket.

If I have everything EXCEPT connecting to MQTT, I am able to freely swap between LTE and GPS.

I've attached my code below:

called by main():

void test_gps(){

    spoof(false);

    led_setup();
    button_setup();

// Storage
    // Set up certificates before nvs or else permission errors
    provision_certificates();

    nvs_setup();
    printk("\nNVS set up\n");
//---

    k_sleep(1000);

//// MQTT
    int err;
    struct mqtt_client client;
    struct sockaddr_storage broker;
    struct pollfd fds;

    s64_t timer = k_uptime_get();

    begin_lte_only();
    lte_lc_offline();
    modem_configure();
    lte_lc_edrx_req(true);

    client_init(&client, &broker, CONFIG_MQTT_BROKER_HOSTNAME);
    aws_fota_init(&client, CONFIG_APP_VERSION, aws_fota_cb_handler);
    err = mqtt_connect(&client);
    if (err != 0) {
            printk("ERROR: mqtt_connect %d\n", err);
    }
    printk("MQTT Connected");
    fds_init(&client, &fds);
    boot_write_img_confirmed();
////---

// Defs
    GPS_Logging_Off();
    bool do_gps = false;

    bool do_lte = true;
    s64_t publish_timer = k_uptime_get();
    s64_t live_timer = k_uptime_get();

    s64_t loop_timer = k_uptime_get();
//---

    printk("\nLoop starting\n");
    while(1){

// GPS Loop
        if(detect_press(2)){
            if(do_gps){
                printk("\ngps off\n");
                GPS_Disable();

                do_gps = false;
            }else{
                mqtt_disconnect(&client);
                lte_lc_offline();
                printk("\ngps on");
                gps_off_lte_off();

                GPS_Init();
                GPS_Logging_Off();
                printk("\nGPS Initialized\n");
                GPS_Enable();
                printk("\nGPS Enabled\n");
                do_gps = true;
                do_lte = false;
            }
        }


        if(detect_press(1)){
            begin_lte_only();
            lte_lc_offline();
            modem_configure();
            lte_lc_edrx_req(true);

            publish_timer = k_uptime_get();
            live_timer = k_uptime_get();
            
            
            struct mqtt_client client;
            struct sockaddr_storage broker;
            struct pollfd fds;
            client_init(&client, &broker, CONFIG_MQTT_BROKER_HOSTNAME);
            aws_fota_init(&client, CONFIG_APP_VERSION, aws_fota_cb_handler);
            err = mqtt_connect(&client);
            if (err != 0) {
                    printk("ERROR: mqtt_connect %d\n", err);
            }
            printk("MQTT Connected");
            fds_init(&client, &fds);
            boot_write_img_confirmed();

            do_lte = true;  
        }

        if(do_gps) GPS_State_Machine(&fs);
//---   
//---
        while(k_uptime_get()-loop_timer <= 20);
        loop_timer = k_uptime_get();
    }
}

GPS code:

void GPS_State_Machine(struct nvs_fs* fs){
    switch(gps_state){
		case GPS_IDLE:
                    
                    // Record a coordinate every gps_update_rate period
                    if(k_uptime_get()-t_last_location_recorded >= GPS_Update_Rate(-1)){
                        t_last_location_recorded = k_uptime_get();
                        gps_state = RECORD_COORDINATE;
                    }
                    break;

		case RECORD_COORDINATE:{

                    // Record a location in memory
                    toggle_led(1);
                    update_gps_data(&gps_data);

                    if(log_data){
                        save_gps_data(&last_fix, fs);
                    }

                    toggle_led(1);
                    gps_state = GPS_IDLE;
                    break;}

                case GET_FIX:
                    // Ping every FIX_PING_RATE period to try to get a fix
                    if(k_uptime_get()-t_last_ping >= FIX_PING_RATE){
                        t_last_ping = k_uptime_get();
                        toggle_led(2);

                        if(!got_first_fix){
                            get_gps_fix(&gps_data);
                        }
                        if(got_first_fix){
                            led_on(2);
                            gps_state = GPS_IDLE;
                        }

                    }
                    break;
	}
}


int get_gps_fix(nrf_gnss_data_frame_t* gps_data){
    /*
        Records data from gps and prints it out every 500ms until a fix is detected.
    */

    if(spoof_gps_data){
        printk("Spoofed data, switching out of getting fix");
        gps_state = GPS_IDLE;
        return 0;
    }

    do {
    
    } while(process_gps_data(gps_data) > 0); // Read data from GPS
     
    if(!got_first_fix){
        cnt = (cnt+1)%4;
        printk("\033[1;1H");
        printk("\033[2J");
        print_satellite_stats(gps_data);
        printk("\nScanning: [%c] ", update_indicator[cnt]);
    }
    else if(k_uptime_get()-fix_timestamp >= 1){
        display_gps_fixed(gps_data);
    }

    return 0;
}

int process_gps_data(nrf_gnss_data_frame_t *gps_data)
{
	int retval;

	retval = nrf_recv(gps_socket, gps_data, sizeof(nrf_gnss_data_frame_t), NRF_MSG_DONTWAIT);

	if (retval > 0) {

		switch (gps_data->data_id) {
		case NRF_GNSS_PVT_DATA_ID:
                        
                        printk("\nPVT data received\n");
			if ((gps_data->pvt.flags &
				NRF_GNSS_PVT_FLAG_FIX_VALID_BIT)
				== NRF_GNSS_PVT_FLAG_FIX_VALID_BIT) {

				if (!got_first_fix) {
					got_first_fix = true;
				}

				fix_timestamp = k_uptime_get();
				memcpy(&last_fix, gps_data, sizeof(nrf_gnss_data_frame_t));

				nmea_string_cnt = 0;
			}
			break;

		case NRF_GNSS_NMEA_DATA_ID:
                        printk("\nNMEA data received\n");
			if (nmea_string_cnt < 10) {
				memcpy(nmea_strings[nmea_string_cnt++],
				       gps_data->nmea,
				       retval);
			}
			break;

		default:
                        printk("\nBytes read\n");
			break;
		}
	}else{
                printk("\nProcess GPS Data error: %d", retval);
        }

	return retval;
}


void GPS_Init(){
    /*
        Sets default variable values and sets the socket options for the GPS.
    */
    
    UART_Output_On();
    GPS_Logging_On();
    GPS_Update_Rate(1000); 
    loc_id = 1;
    if(spoof_gps_data){
        gps_data = office;
        gps_state = GPS_IDLE;
        UART_Output_Off();
    }else{
        gps_state = GET_FIX;
    }
    got_first_fix = false;
    t_last_location_recorded = k_uptime_get();
    
}

int GPS_Enable(){
    if(!spoof_gps_data){
        int rv = init_app();
        if(rv) printk("init_app failure: rv = %d", rv);
    }

    return 0;
}


int enable_gps(void)
{
 	int  at_sock;
 	int  bytes_sent;
 	int  bytes_received;
 	char buf[2];

 	at_sock = socket(AF_LTE, 0, NPROTO_AT);
 	if (at_sock < 0) {
                printk("\nBad at_sock\n");
 		return -1;
 	}

 	for (int i = 0; i < ARRAY_SIZE(at_commands); i++) {
 		bytes_sent = send(at_sock, at_commands[i],
 				  strlen(at_commands[i]), 0);

 		if (bytes_sent < 0) {
                        printk("Negative Bytes");
 			close(at_sock);
 			return -1;
 		}

 		do {
 			bytes_received = recv(at_sock, buf, 2, 0);
 		} while (bytes_received == 0);

 		if (memcmp(buf, "OK", 2) != 0) {
                        printk("\nNot OK: %s, %d\n", buf, i);
 			close(at_sock);
 			return -1;
 		}
 	}

 	close(at_sock);

 	return 0;
 }

int init_app(void)
{
        /*
            Initializes GPS settings and socket for GPS comms.
        */
	u16_t fix_retry     = 0;
	u16_t fix_interval  = 1;
	u16_t nmea_mask     = NRF_CONFIG_NMEA_GSV_MASK |
			      NRF_CONFIG_NMEA_GSA_MASK |
			      NRF_CONFIG_NMEA_GLL_MASK |
			      NRF_CONFIG_NMEA_GGA_MASK |
			      NRF_CONFIG_NMEA_RMC_MASK;
	int   retval;

	if (enable_gps() != 0) {
		printk("Failed to enable GPS\n");
		return -1;
	}

	gps_socket = nrf_socket(NRF_AF_LOCAL, NRF_SOCK_DGRAM, NRF_PROTO_GNSS);

	if (gps_socket >= 0) {
		printk("Socket created\n");
	} else {
		printk("Could not init socket (err: %d)\n", gps_socket);
		return -1;
	}

	retval = nrf_setsockopt(gps_socket,
				NRF_SOL_GNSS,
				NRF_SO_GNSS_FIX_RETRY,
				&fix_retry,
				sizeof(uint16_t));

	if (retval != 0) {
		printk("Failed to set fix retry value: %d\n", retval);
		return -1;
	}

	retval = nrf_setsockopt(gps_socket,
				NRF_SOL_GNSS,
				NRF_SO_GNSS_FIX_INTERVAL,
				&fix_interval,
				sizeof(uint16_t));

	if (retval != 0) {
		printk("Failed to set fix interval value\n");
		return -1;
	}


//------ ADDED USE CASE PARAM FOR GPS REENABLE

	retval = nrf_setsockopt(gps_socket,
				NRF_SOL_GNSS,
				NRF_SO_GNSS_USE_CASE,
				&use_case,
				sizeof(uint8_t));

	if (retval != 0) {
		printk("Failed to set use case value: %d\n", retval);
                while(1);
		return -1;
	}
//-----



	retval = nrf_setsockopt(gps_socket,
				NRF_SOL_GNSS,
				NRF_SO_GNSS_NMEA_MASK,
				&nmea_mask,
				sizeof(uint16_t));

	if (retval != 0) {
		printk("Failed to set nmea mask\n");
		return -1;
	}

	retval = nrf_setsockopt(gps_socket,
				NRF_SOL_GNSS,
				NRF_SO_GNSS_START,
				NULL,
				0);

	if (retval != 0) {
		printk("Failed to start GPS\n");
		return -1;
	}

	return 0;
}


AT command swapping code:

int gps_on_lte_off(){
    const char* cmds[] = {"AT+CFUN=4", "AT\%XSYSTEMMODE=0,0,1,0", "AT+CFUN=1"};
    
    int at_socket = socket(AF_LTE, 0, NPROTO_AT);
    if(at_socket < 0){
        printk("Socket error");
        return at_socket;
    }

    char buf[2];
    int bytes_received;
    s64_t timer;
    for(int ix=0; ix < 3; ix++){
        if(send(at_socket, cmds[ix], strlen(cmds[ix]), 0) < 0){
            printk("send error: %s", cmds[ix]);
            return -1;
        }
        
        do {
                bytes_received = recv(at_socket, buf, 2, 0);
        } while (bytes_received == 0);

        if (memcmp(buf, "OK", 2) != 0) {
                printk("\nNot OK: %s, %s\n", buf, cmds[ix]);
                close(at_socket);
                return -1;
        }

        timer = k_uptime_get();
        while(k_uptime_get()-timer < 500);
    }

    close(at_socket);
    return 0;
}



int gps_off_lte_on(){
    const char* cmds[] = {"AT+CFUN=4", "AT\%XSYSTEMMODE=1,0,0,0", "AT+CFUN=1"};
    
    int at_socket = socket(AF_LTE, 0, NPROTO_AT);
    if(at_socket < 0){
        printk("Socket error");
        return at_socket;
    }

    char buf[2];
    int bytes_received;
    s64_t timer;
    for(int ix=0; ix < 3; ix++){
        if(send(at_socket, cmds[ix], strlen(cmds[ix]), 0) < 0){
            printk("send error: %s", cmds[ix]);
            return -1;
        }
        
        do {
                bytes_received = recv(at_socket, buf, 2, 0);
        } while (bytes_received == 0);

        if (memcmp(buf, "OK", 2) != 0) {
                printk("\nNot OK: %s, %s\n", buf, cmds[ix]);
                close(at_socket);
                return -1;
        }

        timer = k_uptime_get();
        while(k_uptime_get()-timer < 500);
    }

    close(at_socket);
    return 0;
}


int gps_on_lte_on(){
    const char* cmds[] = {"AT+CFUN=4", "AT\%XSYSTEMMODE=1,0,1,0", "AT+CFUN=1"};
    
    int at_socket = socket(AF_LTE, 0, NPROTO_AT);
    if(at_socket < 0){
        printk("Socket error");
        return at_socket;
    }

    char buf[2];
    int bytes_received;
    s64_t timer;
    for(int ix=0; ix < 3; ix++){
        if(send(at_socket, cmds[ix], strlen(cmds[ix]), 0) < 0){
            printk("send error: %s", cmds[ix]);
            return -1;
        }
        
        do {
                bytes_received = recv(at_socket, buf, 2, 0);
        } while (bytes_received == 0);

        if (memcmp(buf, "OK", 2) != 0) {
                printk("\nNot OK: %s, %s\n", buf, cmds[ix]);
                close(at_socket);
                return -1;
        }

        timer = k_uptime_get();
        while(k_uptime_get()-timer < 500);
    }

    close(at_socket);
    return 0;
}


int gps_off_lte_off(){
    const char* cmds[] = {"AT+CFUN=4", "AT\%XSYSTEMMODE=0,0,0,0", "AT+CFUN=1"};
    
    int at_socket = socket(AF_LTE, 0, NPROTO_AT);
    if(at_socket < 0){
        printk("Socket error");
        return at_socket;
    }

    char buf[2];
    int bytes_received;
    s64_t timer;
    for(int ix=0; ix < 3; ix++){
        if(send(at_socket, cmds[ix], strlen(cmds[ix]), 0) < 0){
            printk("send error: %s", cmds[ix]);
            return -1;
        }
        
        do {
                bytes_received = recv(at_socket, buf, 2, 0);
        } while (bytes_received == 0);

        if (memcmp(buf, "OK", 2) != 0) {
                printk("\nNot OK: %s, %s\n", buf, cmds[ix]);
                close(at_socket);
                return -1;
        }

        timer = k_uptime_get();
        while(k_uptime_get()-timer < 500);
    }

    close(at_socket);
    return 0;
}


int begin_lte_only(){
    const char* cmds[] = {"AT+CFUN=4", "AT\%XSYSTEMMODE=1,0,0,0", "AT+CFUN=1"};
//    const char* cmds[] = {"AT\%XSYSTEMMODE=1,0,0,0", "AT+CFUN=1"};

    int at_socket = socket(AF_LTE, 0, NPROTO_AT);
    if(at_socket < 0){
        printk("Socket error");
        return at_socket;
    }

    char buf[2];
    int bytes_received;
    s64_t timer;
    for(int ix=0; ix < 3; ix++){
        if(send(at_socket, cmds[ix], strlen(cmds[ix]), 0) < 0){
            printk("send error: %s", cmds[ix]);
            return -1;
        }
        
        do {
                bytes_received = recv(at_socket, buf, 2, 0);
        } while (bytes_received == 0);

        if (memcmp(buf, "OK", 2) != 0) {
                printk("\nNot OK: %s, %s\n", buf, cmds[ix]);
                close(at_socket);
                return -1;
        }

        timer = k_uptime_get();
        while(k_uptime_get()-timer < 500);
    }

    close(at_socket);
    return 0;
}

int swap_to_gps_only(){
    const char* cmds[] = {"AT+CFUN=4", "AT\%XSYSTEMMODE=0,0,1,0", "AT\%XMAGPIO=1,0,0,1,1,1574,1577", "AT+CFUN=1"};
    
    int at_socket = socket(AF_LTE, 0, NPROTO_AT);
    if(at_socket < 0){
        printk("Socket error");
        return at_socket;
    }

    char buf[2];
    int bytes_received;
    s64_t timer;
    for(int ix=0; ix < 4; ix++){
        if(send(at_socket, cmds[ix], strlen(cmds[ix]), 0) < 0){
            printk("send error: %s", cmds[ix]);
            return -1;
        }
        
        do {
                bytes_received = recv(at_socket, buf, 2, 0);
        } while (bytes_received == 0);

        if (memcmp(buf, "OK", 2) != 0) {
                printk("\nNot OK: %s, %s\n", buf, cmds[ix]);
                close(at_socket);
                return -1;
        }

        timer = k_uptime_get();
        while(k_uptime_get()-timer < 500);
    }

    close(at_socket);
    return 0;
}


int swap_to_lte_only(){
    const char* cmds[] = {"AT+CFUN=4", "AT\%XSYSTEMMODE=1,0,0,0", "AT\%XMAGPIO", "AT+CFUN=1"};
    
    int at_socket = socket(AF_LTE, 0, NPROTO_AT);
    if(at_socket < 0){
        printk("Socket error");
        return at_socket;
    }

    char buf[2];
    int bytes_received;
    s64_t timer;
    for(int ix=0; ix < 4; ix++){
        if(send(at_socket, cmds[ix], strlen(cmds[ix]), 0) < 0){
            printk("send error: %s", cmds[ix]);
            return -1;
        }
        
        do {
                bytes_received = recv(at_socket, buf, 2, 0);
        } while (bytes_received == 0);

        if (memcmp(buf, "OK", 2) != 0) {
                printk("\nNot OK: %s, %s\n", buf, cmds[ix]);
                close(at_socket);
                return -1;
        }

        timer = k_uptime_get();
        while(k_uptime_get()-timer < 500);
    }

    close(at_socket);
    return 0;
}

int lte_systemmode(){
    
    int at_socket = socket(AF_LTE, 0, NPROTO_AT);
    if(at_socket < 0){
        printk("Socket error");
        return at_socket;
    }

    char buf[2];
    int bytes_received;
    if(send(at_socket, "AT\%XSYSTEMMODE=1,0,0,0", strlen("AT\%XSYSTEMMODE=1,0,0,0"), 0) < 0){
        printk("send error: %s", "AT\%XSYSTEMMODE=1,0,0,0");
        return -1;
    }
    
    do {
            bytes_received = recv(at_socket, buf, 2, 0);
    } while (bytes_received == 0);

    if (memcmp(buf, "OK", 2) != 0) {
            printk("\nNot OK: %s, %s\n", buf, "AT\%XSYSTEMMODE=1,0,0,0");
            close(at_socket);
            return -1;
    }

    close(at_socket);
    return 0;
}



int gps_systemmode(){
    
    int at_socket = socket(AF_LTE, 0, NPROTO_AT);
    if(at_socket < 0){
        printk("Socket error");
        return at_socket;
    }

    char buf[2];
    int bytes_received;
    if(send(at_socket, "AT\%XSYSTEMMODE=0,0,1,0", strlen("AT\%XSYSTEMMODE=0,0,1,0"), 0) < 0){
        printk("send error: %s", "AT\%XSYSTEMMODE=0,0,1,0");
        return -1;
    }
    
    do {
            bytes_received = recv(at_socket, buf, 2, 0);
    } while (bytes_received == 0);

    if (memcmp(buf, "OK", 2) != 0) {
            printk("\nNot OK: %s, %s\n", buf, "AT\%XSYSTEMMODE=0,0,1,0");
            close(at_socket);
            return -1;
    }

    close(at_socket);
    return 0;
}

Output:

***** Booting Zephyr OS build v1.14.99-ncs3-snapshot2 *****
nrf_inbuilt_key_delete(16842753, 0) => result=0
nrf_inbuilt_key_delete(16842753, 1) => result=0
nrf_inbuilt_key_delete(16842753, 2) => result=0
nrf_inbuilt_key_write => result=0
nrf_inbuilt_key_write => result=0
nrf_inbuilt_key_write => result=0

NVS set up
[00:00:04.551,025] <inf> fs_nvs: 3 Sectors of 4096 bytes
[00:00:04.551,025] <inf> fs_nvs: alloc wra: 1, 7e8
[00:00:04.551,025] <inf> fs_nvs: data wra: 1, 604
LTE Link Connecting ...
LTE Link Connected! 0
IPv4 Address 0xaa271203
client_id: nrf-352656100266173
MQTT Connected
Loop starting

gps on
GPS Initialized
Socket created

GPS Enabled

Process GPS Data error: -1
Tracking: 0 Using: 0 Unhealthy: 0
Seconds since last fix 135

Scanning: [|]
PVT data received

NMEA data received

NMEA data received

NMEA data received

NMEA data received

NMEA data received

Process GPS Data error: -1
Tracking: 0 Using: 0 Unhealthy: 0
Seconds since last fix 135

Scanning: [/]
Process GPS Data error: -1
Tracking: 0 Using: 0 Unhealthy: 0
Seconds since last fix 136

Scanning: [-]
PVT data received

NMEA data received

NMEA data received

NMEA data received

NMEA data received

NMEA data received

Process GPS Data error: -1
Tracking: 0 Using: 0 Unhealthy: 0
Seconds since last fix 136

Scanning: [\]
PVT data received

NMEA data received

NMEA data received

NMEA data received

NMEA data received

NMEA data received

Process GPS Data error: -1
Tracking: 0 Using: 0 Unhealthy: 0
Seconds since last fix 137

Scanning: [|]
Process GPS Data error: -1
Tracking: 0 Using: 0 Unhealthy: 0
Seconds since last fix 137

Scanning: [/]
gps off
LTE Link Connecting ...
LTE Link Connected! 0
IPv4 Address 0x7dc40e03
client_id: nrf-352656100266173
MQTT Connected
gps on
GPS Initialized
Socket created

GPS Enabled

Process GPS Data error: -1
Tracking: 0 Using: 0 Unhealthy: 0
Seconds since last fix 177

Scanning: [|] Err: 3

Process GPS Data error: -1
Tracking: 0 Using: 0 Unhealthy: 0
Seconds since last fix 181

Scanning: [/]
Process GPS Data error: -1
Tracking: 0 Using: 0 Unhealthy: 0
Seconds since last fix 181

Using the debugger, I was able to find that the error occurred after the call to  retval = nrf_setsockopt(gps_socket, NRF_SOL_GNSS, NRF_SO_GNSS_START, NULL, 0);

What's going wrong?

Thanks.

Parents
  • Hi Johnny,
    The modem firmware v1.0.0 introduces GPS in PSM mode. 

    We have seen that switching OFF the modem and switching back and forth the GPS can cause unwanted behavior. 

    The recommended way is to use the GPS when the LTE-M is in PSM mode.

    You can see an example of this in the PR#943, which introduces GPS in PSM mode in the Asset tracker application.

  • Hi Martin,

    Thanks for the response. Is there any plans to address switching on and off the modem switching back and for the GPS issue?

    I'd very much like to have GPS operational during PSM. I've seen in many tickets references to that pull request. However, I and others on this site have trouble interpreting that application. There is little to no commenting or documentation, especially when it comes to how PSM and GPS are supposed to be set up to act concurrently. It seems almost specific to the asset tracker project itself, making it incredibly difficult to do it in a custom program.

    If the procedure moving forward for ALL projects using GPS and LTE with the nRF9160 is to use GPS while LTE is in PSM, I suggest an example that demonstrates just that. Or, a paragraph or two explaining the procedure to have PSM and GPS activated at the same time in any project would be incredibly helpful.

    For context, I've tried activating GPS as shown in the GPS example after calling modem_configure() and lte_lc_psm_req(true) and have not been successful. I've also used a power analyzer to verify I've entered PSM, then tried activating the GPS, to no avail.

Reply
  • Hi Martin,

    Thanks for the response. Is there any plans to address switching on and off the modem switching back and for the GPS issue?

    I'd very much like to have GPS operational during PSM. I've seen in many tickets references to that pull request. However, I and others on this site have trouble interpreting that application. There is little to no commenting or documentation, especially when it comes to how PSM and GPS are supposed to be set up to act concurrently. It seems almost specific to the asset tracker project itself, making it incredibly difficult to do it in a custom program.

    If the procedure moving forward for ALL projects using GPS and LTE with the nRF9160 is to use GPS while LTE is in PSM, I suggest an example that demonstrates just that. Or, a paragraph or two explaining the procedure to have PSM and GPS activated at the same time in any project would be incredibly helpful.

    For context, I've tried activating GPS as shown in the GPS example after calling modem_configure() and lte_lc_psm_req(true) and have not been successful. I've also used a power analyzer to verify I've entered PSM, then tried activating the GPS, to no avail.

Children
Related