u-blox / ubxlib

Portable C libraries which provide APIs to build applications with u-blox products and services. Delivered as add-on to existing microcontroller and RTOS SDKs.
Apache License 2.0
303 stars 92 forks source link

capture all UBX data from GNSS module #205

Closed mabroens closed 6 months ago

mabroens commented 7 months ago

Hi Rob,

for my validation i woul dlike to printout all data in UBX format and prpint that to the console of my app. im using zephyer and for NMEA this is working but ubx format should give me more information on SNR and spectrum analyser stuff.

i started by using your code example: dec_main.c and was able to get that to work. it nicely prints:

Setting module type to M10
U_GNSS: initialising with ENABLE_POWER pin not connected, transport type UART.
U_GNSS: sent command b5 62 0a 06 00 00 10 3a.
U_GNSS: decoded UBX response 0x0a 0x06: 00 00 00 00 00 00 00 00 00 00 00 00 00 0 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00[body 120 byte(s)].
U_GNSS: sent command b5 62 06 04 04 00 00 00 09 00 17 76.
U_GNSS: sent command b5 62 0a 06 00 00 10 3a.
U_GNSS: decoded UBX response 0x0a 0x06: 00 00 00 00 00 00 00 00 00 00 00 00 00 0 00 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00[body 120 byte(s)].
Device opened successfull.
U_GNSS: sent command b5 62 06 8a 09 00 01 01 00 00 07 00 91 20 01 54 51.
U_GNSS: decoded UBX response 0x05 0x01: 06 8a [body 2 byte(s)].
UTC time 1708697665000002466 nanoseconds.
UTC time 1708697668000003683 nanoseconds.
UTC time 1708697669000004087 nanoseconds.
UTC time 1708697669999800621 nanoseconds.
UTC time 1708697670999800997 nanoseconds.
UTC time 1708697671999801372 nanoseconds.
UTC time 1708697672999801748 nanoseconds.
UTC time 1708697673999802122 nanoseconds.
UTC time 1708697674999802497 nanoseconds.
UTC time 1708697675999802870 nanoseconds.
UTC time 1708697676999803243 nanoseconds.
UTC time 1708697677999803616 nanoseconds.
UTC time 1708697678999803990 nanoseconds.
13 UBX-NAV-PVT message(s) decoded.
Done.

but i would like it

  1. to be streaming until i poweroff
  2. to not only get PVT msg but all.

for 2) i changed: messageId.id.ubx = 0x0107; // The message class/ID of a UBX-NAV-PVT message to: messageId.id.ubx = U_GNSS_UBX_MESSAGE_ALL; // for all UBX format messages

but i think i still only get PVT out. atleast when i seta breakpoint in the callback and watch pDec. image

am i missing something? and what is the best way to print the ubx to console such that u-Center will eat it?

Br Martijn

mabroens commented 7 months ago

and is there a function that decodes the pvt content to human readebl for printing to log file?

mabroens commented 7 months ago

ok the streaming was easy. i forgot to place the while (1) :-(.

RobMeades commented 7 months ago

Hi again Martijn: the ubxlib code will only print out messages that the GNSS chip sends it and, by default, I don't believe any of the UBX messages are enabled in the GNSS chip. The messages can be large and there are many of them; you will likely find that enabling all of them will lead to character loss on the communications link.

Which GNSS chip is this with? The mechanism to enable the messages is different depending on whether you are using series 8, 9 or 10.

mabroens commented 7 months ago

Hi again :-),

Fair point Rob, im using the M10. but i think the pvt is enough. but i'll ask my FAE for this.I will also have a look at the EVK as ther i can see the spectrum analyser work.

RobMeades commented 7 months ago

OK, so for M10 when you're talking over UART, to enable a given UBX message you'd use the pattern:

U_GNSS_CFG_SET_VAL_RAM(devHandle, MSGOUT_UBX_NAV_PVT_UART1_U1, 1)

...where you would replace the UBX_NAV_PVT part with the UBX message type you want, see the list in u_gnss_cfg_val_key.h.

As to printing out messages so that u-Center will eat them, I'm not actually a u-Center user myself, so I don't even know what the format is! I guess such a thing could be provided though, I can put it on the list - how soon do you need it?

