Author Topic: Anyone using the U-BLOX NEO-M9N GPS?  (Read 9887 times)

0 Members and 1 Guest are viewing this topic.

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3671
  • Country: gb
  • Doing electronics since the 1960s...
Anyone using the U-BLOX NEO-M9N GPS?
« on: February 14, 2021, 01:04:06 pm »
I have just started on a project which will probably use this.

Basically I need a WAAS/EGNOS GPS with an SMA passive antenna socket and outputting NMEA. I need to get lat/long, ground speed, track, VDOP, HDOP. At 5Hz.

The manuals e.g. https://www.u-blox.com/en/docs/UBX-19035940 are impenetrable. Half the stuff is defined in terms of the other half... Even working out the defaults is very hard i.e. what actually comes out as default.

I will probably just hook it up to Teraterm and see what comes out...

In the final project I may want to talk to it via SPI - because I am already using SPI for other stuff.

However, the SPI port can run at 5MHz+ and the rate at which one can transfer a new sentence is much higher than over 38k serial, and this fits in a bit better with the RTOS environment I am working with. But there are all sorts of weird limitations on this. There is no message register which you could read out with a single (long) SPI read, by sending e.g. an opcode and then reading N bytes. With SPI, you send it a byte (which is supposed to be 0xff, otherwise the device will try treating it is a config etc byte) and then you read a byte (which arrived in the SPI RX queue as the output byte was being shifted to the device) and that is the next byte in what would have been the serial data stream if you used the UART port. And if there was no data in the queue then you get 0xff. So you run the SPI at whatever speed, transmitting 0xff and if the received byte is 0xff you throw it away. That is their "UART emulation over SPI". Is this correct?

But there are some weird implied limitations on how fast the device can fill its queue. One suggests that if a serial port is set to say 38k, that also limits how fast the SPI can be fed by the device. So you can extract data at ~4k bytes/sec max. That would imply that if using SPI one must either disable serial output, or set the baud rate to the highest value possible. But if a byte gets transmitted over serial, doesn't it disappear from SPI? There is a suggestion that there is only one buffer for all output options. Another limitation says max SPI transfer rate is 150kbytes/sec, which is a lot better than 38kbps.

The docs are written by "documentation purists" :) Their support is nonexistent, except via a forum, where a couple of employees respond, but mostly they just tell you to read the manual. I just want to know how to achieve the above output, and 38k serial will do for a start.

Another thing is that the only sentence I can find which returns both VDOP and HDOP is the UBX-private one 2.8.2 POSITION (PUBX,00). This appears to need polling with a PUBX,00 message without any data fields. But it isn't clear if this needs to be sent each time you want this message to come out. However I also don't want other messages being transmitted because that will make parsing harder. How are they disabled?

And finally I am after the highest precision so may try the config option to extend the number of decimal places. I will be using sscanf() into a double. That's another config but the manual says the command has been deprecated and it lists others which are not obvious to decipher.

Many thanks for any pointers.
« Last Edit: February 14, 2021, 01:08:59 pm by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3671
  • Country: gb
  • Doing electronics since the 1960s...
Re: Anyone using the U-BLOX NEO-M9N GPS?
« Reply #1 on: February 19, 2021, 09:05:11 am »
As an update, I never got any definitive response on how the device actually works w.r.t. running its side of the SPI interface, so I am sticking with serial.

It is a TTL-level (3.3V) inverted serial and with the message choice I am configuring I am seeing 1.4kbytes/sec which is fine for a 38k UART.

SPI would have been really nice if they implemented it properly i.e. have a buffer for the whole "sentence", with a length value, and then one long 5MHz SPI transfer would grab the whole lot. Very efficient all around, not to mention the avoidance of data arriving from a serial port circular queue which then needs to be searched for valid sentence headers etc.
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline tszaboo

  • Super Contributor
  • ***
  • Posts: 7307
  • Country: nl
  • Current job: ATEX product design
Re: Anyone using the U-BLOX NEO-M9N GPS?
« Reply #2 on: February 19, 2021, 09:22:23 am »
If you approach ublox directly, the support is not going to be great. What you need to do, turn to your distributor, and ask them the questions. Basically most companies dont provide direct support, because they dont know if you are just a maker trying to make one device working, or a company that will use millions of their products.
Sometimes it is just easier to implement a product the way the manufacturer meant it to be implemented. For GSM/GPS module that is UART. When you deviate from it, all kind of weird things start to happen, because 90% of their users dont use that interface, and they might not even test those parts properly. What happens is, there is a product manager, and he goes on and lists every possible interface that they can think of, and it doesnt matter how fitting that interface is. They just want to tick checkboxes.
 
