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

IO error when configuring modem

Hi,

I have a project where my nrf9160 is able to enable and get a fix with GPS and turn in on and off. I am trying to enable LTE when the GPS is off. Here is my procedure:

Enable GPS as is in the GPS sample.

Get GPS fix

Close GPS socket

Send AT command AT%XSYSTEMMODE=0,0,0,0

Send AT command AT%XSYSTEMMODE=1,0,0,0

call lte_lc_init_and_connect();

Upon the last  call, I get error code -5, and occasionally +CEREG: 5,"D113","03318501",7 as output.

What more must I do to deactivate GPS and activate LTE effectively?

Thanks.

Parents
  • Please take a look at this pull request, which works out of the box on the 91 DK. In order to get GPS + LTE to work, you will need to set PSM mode. That way, the GPS can go to work while the LTE connection is sleeping. Let me know if you need any more help!

  • Hi Bjorn,
    Thanks for the response. So this is what I understand to be proper procedure for GPS and LTE:

    1. Start modem with lte_lc_init_and_connect()

    2. Activate psm with lte_lc_psm_req(true)

    3. Initialize and enable GPS (it is unclear how to do this. Do I use the procedure as shown in the GPS sample? The pull request you referenced does something completely different)

    4. Get GPS fix and data

    5. Turn off GPS

    6. Send data over LTE, psm reactivating after sending is finished

    7. Repeat from step 3.

    Undergoing this process (setting up GPS as it is shown in the GPS sample) fails with nrf_setsockopt(gps_socket, NRF_SOL_GNSS, NRF_SO_GNSS_FIX_RETRY, &fix_retry, sizeof(uint16_t)); returning -1 in init_app().

    Here is my code and output:

    int test_flow(){
        printk("Test Flow\n");
        int err;
    
        printk("Configuring Modem\n");
        err = lte_lc_init_and_connect();
        if(err){
            printk("lte: %d", err);
            return -1;
        }
        printk("\nModem Configured");
        printk("\nActivating PSM");
        err = lte_lc_psm_req(true);
        if(err){
            printk("psm: %d", err);
            return -1;
        }
        printk("\nSetting up GPS");
        err = init_app();
        if(err){
            printk("init app: %d", err);
            return -1;
        }
        printk("\nGPS Enabled\n");
    
    
        return 0;
    }

    Test Flow
    Configuring Modem
    
    Modem Configured
    Activating PSM
    Setting up GPSSocket created
    Failed to set fix retry value: -1
    init app: -1
    

    There are many tickets that reference that pull request. However, that sample is not very helpful. The code itself is not clear about how GPS is acting alongside LTE (by operating during the sleep period of PSM, yes, but how?). What would be most useful to me is a procedure or pseudo code or example showing the set up of LTE, going into PSM, and setting up GPS successfully.

  • The setting up of LTE for either NB-IoT and Cat-M has no effect on the operation of the GPS. What does affect it is the way the LTE information is cleared and the modem reconfigured for GPS. In all honesty, your better off coding your own custom modem interaction code, that way you know exactly what the modem is doing. PSM is optional and I won't include it here. If you wish to use GPS in PSM you will need to ensure the device is attached to the network and requested PSM. PSM GPS only works during the sleep windows when the LTE connection is off as you noted. Once the basic GPS and LTE configurations are working, move to adding PSM to your application.

    The functioning flow which my custom program uses is:

    1. Initial modem configuration for LTE (in this case NB-IoT)

    "AT+CFUN=4"
    "AT\%XSYSTEMMODE=0,1,0,0"
    "AT+CFUN=1"
    

    2.Swap to GPS, modem must be placed in flight mode, leave socket open:

    "AT+CFUN=4"
    "AT\%XSYSTEMMODE=0,0,1,0"
    "AT\%XMAGPIO=1,0,0,1,1,1574,1577"
    "AT+CFUN=1"

    3. Then open the GPS socket using the code from the GPS example application to open and set the socket options, literally how they do it is how it should be written. I believe you reference the set-up function with init_app() in your code.

    4. Once finished sampling GPS fixes, close the GPS socket with the stop socket option, remember to close the open GPS socket here:

    	err = nrf_setsockopt(Socket_ID,
    				NRF_SOL_GNSS,
    				NRF_SO_GNSS_STOP,
    				NULL,
    				0);
    				
    	err = nrf_close(Socket_ID);

    5. Clear GPS configuration, set modem to LTE

    "AT+CFUN=4"
    "AT\%XSYSTEMMODE=0,1,0,0"
    "AT\%XMAGPIO"
    "AT+CFUN=1"

  • Thank you for the detailed response!

    I had tried something similar using AT+CFUN and the SYSTEMMODE commands, but I had not used the MAGPIO settings (except when configuring the GPS)

    Here is my current program:

    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 get_gps_fix(&gps_data);
        return 0;
    }
    
    int GPS_Disable(){
        int err;
        err = nrf_setsockopt(gps_socket,
                                NRF_SOL_GNSS,
                                NRF_SO_GNSS_STOP,
                                NULL,
                                0);
        if(err){
            printk("\nDisable setsockopt error: %d\n", err);
        }
        err = nrf_close(gps_socket);
        if(err){
            printk("\nnrf_close error: %d\n", err);
        }
        return err;
    }
    
    int modem_configure(void)
    {
    	if (IS_ENABLED(CONFIG_LTE_AUTO_INIT_AND_CONNECT)) {
    		/* Do nothing, modem is already turned on
    		 * and connected.
    		 */
    	} else {
    		int err;
    
    		printk("LTE Link Connecting ...\n");
    		err = lte_lc_init_and_connect();
    		__ASSERT(err == 0, "LTE link could not be established.");
    		printk("LTE Link Connected! %d \n", err);
                    return err;
    	}
            return 0;
    }
    
    
    
    int begin_lte_only(){
        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 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 main(void){
           
        begin_lte_only();
        modem_configure();
        
        printk("\nSwapping to GPS\n");
        swap_to_gps_only();
    
        GPS_Init();
        int rv = GPS_Enable();
        if(rv) printk("init_app failure: rv = %d", rv);
        printk("\nGPS Enabled");
        
        k_sleep(K_MSEC(2000));
    
        GPS_Disable();
        printk("\nGPS Disabled");
        swap_to_lte_only();
        modem_configure();
    
        return 0;
    }
    
    
    
    
    
    

    It gives me this output:

    LTE Link Connecting ...                                                         
    LTE Link Connected! -5                                                          
                                                                                    
    Swapping to GPS                                                                 
    Socket created                                                                  
                                                                                    
    GPS Enabled                                                                     
    GPS DisabledLTE Link Connecting ...                                             
    LTE Link Connected! -5                                                          
                                                                                    
                                                                                    
    Ending Program 
    

    Then, after a few seconds:

    +CEREG: 2,"D113","03316803",7                                     
    +CEREG: 5,"D113","03316803",7 
    

    I've tried waiting up to 3 seconds between each call to a series of AT commands and received the same output.

    If I don't call begin_lte_only(), then LTE works the first time.

    Any insight on why I'm still getting this IO error? I probed the GPS MAGPIO pin and it seems to be going high and low at the appropriate times.

Reply
  • Thank you for the detailed response!

    I had tried something similar using AT+CFUN and the SYSTEMMODE commands, but I had not used the MAGPIO settings (except when configuring the GPS)

    Here is my current program:

    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 get_gps_fix(&gps_data);
        return 0;
    }
    
    int GPS_Disable(){
        int err;
        err = nrf_setsockopt(gps_socket,
                                NRF_SOL_GNSS,
                                NRF_SO_GNSS_STOP,
                                NULL,
                                0);
        if(err){
            printk("\nDisable setsockopt error: %d\n", err);
        }
        err = nrf_close(gps_socket);
        if(err){
            printk("\nnrf_close error: %d\n", err);
        }
        return err;
    }
    
    int modem_configure(void)
    {
    	if (IS_ENABLED(CONFIG_LTE_AUTO_INIT_AND_CONNECT)) {
    		/* Do nothing, modem is already turned on
    		 * and connected.
    		 */
    	} else {
    		int err;
    
    		printk("LTE Link Connecting ...\n");
    		err = lte_lc_init_and_connect();
    		__ASSERT(err == 0, "LTE link could not be established.");
    		printk("LTE Link Connected! %d \n", err);
                    return err;
    	}
            return 0;
    }
    
    
    
    int begin_lte_only(){
        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 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 main(void){
           
        begin_lte_only();
        modem_configure();
        
        printk("\nSwapping to GPS\n");
        swap_to_gps_only();
    
        GPS_Init();
        int rv = GPS_Enable();
        if(rv) printk("init_app failure: rv = %d", rv);
        printk("\nGPS Enabled");
        
        k_sleep(K_MSEC(2000));
    
        GPS_Disable();
        printk("\nGPS Disabled");
        swap_to_lte_only();
        modem_configure();
    
        return 0;
    }
    
    
    
    
    
    

    It gives me this output:

    LTE Link Connecting ...                                                         
    LTE Link Connected! -5                                                          
                                                                                    
    Swapping to GPS                                                                 
    Socket created                                                                  
                                                                                    
    GPS Enabled                                                                     
    GPS DisabledLTE Link Connecting ...                                             
    LTE Link Connected! -5                                                          
                                                                                    
                                                                                    
    Ending Program 
    

    Then, after a few seconds:

    +CEREG: 2,"D113","03316803",7                                     
    +CEREG: 5,"D113","03316803",7 
    

    I've tried waiting up to 3 seconds between each call to a series of AT commands and received the same output.

    If I don't call begin_lte_only(), then LTE works the first time.

    Any insight on why I'm still getting this IO error? I probed the GPS MAGPIO pin and it seems to be going high and low at the appropriate times.

Children
  • I think I solved it. By calling lte_lc_offline() (effectively AT+CFUN=4) before modem_configure, I was able to connect to LTE without error. I guess lte_lc_init_and_connect() expects the modem to be in this state before issuing its commands. Comments about this and other quirks in the lte_lc.c file would be nice.

    For others experiencing this, this is now effectively my procedure:

    1. Start Device

    2. AT+CFUN=4, AT%XSYSTEMMODE=1,0,0,0, AT+CFUN=1

    3. lte_lc_offline() (AT+CFUN=4)

    4. modem_configure()

    5. Do LTE stuff

    6. AT+CFUN=4

    7. init_app() as shown in the GPS sample (basically sets up the gps socket and sends "AT+CFUN=4", "AT%XSYSTEMMODE=0,0,1,0", "AT%XMAGPIO=1,0,0,1,1,1574,1577", "AT+CFUN=1")

    8. Do GPS stuff

    9. Disable GPS the way MJD093 does it

    10. Continue

Related