mabroens commented 7 months ago

cool thankx this will already help me out. let me try before you need to do anything. and same here no idea what data uBlox unit spits out in UBX format. when i connect to the EVK i can see non human readable data. need to dive into this. but the goals is that.

other question where can i find more information on the MSGOUT types mentioned in see the list in u_gnss_cfg_val_key.h. ?

and if i would like the datarate to be 10Hz what should i do? uGnssCfgSetMsgRate(devHandle, &messageId, 10) or is there another function to do so?

RobMeades commented 7 months ago

They are listed in section 4.9.11 of the M10 interface manual but it doesn't say much more there: enable the given message at the given rate.

uGnssCfgSetMsgRate() only works for M8 and M9 modules, for M10 modules you just set the number at the end of the U_GNSS_CFG_SET_VAL_RAM() macro; for 10 Hertz put 10 in there but be warned, 10 Hertz is quite a high rate for a 9600 bits/s UART interface and, if your measurement epoch is still 1 second it won't be giving you navigation solutions any more quickly.

mabroens commented 7 months ago

hi Rob,

again thnks for the feedback.

my M10 is running at 38400 so that should be fine. this speed is btw the def for the chip. perhaps that the modules use 9600 but the chip itself is using 38400.

and yes the epcoch need to look into that one. not fam. with it yet.

i'll dive into that. thx

mabroens commented 7 months ago

@RobMeades

As to printing out messages so that u-Center will eat them, I'm not actually a u-Center user myself, so I don't even know what the format is! I guess such a thing could be provided though, I can put it on the list - how soon do you need it?

Would it be possible for you give this a try? i could not get any further then printing the decoded msg.

this is what i did so far:

static void callback(uDeviceHandle_t devHandle, const uGnssMessageId_t *pMessageId,
                     int32_t errorCodeOrLength, void *pCallbackParam)
{
    char *pBuffer = (char *) pCallbackParam;
    int32_t length;
    uGnssDec_t *pDec;
    char prefix[2] = {0};
    int32_t whole[2] = {0};
    int32_t fraction[2] = {0};

#ifndef U_CFG_TEST_USING_NRF5SDK
    uGnssDecUbxNavPvt_t *pUbxNavPvt;
    int64_t utcTimeNanoseconds;
#endif

    (void) pMessageId;

    if (errorCodeOrLength >= 0) {
        // Read the message into our buffer
        length = uGnssMsgReceiveCallbackRead(devHandle, pBuffer, errorCodeOrLength);
        if (length >= 0) {
            // Call the uGnssDec() API to decode the message
            pDec = pUGnssDecAlloc(pBuffer, length);
            if ((pDec != NULL) && (pDec->errorCode == 0)) {
                gDecCount++;
                // No need to check pDec->id (or pMessageId) here since we have
                // only asked for UBX-NAV-PVT messages.
#ifndef U_CFG_TEST_USING_NRF5SDK // NRF52 goes a bit crazy if you print here
                pUbxNavPvt = &(pDec->pBody->ubxNavPvt);
                // Do stuff with the contents
                utcTimeNanoseconds = uGnssDecUbxNavPvtGetTimeUtc(pUbxNavPvt);
                prefix[0] = latLongToBits(pUbxNavPvt->lon, &(whole[0]), &(fraction[0]));
                prefix[1] = latLongToBits(pUbxNavPvt->lat, &(whole[1]), &(fraction[1]));

                if (utcTimeNanoseconds >= 0) {
                    // This print will only do anything useful if you have
                    // a uPortLog() which supports 64-bit integers
                    // uPortLog("UTC time %lld nanoseconds.\n", utcTimeNanoseconds);

                   // Here we should just print teh binary data such that uCentre understands it.
                    printf("lon: %c%d.%07d, lat %c%d.%07d fixType: %dD, pDOP:%d, sAcc:%dm, vAcc:%dm\n",prefix[1], whole[1], fraction[1], prefix[0], whole[0], fraction[0], pUbxNavPvt->fixType, pUbxNavPvt->pDOP, pUbxNavPvt->sAcc,pUbxNavPvt->vAcc);
                } else {
                    uPortLog("UTC time not available.\n");
                }
#endif
            }
            // Must *always* free the memory that pUGnssDecAlloc() allocated
            uGnssDecFree(pDec);
        }
#ifndef U_CFG_TEST_USING_NRF5SDK // NRF52 goes a bit crazy if you print here
    } else {
        uPortLog("Empty or bad message received.\n");
#endif
    }
}