The following users thanked this post: cdev

Offline Berni

  • Super Contributor
  • ***
  • Posts: 4922
  • Country: si
Re: Anyone using the U-BLOX NEO-M9N GPS?
« Reply #3 on: February 19, 2021, 10:06:00 am »
Yep as NAND said. Pretty much all GPS receiver modules are designed around using UART to periodically spit out messages with new data. As soon as you start using some other interface you pretty much get that same UART interface wrapped up to fit trough the I2C or SPI or whatever protocol. So what you end up talking to is pretty much a UART to SPI converter block rather than the GPS module itself.

So if you have UART just use that and be done with it.
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3671
  • Country: gb
  • Doing electronics since the 1960s...
Re: Anyone using the U-BLOX NEO-M9N GPS?
« Reply #4 on: February 19, 2021, 03:17:33 pm »
That's my conclusion too.

A pity because SPI is incredibly efficient. I have several SPI devices hanging on one SPI controller and everything runs very fast and very smoothly.

U-BLOX don't support anything but on their forum there is a user there, who may be working for U-BLOX but doesn't say so, who does answer, and I did eventually get the required answers.

I also like posting questions here because they are properly searchable and the answers may help somebody one day.
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline jc101

  • Frequent Contributor
  • **
  • Posts: 613
  • Country: gb
Re: Anyone using the U-BLOX NEO-M9N GPS?
« Reply #5 on: February 19, 2021, 05:23:20 pm »
I've hit a snag with U-Blox of late, the 26 weeks lead time on orders.  All down to a factory fire in Japan last year, apparently.  Check you can actually the modules you want to use.

I have found their Technically Certified Distributor in the UK, Alpha Micro Components Ltd, have been very helpful and answered anything technical I've thrown at them.  Price for modules was very competitive too compared to the main distributors (e.g. Farnell, DigiKey etc.)

https://www.u-blox.com/en/about-us/sales-network-offices/united-kingdom-2
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3671
  • Country: gb
  • Doing electronics since the 1960s...
Re: Anyone using the U-BLOX NEO-M9N GPS?
« Reply #6 on: February 20, 2021, 07:32:24 pm »
Yes; I use that firm for other chips.

The 100+ price is about £10 which is amazing.

Yes the NEO-M9N is on 16wks+ but the modules from e.g. MIKRO-E are apparently available and I suspect I may be using those, at about £30 each.

Mouser are showing 9 wks lead time on it. The module itself is showing delivery August, and 26wks general lead time.

It is a very good GPS. Amazing performance.
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14301
  • Country: fr
Re: Anyone using the U-BLOX NEO-M9N GPS?
« Reply #7 on: February 20, 2021, 08:19:31 pm »
I've used the NEO-M8 module and found its performance extremely good. Even indoors!

Yes most GPS modules are made to spit out data continuously, so a SPI slave interface is often inconvenient. A decent SPI implementation would involve reading registers instead of getting those NMEA sentences, with for instance a register telling you which data is currently available, and then registers to read various data (which upon reading would clear the corresponding flag in the status register so you can know when there's new data and which.) I've rarely seen SPI mode well implemented.

The UART mode requires constantly listening to the UART port and parsing incoming data, properly synchronizing the beginning of new sentences. NMEA is standard and I guess vendors favor sticking to the standard instead of implementing proprietary communication with the modules.
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3671
  • Country: gb
  • Doing electronics since the 1960s...
Re: Anyone using the U-BLOX NEO-M9N GPS?
« Reply #8 on: February 20, 2021, 10:45:15 pm »
SPI would lend itself very well to GPS data, because the GPS would place different sentences (which otherwise it transmits consecutively over the UART) into different buffers, and you could have a "data ready" pin (or just poll status over SPI; I am doing that with one properly implemented chip and the status read takes only 3.5us).

And because you would be collecting linear strings, there would be no need for convoluted code, with timeouts, to get bytes one at a time out of a UART, put them in a buffer, while searching that buffer for different sentence headers concurrently.

The U-BLOX units have the UBX protocol also which is binary and makes things more tricky because any NMEA header could appear within the binary data by accident, so you have to search for the first four bytes of that header and then unpack it appropriately.

I've just spent 2 days doing code to unpack both NMEA (PUBX00 etc) and UBX sentences and I got it to run at 17kbytes/sec which is fine for the task (it is about 10x the data rate coming out of the GPS, running at 38k and with 3 sentences enabled) but for a 168MHz 32F417 it is pretty disappointing. And that is just identifying the packets and placing them into linear buffers from where another RTOS task can pick them up and extract the values with a load of sscanf or similar code. The code is certainly well sub-optimal though :)

I have also just did much the same sort of code for the SPI device and it is far more efficient.

The U-BLOX units do have SPI but because there is no spec on the minimum internal transfer rate, you can't use it sensibly. The best you could do is set it up to grab a byte at say 100kbytes/sec and throw away whatever 0xff bytes turn up. But you can't do that with the UBX protocol which could contain 0xff anywhere :)


