Perform continuous location tracking with periodic data transmission to server

Hi all,

I am working on an IoT tracking feature that transmits the location every 5/10 seconds. Currently, I tried using a Thingy:91X to get and send the location with the location library every ~30 s and to do continuous tracking every second without transmitting the location.

Target: continuous tracking (every second) and transmitting the location every 5/10 seconds using the same device, such as Thingy:91X

Difficulties: (I guess) LTM transmission preempts GNSS location tracking because of the modem's limitations.

Tried:

1. (with location library) location config set: interval = 5s and timeout = 60s, and submit UDP transmission work after LOCATION_EVT_LOCATION. --> It can get the location every ~30 s and send the location to the server.
2. (with location library) location config set: interval = 5s and timeout = 60s while submitting UDP transmission work with a 10s timer  --> It cannot get the GNSS location because it is interrupted by LTM transmission.
3. (with location library) location config set: interval = 5s and timeout = 60s, and start a 10s timer that submits UDP transmission work after LOCATION_EVT_LOCATION --> It can get the first GNSS location in 30 s but not anymore, as it is interrupted by LTM transmission.

4. (with GNSS library) gets the first GNSS location in 4 minutes and every second afterwards.
5. (with GNSS library) gets the first GNSS location in 4 minutes and sends the location. However, it cannot find the GNSS afterwards.

I considered using 2 Thingy:91X units: one for location tracking and the other for data transmission with a physical/BLE connection. However, this approach may not be accepted, as it doubles the power consumption.

Questions:

How can (/Can) a Thingy:91X perform this feature?

Please let me know if you need more details. Thank you

Parents
  • Hi Charles,

    Yes, this works on a single nRF91 — I have it running on nRF9151 / NCS v3.0.0 with a ~10–12 s GNSS-fix-plus-publish cycle sustained indefinitely. The problem in your attempts 2, 3 and 5 isn't a modem limitation, it's the scheduling model.

    The nRF91 has one RF front end shared between LTE and GNSS. They are time-multiplexed, never simultaneous. Your attempts 2 and 3 run a free-running timer that fires the UDP transmission asynchronously into an open GNSS window. LTE wins the arbitration, the GNSS window is destroyed, and the location request times out. That's exactly the symptom you describe.

    The fix: never let GNSS and LTE run at once. Do them one after the other, in a loop.

    Step 1 — Turn off the location library's own timer

    Change from periodic to single-shot. Keep config at file scope, since Step 4 reuses it:

    static struct location_config config;   /* file scope - Step 4 needs it */
    
    config.interval = 0;                                  /* was 5 */
    config.methods[0].gnss.timeout = 25 * MSEC_PER_SEC;
    config.methods[0].gnss.priority_mode = false;
    location_request(&config);
    

    Step 2 — Delete the transmission timer

    Remove the 10 s k_timer that submits the UDP work. This is what is breaking GNSS. Sends are triggered from Step 4 instead.

    Step 3 — Send only after a fix arrives

    case LOCATION_EVT_LOCATION:
        /* save lat/lon */
        k_work_reschedule(&publish_work, K_NO_WAIT);
        break;
    

    Step 4 — Request the next fix only after the send finishes

    This is the important one. At the end of your publish handler:

    static void publish_work_handler(struct k_work *work)
    {
        send_to_server(...);        /* UDP / MQTT publish */
    
        location_request(&config);  /* re-arm GNSS only now */
    }
    

    The cycle becomes fix → send → fix → send. Only one radio user at a time.

    Step 5 — Enable A-GNSS

    CONFIG_NRF_CLOUD_AGNSS=y
    CONFIG_DATE_TIME=y
    CONFIG_DATE_TIME_MODEM=y
    

    Your 4-minute first fix is a cold start with no assistance data. With A-GNSS it becomes seconds, and every fix after that is a hot start.

    Step 6 — Use the right network mode

    CONFIG_LTE_NETWORK_MODE_LTE_M_NBIOT_GPS=y
    

    Prefer LTE-M over NB-IoT where you have coverage — NB-IoT uplinks take much longer and steal more time from GNSS.

    Step 7 — Turn PSM and eDRX off while tracking

    lte_lc_psm_req(false);
    lte_lc_edrx_req(false);
    

    Gate this on a "tracking active" state and re-enable when idle — it costs real current.

    Step 8 — Open the socket once

    Connect your UDP/MQTT socket once at startup and keep it alive; reconnect only on failure. Connecting per transmission adds seconds of radio time to every cycle, all of it taken from GNSS.

    Let me know if this way works for you, i know another way to do this.

    Thanks and regards

    Nishant

  • Hi Nishant,

    Thank you for the answer and suggestion. That significantly improves performance on attempt 1, which contributes to its acceptance. However, I am afraid that it may not be able to get the location within 5 seconds, as sending the location every 5/10 seconds (depending on the designed modes) is a strict requirement. Therefore, my previous idea is to create two timer threads: UDP and GNSS. It works like this (logic flow only, without hardware limitations): after the first fix, start a UDP timer every 5/10 seconds to send the location, regardless of whether the location is updated, while GNSS continuous tracking still works in the background.

    With the information provided:

    The nRF91 has one RF front end shared between LTE and GNSS. They are time-multiplexed, never simultaneous. Your attempts 2 and 3 run a free-running timer that fires the UDP transmission asynchronously into an open GNSS window. LTE wins the arbitration, the GNSS window is destroyed, and the location request times out. That's exactly the symptom you describe.

    Can the Thingy:91X temporarily stop/close the GNSS window when UDP transmission is in progress, then resume/open it again after the transmission is finished? Or cache the GNSS location data before the transmission and restore it after it?

    New question to shorten the first fix: I believe the library you suggested is location instead of GNSS. I have heard about "location injection" that helps the device to locate the GNSS satellites. I coded it like this in my main.c after initializing the Location library and also after every successful fix:

        /* Inject known coarse location to speed up first cold start */
        struct nrf_modem_gnss_agnss_data_location loc = {0};
        loc.latitude          = my_lat; // xx.xxxx
        loc.longitude         = my_long; // xxx.xxxx
        loc.altitude          = 50;
        loc.unc_semimajor     = 127;
        loc.unc_semiminor     = 127;
        loc.orientation_major = 0;
        loc.unc_altitude      = 255;
        loc.confidence        = 100;

        err = nrf_modem_gnss_agnss_write(&loc, sizeof(loc), NRF_MODEM_GNSS_AGNSS_LOCATION);
        if (err) {
            LOG_WRN("Failed to inject coarse location, err: %d", err);
        }

    Could you tell me if the location injection helps and whether the implementation is correct?

    Thanks and regards

    Charles