I was thinking. when i us uCenter to configure the M10 for UBX format then disconnect the uart port and open it with putty i can see binary data. So simply stated i would say when you just print the the binary data that could be a starting point. otherwise it might just be a conversion that needs to be added or is this to simple??

Meanwhile i will also try to figure out if and where i can find information on the ubx format comming from the uBlox devcie.

RobMeades commented 7 months ago

Meanwhile i will also try to figure out if and where i can find information on the ubx format comming from the uBlox devcie.

The UBX-format messages are all defined in the interface manual, section 3.

I will capture a u-center log from a device and see what it looks like: if it is similar to the .ucf format then it would appear to be some form of JSON, should be easy enough to print that out.

RobMeades commented 7 months ago

Find here:

https://github.com/u-blox/ubxlib/tree/preview_feature_gnss_ucenter_script_rmea

...a preview branch which contains a Python (3) script u_gnss_create_ucenter_ubx_file.py which will take the ubxlib log output, find all of the UBX message exchanges in it and write these to a file which the u-blox uCenter tool can open.

For instance, cut and paste any log output you have into a file log.txt and run the script with:

python u_gnss_create_ucenter_ubx_file.py log.txt log

...then open log.ubx in uCenter. By default it will include commands sent to the GNSS device as well as the responses: add the command-line switch -r to include only the responses.

Give it a try and let me know if it works for you, all feedback welcomed. When you are satisfied I will push it to master here and delete the preview branch.

RobMeades commented 6 months ago

Hi again Martijn. Further to our discussion I've updated the script on the preview branch, script now renamed to u_gnss_ucenter_ubx.py ('cos it doesn't just do files anymore), so that it can also be given a serial device as input, instead of a saved file, and, on Linux, it can write its output to a pty (note: it needs an installation of the Python module pyserial to do this (pip3 install pyserial); DO MAKE SURE you install pyserial; the similarly named Python module serial will not work, it will cause a Python run-time error: pip3 install -r <ubxlib_dir>/gnss/api/requirements.txt should also do it); run the script with -h for help.

The problem, of course, is that Python only allows the creation of virtual serial ports (the pty) on Linux, there is no way to do this on Windows, and uCenter is a Windows application. So if you have no way to connect your uCenter installation across to a Linux pty, the script also allows the output to be an existing serial port (on Windows or Linux). For this to be useful you would need to install com0com on Windows (or you could use socat on Linux) to create a looped-back pair of COM ports. Then you can specify one end of a com0com looped-back serial port as the destination for the script output and connect uCenter on Windows to the other end of that com0com looped-back serial port. I have heard of some people having problems getting com0com running (it seems to work for me here); there is also Eltima's Virtual Serial Port, which we use inside the ubxlib test system when testing our Windows UART drivers, but that costs money.

Example: to read ubxlib log output from COM1, extract the UBX messages from it and write these messages to COM10 (which is the thing that must be one end of a com0com looped-back serial port) in a form that uCenter should be able to read (from the other end of the looped-back serial port), you would do:

python u_gnss_ucenter_ubx.py COM1 COM10

You can add something like -b 38400 on the command-line to specify the baud rate (otherwise 9600 is the default) and -e to cause the script to echo all of the stuff it receives on COM1 to stdout while it is running.

Let me know if this works for you; it seems to work OK here, see below (this just processing a bit of ubxlib log output I happened to have lying around into uCenter via com0com):

image

RobMeades commented 6 months ago

HI Martijn; now that you are, I believe, happily using the script of commit https://github.com/u-blox/ubxlib/commit/ad355d15a67ad2c8bc60b887c08df176cd403917 I will close this issue; feel free to re-open it, or open a new one, if there is more to discuss on this topic.

I will delete the preview branch some time next week.