Correction: I am getting 835000 bytes/sec. What I was doing earlier was declaring a long array of constants (test data) inside a function instead of outside it, and this stuff had to be initialised each time the function was called!
« Last Edit: February 21, 2021, 09:49:22 pm by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3671
  • Country: gb
  • Doing electronics since the 1960s...
Re: Anyone using the U-BLOX NEO-M9N GPS?
« Reply #9 on: May 04, 2022, 03:25:08 pm »
Getting back to this...

This GPS module has this weird SPI interface which has to be "pumped" i.e. you send it 0xFF bytes and if there is data in the module's TX queue, it returns the data, otherwise it returns an 0xFF.

This would be ok except that some of the data returned is binary and could itself be 0xFF :)

There is an RS232 option but I don't want to use that because it would mess up some other stuff...

There is also an SPI UART: the MAX3107. Not recommended for new designs, and I would prefer to avoid Maxim nowadays. It is also very expensive.

The whole proposition just doesn't sound right. Has anyone dealt with this before?

Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline jc101

  • Frequent Contributor
  • **
  • Posts: 613
  • Country: gb
Re: Anyone using the U-BLOX NEO-M9N GPS?
« Reply #10 on: May 04, 2022, 03:36:28 pm »
Does it not reply with complete data sentences, and as none start with 0xFF you should be able to parse the data?

Though I've not used the SPI interface, just the UART on these modules.
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3671
  • Country: gb
  • Doing electronics since the 1960s...
Re: Anyone using the U-BLOX NEO-M9N GPS?
« Reply #11 on: May 04, 2022, 04:17:23 pm »
There are ASCII packets (which are no problem) and there are binary packets (which I think are a problem) and I am using one of these. This is the one:



I immediately see that within the first four bytes there could be an 0xFF by accident. And there are loads of other bytes, some of which clearly can't be but others are bit fields and probably could be.

So, yes, if you throw away every 0xFF, you can detect the start of this packet easily enough, but probably not the rest.

So this protocol appears impossible to deal with if the SPI can return 0xFF at any point. I cannot see any way to determine whether a given 0xFF could be thrown away, if you are getting bytes which could contain 0xFF :)

Therefore, I suspect the answer to this lies in running the SPI at a specific speed: slower than the serial baud rate selected, because the SPI is probably just tacked-on to the end of the UART. The default baud rate is 38400 and I am running the module over serial at that speed. So running SPI with say a 30kHz clock might well prevent the underrun condition once you have detected that packet (B5 62 01 35). The problem is that if you run the SPI at 35kHz all the time you will obviously get an overrun unless the module has a big enough transmit buffer.

I am running the module at 5Hz (with the binary packet within that at 1Hz) and looking at the output (Teraterm) at 38400 there are large gaps in the returned data. At a wild guess 20-50% of the time there is no data coming out. The SPI will return large sections of 0xFF bytes during these gaps, and then when the real data starts, the SPI might not return any FFs assuming each packet is solid with no gaps.
There is a curious spec limiting the SPI to 150kHz but that might be unrelated.

It just seems really weird.

I can avoid using the non-ASCII packet in a part of my application (for example extracting basic date/time/lat/long can be done with just the G*RMC packet) but not in another.
« Last Edit: May 04, 2022, 04:19:36 pm by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline jc101

  • Frequent Contributor
  • **
  • Posts: 613
  • Country: gb