Reply
  • Hi Nishant,

    Thank you for the answer and suggestion. That significantly improves performance on attempt 1, which contributes to its acceptance. However, I am afraid that it may not be able to get the location within 5 seconds, as sending the location every 5/10 seconds (depending on the designed modes) is a strict requirement. Therefore, my previous idea is to create two timer threads: UDP and GNSS. It works like this (logic flow only, without hardware limitations): after the first fix, start a UDP timer every 5/10 seconds to send the location, regardless of whether the location is updated, while GNSS continuous tracking still works in the background.

    With the information provided:

    The nRF91 has one RF front end shared between LTE and GNSS. They are time-multiplexed, never simultaneous. Your attempts 2 and 3 run a free-running timer that fires the UDP transmission asynchronously into an open GNSS window. LTE wins the arbitration, the GNSS window is destroyed, and the location request times out. That's exactly the symptom you describe.

    Can the Thingy:91X temporarily stop/close the GNSS window when UDP transmission is in progress, then resume/open it again after the transmission is finished? Or cache the GNSS location data before the transmission and restore it after it?

    New question to shorten the first fix: I believe the library you suggested is location instead of GNSS. I have heard about "location injection" that helps the device to locate the GNSS satellites. I coded it like this in my main.c after initializing the Location library and also after every successful fix:

        /* Inject known coarse location to speed up first cold start */
        struct nrf_modem_gnss_agnss_data_location loc = {0};
        loc.latitude          = my_lat; // xx.xxxx
        loc.longitude         = my_long; // xxx.xxxx
        loc.altitude          = 50;
        loc.unc_semimajor     = 127;
        loc.unc_semiminor     = 127;
        loc.orientation_major = 0;
        loc.unc_altitude      = 255;
        loc.confidence        = 100;

        err = nrf_modem_gnss_agnss_write(&loc, sizeof(loc), NRF_MODEM_GNSS_AGNSS_LOCATION);
        if (err) {
            LOG_WRN("Failed to inject coarse location, err: %d", err);
        }

    Could you tell me if the location injection helps and whether the implementation is correct?

    Thanks and regards

    Charles

Children
No Data
Related