Re: Anyone using the U-BLOX NEO-M9N GPS?
« Reply #12 on: May 04, 2022, 05:18:45 pm »
I have a small state machine that decodes the inbound data, so I'd know if I was inside a packet or not.  It's actually a FreeRTOS task that is sent the data as it is received.  This looks for the start of frame, and then decodes the packet once a fully formed packet is received.  If an 0xFF were received outside of a packet being received then it would just be ignored, if it were part of the payload of a packet it will be stored ready for decoding.

All the packets have a start of frame of 0xb5 0x62 for the UBX, the packet length encoded in the header, so I know what to expect.  Once the right number of bytes is received and the checksum is correct, the packet is then decoded.  The data is received into a union of the various packets I am interested in (the UBX protocol is designed for this, as covered in 32.3 in the protocol description).

These snippets should give you a gist of how I went about it, been working fine for me, this this was for UART data but it should be tweakable for SPI data too.

I also turn off any data I'm not interested in receiving, so there is less data to be thrown around.

Code: [Select]
    typedef struct {

        union {
            uint16_t classID;

            struct {
                uint8_t ID : 8;
                uint8_t class : 8;
            };
        };
        uint16_t length;
        uint8_t chk_a;
        uint8_t chk_b;
    } UBX_HEADER_t;

    typedef struct {
        uint8_t cldID;
        uint8_t nsgID;
    } UBX_ACK_ACK_t;

    typedef struct {
        uint32_t iTOW;
        uint16_t year;
        uint8_t month;
        uint8_t day;
        uint8_t hour;
        uint8_t min;
        uint8_t sec;
        uint8_t valid;
        uint32_t tAcc;
        int32_t nano;
        uint8_t fixType;
        uint8_t flags;
        uint8_t flags2;
        uint8_t numSV;
        int32_t lon;
        int32_t lat;
        int32_t height;
        int32_t hMSL;
        uint32_t hAcc;
        uint32_t vAcc;
        int32_t velN;
        int32_t velE;
        int32_t velD;
        int32_t gSpeed;
        int32_t headMot;
        uint32_t sAcc;
        uint32_t headAcc;
        uint16_t pDOP;
        uint8_t flags3;
        uint8_t reserved1[5];
        int32_t headVeh;
        int16_t magDec;
        uint16_t magAcc;
    } UBX_NAV_PVT_t;

    typedef struct {
        uint8_t tpIdx;
        uint8_t version;
        uint8_t reserved1[2];
        int16_t antCableDelay;
        int16_t rfGroupDelay;
        uint32_t freqPeriod;
        uint32_t freqPeriodLock;
        uint32_t pulseLenRatio;
        uint32_t pulseLenRatioLock;
        int32_t userConfigDelay;
        uint32_t flags;
    } UBX_CFG_TP5_t;

    typedef union {
        uint8_t payload[UBX_MAX_PAYLOAD_SIZE];
        UBX_NAV_PVT_t nav_pt;
        UBX_ACK_ACK_t ack;
        UBX_ACK_ACK_t nack;
        UBX_CFG_TP5_t cfg_tp5;
    } UBX_PAYLOAD_t;

    typedef struct {
        UBX_HEADER_t header;
        UBX_PAYLOAD_t payload;
    } UBX_t;

void gpsDataRXTask( void* p_arg ) {
    vPortTaskUsesFPU( ); // Inform FreeRTOS task makes use of FPU

    typedef enum {
        UBX_SYNC_1 = 0,
        UBX_SYNC_2,
        UBX_CLASS,
        UBX_ID,
        UBX_LEN1,
        UBX_LEN2,
        UBX_PAYLOAD,
        UBX_CHK1,
        UBX_CHK2,
        UBX_FINISHED
    } UBX_PARSE_STATE_t;

    UBX_PARSE_STATE_t ubx_state = UBX_SYNC_1;
    uint32_t payload_counter = 0;
    UBX_t ubx_packet;
    uint8_t rx_data;

    while ( 1 ) {
        xStreamBufferReceive( gps_data.gps_rx_stream_buffer, &rx_data, 1, portMAX_DELAY );

        switch ( ubx_state ) {
            case UBX_SYNC_1:
                if ( rx_data == UBX_SYNC_CHAR_1 ) {
                    ubx_state = UBX_SYNC_2;
                }
                break;
            case UBX_SYNC_2:
                if ( rx_data == UBX_SYNC_CHAR_2 ) {
                    ubx_state = UBX_CLASS;
                } else {
                    ubx_state = UBX_SYNC_1;
                }
                break;
            case UBX_CLASS:
                ubx_packet.header.class = rx_data;
                ubx_state = UBX_ID;
                break;
            case UBX_ID:
                ubx_packet.header.ID = rx_data;
                ubx_state = UBX_LEN1;
                break;
            case UBX_LEN1:
                ubx_packet.header.length = rx_data;
                ubx_state = UBX_LEN2;
                break;
            case UBX_LEN2:
                ubx_packet.header.length += (rx_data << 8);
                payload_counter = 0;
                ubx_state = UBX_PAYLOAD;
                break;
            case UBX_PAYLOAD:
                if ( payload_counter < ubx_packet.header.length ) {
                    ubx_packet.payload.payload[payload_counter] = rx_data;
                    if ( ++payload_counter == ubx_packet.header.length ) {
                        ubx_state = UBX_CHK1;
                    }
                }
                break;
            case UBX_CHK1:
                ubx_packet.header.chk_a = rx_data;
                ubx_state = UBX_CHK2;
                break;
            case UBX_CHK2:
                ubx_packet.header.chk_b = rx_data;
                if ( ubxChecksum( &ubx_packet ) ) {
                    ubx_state = UBX_FINISHED;
                } else {
                    ubx_state = UBX_SYNC_1;
                }
                break;
            default:
                break;
        }
        if ( ubx_state == UBX_FINISHED ) {
            UBXPacketDecoder( &ubx_packet );
            memset( &ubx_packet, 0x00, sizeof (ubx_packet) );
            ubx_state = UBX_SYNC_1;
        }
    }
}



I can then just decode the packets like this snippet.

Code: [Select]
void UBXPacketDecoder( UBX_t * ubx ) {
    switch ( ubx->header.classID ) {
        case UBX_NAV_PVT:
            gps_record.latitude = (double) ubx->payload.nav_pt.lat * UBX_NAV_PVT_LAT_LON_SCALING;
            gps_record.longitude = (double) ubx->payload.nav_pt.lon * UBX_NAV_PVT_LAT_LON_SCALING;
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3671
  • Country: gb
  • Doing electronics since the 1960s...
Re: Anyone using the U-BLOX NEO-M9N GPS?
« Reply #13 on: May 04, 2022, 07:07:44 pm »
We must have wires crossed :)

I am doing the same as you - well same idea. This is easy with serial (UART). And it works 100% perfectly.

The SPI interface works differently. See my #1 post in this thread. To receive data, you have to "pump" the module for data. You transmit 0xFF bytes out of SPI TX, and then you look at the SPI RX byte (with SPI, for each TX byte you always get one back, every 8 clocks). But since there is no way of knowing if the module has any data to actually give you, it returns 0xFF if it didn't. So you have to throw these FFs away.

This is fine for ASCII data.

But here, let's say you get B5 62 01 35. You know you have the start of that packet. Next byte is the "8-numsvs-12" which probably cannot be an FF, so you can chuck away any FF you see. Then what about the next four? They can be FFs. So you can't throw away FFs there.

The only way I can see of decoding this sh*t protocol is to load the whole lot into a buffer including the FFs. You may need a big buffer if your SPI speed is a lot more than the generated data :) And then compute the checksum, which will obviously be wrong, due to the extra FFs. Then remove the FFs one by one until the checksum works out. This is ridiculous!

Speculative checksumming is done with protocols where the end of a variable length packet is defined with a timeout only, and there you receive bytes into a buffer and after each byte you check if the last byte or two are a valid checksum or CRC.

Unless I am missing something obvious, but I can't see what.
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline jc101

  • Frequent Contributor
  • **
  • Posts: 613
  • Country: gb
Re: Anyone using the U-BLOX NEO-M9N GPS?
« Reply #14 on: May 04, 2022, 07:35:46 pm »
The UBX protocol gives you the length of the payload excluding the checksum.  So you know how many bytes to expect back, so you can keep track.

You are sending a stream of 0xFF out, and getting data back (be that actual data or an 0xFF no data), once you find the start of the frame and know the payload length, you will know if any 0xFF received is part of a packet or not.  You will have to build a buffer of at least 1 packet's worth of data, sized to the largest expected packet size.  Maybe a few of them depending on how fast you need the data.

For the 8 + 12 * numSvs, this size will tell you how many SV's records worth of data to expect.  If there are 8 SV's worth of data the payload 104 bytes, as 8 + ( 12 * 8 ) is 104 {0x00 0x67}, plus the checksum bytes at the end.  To me it reads as just the same as data via UART, but you have to send an 0xFF out to get a byte back.  You have to track if you are mid packet or not because of the null 0xFF returned if there is no data available.

So, in your example...

0xb5 0x62 0x01 0x35 0x00 0x67 {payload of 104 bytes} {checksum A} {checksum B}

Any 0xFF received outside of the detected start of frame, and the expected payload length + checksum data can be discarded.

There must be a maximum number of SV's can be returned per GNSS system, so you can size the buffer accordingly.

Unless I'm missing something here too!

edit: This assumes that when you send the 0xFF's out the module returned whole frames of data without random 0xFF's sprinkled through them, which I can't see be the case from the protocol specification.  Once a frame has started being sent it will be completed and the 0xFF's return once the whole frame has been sent.  I don't have a module here with an SPI interface to test this though...
« Last Edit: May 04, 2022, 07:46:57 pm by jc101 »
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3671
  • Country: gb
  • Doing electronics since the 1960s...
Re: Anyone using the U-BLOX NEO-M9N GPS?
« Reply #15 on: May 04, 2022, 08:03:57 pm »
Quote
you will know if any 0xFF received is part of a packet or not

No you won't :)

Quote
Unless I'm missing something here too!

I am sure one of us is.

Quote
This assumes that when you send the 0xFF's out the module returned whole frames of data without random 0xFF's sprinkled through them

I think that assumption is wrong unless the SPI speed is carefully adjusted to not be too high. IOW, the documentation is crap.

Quote
Once a frame has started being sent it will be completed and the 0xFF's return once the whole frame has been sent.

I agree here. Which takes me to what I said above. There is a key bit of info missing: the SPI clock speed.

There will be a minimum speed and a maximum speed.

If the clock is too slow then you won't be extracting the data fast enough. At 5Hz, the GPS is generating of the order of 2kbytes/sec (I could check exactly but that would be right only for my particular GPS config; I have set it up to emit only required packets). At 38400 baud I do see gaps, but at 5Hz GPS they are obviously shorter than 200ms. So a 20kHz SPI clock would be the minimum.

If the clock is too fast, then you will get FFs within a packet.

The docs say bugger-all on this. Indirectly, there is this



It is possible the 125k/sec SPI byte rate is intended to mean that if you do that, you won't see any FFs within a packet, which AIUI is crucial to the protocol working. But nowhere I know of does it say that.

« Last Edit: May 04, 2022, 08:27:18 pm by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline jc101

  • Frequent Contributor
  • **
  • Posts: 613
  • Country: gb
Re: Anyone using the U-BLOX NEO-M9N GPS?
« Reply #16 on: May 04, 2022, 08:23:57 pm »
Ah, I see.

I can't see the SPI as being too fast as a problem, as the module will only start to send a frame if there is a whole frame ready to be sent.  My concern would be too low an SPI speed and some data could be missed, as there would be insufficient internal buffer space to hold the frames.

I'd give a test with a high SPI speed, and debug by counting how many check sum errors you get, which will show if there are any malformed packets received as a result.

It's a bit like turning on lots of messages and using a UART speed too low to get all the data out in time.  You will never see any malformed packets, as the module will just throw away the data it cannot send when the internal buffer overruns.

The only way to know for sure is to ask U-Blox, drop a line to Alpha Micro ( https://alphamicro.net ) who are the UK U-Blox tech people, they can raise the question directly with U-Blox.  I've bought modules from them before for a fraction of the price you get them from Farnell, Mouser etc. too.  They are normally very responsive.

Edit: The alternative is to use the TX_Ready pin and idle reading data until that is asserted, then once you receive a stream of 0xff's idle until the TX_ready asserts again.
« Last Edit: May 04, 2022, 08:34:02 pm by jc101 »
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3671
  • Country: gb
  • Doing electronics since the 1960s...
Re: Anyone using the U-BLOX NEO-M9N GPS?
« Reply #17 on: May 04, 2022, 08:35:34 pm »
My take on this is that the 125k bytes/sec limit is set by how fast the CPU can service interrupts, moving bytes from the buffers to the SPI TX. If this requirement is met, then there will be no underrun, because the CPU has already laid out the packet(s) in the buffers.

I posted this Q on the U-BLOX forum, here
https://portal.u-blox.com/s/question/0D72p000009bAGVCA2/detail?s1oid=00D200000001ogf&t=1651691683831&s1nid=0DB2p0000008PMD&emkind=chatterCommentNotification&s1uid=0052p00000AKKM8&emtm=1651683154013&fromEmail=1&s1ext=0
and while nobody there actually knows, the speculation is that there is a buffer for each packet type. So once you have seen the header of a packet, there should be no underrun (no FFs returned) for the rest of that packet.

But the doc doesn't say that :)

It seems obvious that the SPI is extremely primitive. Just a 1 byte buffer, loaded by an ISR, hence the 8us/byte speed limit.

If you were doing this properly, you would lay out the whole packet in a buffer and then SPI could fetch this at the max SPI clock speed (5.5MHz in this case). But this module was designed for the UART, and SPI was just tacked on.

I will email Alphamicro; I buy from them.

EDIT: that thread I started on the u-blox forum ended up being completely ridiculous.

Grampy, who must be an OSI 127 layer protocol specialist, in between teaching me that an octet is a byte ;) ended up basically agreeing that if the SPI clock is faster than some value (which by over-interpreting the data sheet seems to be 1MHz) then you will be getting 0xFF bytes received within a packet and then the binary protocol is impossible to decode (as I've been saying all along).

And Clive (who is a really clever guy and knows these modules in huge detail) stopped disagreeing with the above and moved to telling me that getting the data out too slowly results in a latency in time+position. That is obviously true but actually running this over SPI at 125kbytes/sec (1MHz SPI clock) is still vastly faster than running it via the UART at 38400 baud, and still about 9 x faster than running it at 115200 baud.

So SPI is well worth getting going.

My current RTOS GPS thread polls the UART to see if there is any RX data (if not, it yields to the RTOS) and processes that with a state machine. So in this case instead of polling the UART I will continually transmit 0xFFs, with a 1MHz SPI clock, chuck away any 0xFFs received, and process the other bytes exactly as I have been doing :)
« Last Edit: May 05, 2022, 06:15:56 am by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline thinkfat

  • Supporter
  • ****
  • Posts: 2150
  • Country: de
  • This is just a hobby I spend too much time on.
    • Matthias' Hackerstübchen
Re: Anyone using the U-BLOX NEO-M9N GPS?
« Reply #18 on: May 05, 2022, 09:09:05 am »
That is really a peculiar behavior. I'd never have thought of an implementation quirk like that. I've been using UART all along with the Ublox modules. Behavior like that makes me not wanting to use SPI. Have you ever actually witnessed Tx underruns? The advice to switch off unused interfaces to make more space for buffering sounded reasonable to me.
Everybody likes gadgets. Until they try to make them.
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3671
  • Country: gb
  • Doing electronics since the 1960s...
Re: Anyone using the U-BLOX NEO-M9N GPS?
« Reply #19 on: May 05, 2022, 10:55:36 am »
I think they just tried to save silicon, so they implemented a 1-byte SPI, serviced with an interrupt from the NMEA etc packet buffers, exactly the same as they service the UART with an interrupt, and probably the same is used for the I2C port.

The 125kbyte/sec SPI rate limit suggests they want 8us for the ISR execution.

That would also limit the UART to about 1mbps, but with a UART it doesn't matter anyway because it syncs on each byte (NRZ, start bit, etc). SPI is master-slave and has to be polled by the host (the master) and the slave has no way to slow the master down, hence the possibility of an underrun.

The proper way would be to service the SPI with DMA, not an ISR, and then you could retrieve data from the GPS at the full SPI speed, which the data sheet says is 5.5MHz clock (which is reasonable, on the landscape of SPI chips). And have a register with a byte count somewhere, perhaps at the start of the buffer, so you would read 2 bytes with SPI, and then do an SPI block transfer of the rest (a few k bytes). But that is more work, plus you won't have a byte count until all the configured packets have been generated, and if some are set for 5Hz and some for 1Hz then you could have stuff coming out at all different times... so I can see why they just did a "one byte at a time" SPI which works same as a UART. But because there is no start bit sync, there is the possibility of an overrun, on which they return 0xFF. The data sheet should actually say this...
« Last Edit: May 05, 2022, 11:13:14 am by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3671
  • Country: gb
  • Doing electronics since the 1960s...
Re: Anyone using the U-BLOX NEO-M9N GPS?
« Reply #20 on: May 05, 2022, 07:53:26 pm »
Today I designed a board with this GPS module on it, with an SPI interface, and I will try it with a 1MHz SPI clock - 125kbytes/sec as per the data sheet. I have error counters on all the packets which can be watched.

I had a bit of fun working out the FR4 PCB track with for a 50 ohm trace. There are 100 search hits and most of them differ :) I am using a 1.6mm 4 layer PCB and the trace is on the outside. I made the trace 0.012". There are other values (much wider) mentioned if one pours a ground plane around the trace, which I can do also.

It sounds like the outside FR4 layers are 0.2mm thick.
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline jc101

  • Frequent Contributor
  • **
  • Posts: 613
  • Country: gb
Re: Anyone using the U-BLOX NEO-M9N GPS?
« Reply #21 on: May 05, 2022, 07:58:54 pm »
If your CAD package doesn’t easily do impedance controlled traces, download the free Saturn PCB toolkit.  Fill in the details of the PCB stack up etc. and the answer pops out. Never let me down yet.
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3671
  • Country: gb
  • Doing electronics since the 1960s...
Re: Anyone using the U-BLOX NEO-M9N GPS?
« Reply #22 on: May 05, 2022, 08:39:32 pm »
My CAD package is Protel PCB 2.8 from 1995 :)

This one works ok
https://www.pcbway.com/pcb_prototype/impedance_calculator.html
« Last Edit: May 05, 2022, 08:46:28 pm by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 
The following users thanked this post: jc101

Offline thinkfat

  • Supporter
  • ****
  • Posts: 2150
  • Country: de
  • This is just a hobby I spend too much time on.
    • Matthias' Hackerstübchen
Re: Anyone using the U-BLOX NEO-M9N GPS?
« Reply #23 on: May 05, 2022, 08:43:46 pm »
Today I designed a board with this GPS module on it, with an SPI interface, and I will try it with a 1MHz SPI clock - 125kbytes/sec as per the data sheet. I have error counters on all the packets which can be watched.

I had a bit of fun working out the FR4 PCB track with for a 50 ohm trace. There are 100 search hits and most of them differ :) I am using a 1.6mm 4 layer PCB and the trace is on the outside. I made the trace 0.012". There are other values (much wider) mentioned if one pours a ground plane around the trace, which I can do also.

It sounds like the outside FR4 layers are 0.2mm thick.

The tracewidth depends on many things. \$\epsilon_r\$ and the thickness of the dielectric is one, but vicinity of a ground pour on the same layer plays an important role. If you calculate the tracewidth for a microstrip line, make sure you have ample spacing to the ground pour. If the gap is too close, your microstrip becomes a G-CPW and a different mode of transmission becomes dominant, and thus a different width must be used. I'd try to avoid CPWs. They're finicky towards surface quality as the e-field propagates mostly "above" the signal trace, which makes the launch more peculiar. Edge connectors are a must.

If you're unsure, and if you have access to a VNA or at least spectrum analyzer with tracking generator, make a measurement. Terminate the line at the module pads with a 50 \$\Omega\$ resistor, mount the antenna connector and measure "into" the board. That'll give you an idea. 1.5GHz is not too critical, though. No need to fuzz about the layout too long.
Everybody likes gadgets. Until they try to make them.
 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 26755
  • Country: nl
    • NCT Developments
Re: Anyone using the U-BLOX NEO-M9N GPS?
« Reply #24 on: May 05, 2022, 08:43:52 pm »
For a 1MHz clock the trace impedance doesn't matter at all so don't bother. Using 33 Ohms series resistors on the pins that drive the SPI bus is a good idea to reduce emissions. If SPI fails then it is likely a problem with clock polarity. For example: sending data on the rising edge of the clock when the receiver is sampling on the rising edge of the clock is asking for flaky operation.

BTW: I didn't had much luck trying to use a uBlox M8 (whatever) module at other update rates than 1Hz.
« Last Edit: May 05, 2022, 08:48:17 pm by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf