Anyone using the U-BLOX NEO-M9N GPS? - Page 1
Forum section: electronics / projects

author: peter-h
author_rank: Super Contributor
timestamp: February 14, 2021, 01:04:06 pm
content: 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-19035940are 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.

author: peter-h
author_rank: Super Contributor
timestamp: February 19, 2021, 09:05:11 am
content: 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.

author: tszaboo
author_rank: Super Contributor
timestamp: February 19, 2021, 09:22:23 am
content: 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.

author: Berni
author_rank: Super Contributor
timestamp: February 19, 2021, 10:06:00 am
content: 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.

author: peter-h
author_rank: Super Contributor
timestamp: February 19, 2021, 03:17:33 pm
content: 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.

author: jc101
author_rank: Frequent Contributor
timestamp: February 19, 2021, 05:23:20 pm
content: 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

author: peter-h
author_rank: Super Contributor
timestamp: February 20, 2021, 07:32:24 pm
content: 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 averygood GPS. Amazing performance.

author: SiliconWizard
author_rank: Super Contributor
timestamp: February 20, 2021, 08:19:31 pm
content: 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.

author: peter-h
author_rank: Super Contributor
timestamp: February 20, 2021, 10:45:15 pm
content: 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 thoughI 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 anywhereCorrection: 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!

author: peter-h
author_rank: Super Contributor
timestamp: May 04, 2022, 03:25:08 pm
content: 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 0xFFThere 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?

author: jc101
author_rank: Frequent Contributor
timestamp: May 04, 2022, 03:36:28 pm
content: 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.

author: peter-h
author_rank: Super Contributor
timestamp: May 04, 2022, 04:17:23 pm
content: 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 0xFFTherefore, 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 overserialat 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 35kHzall the timeyou 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 FFsassuming 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.

author: jc101
author_rank: Frequent Contributor
timestamp: May 04, 2022, 05:18:45 pm
content: 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: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;int32_t headVeh;int16_t magDec;uint16_t magAcc;} UBX_NAV_PVT_t;typedef struct {uint8_t tpIdx;uint8_t version;uint8_t reserved1;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_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 FPUtypedef 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 = 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: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;

author: peter-h
author_rank: Super Contributor
timestamp: May 04, 2022, 07:07:44 pm
content: We must have wires crossedI 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 bufferincluding the FFs. You may need a big buffer if your SPI speed is a lot more than the generated dataAnd 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.

author: jc101
author_rank: Frequent Contributor
timestamp: May 04, 2022, 07:35:46 pm
content: 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...

author: peter-h
author_rank: Super Contributor
timestamp: May 04, 2022, 08:03:57 pm
content: QuoteNo you won'tQuoteI am sure one of us is.QuoteI think that assumption is wrongunless the SPI speed is carefully adjusted to not be too high. IOW, the documentation is crap.QuoteI 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 FFswithina packet.The docs say bugger-all on this. Indirectly, there is thisIt is possible the 125k/sec SPI byte rate is intended to mean that if you do that, you won't see any FFswithina packet, which AIUI is crucial to the protocol working. But nowhere I know of does it say that.

author: jc101
author_rank: Frequent Contributor
timestamp: May 04, 2022, 08:23:57 pm
content: 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.

author: peter-h
author_rank: Super Contributor
timestamp: May 04, 2022, 08:35:34 pm
content: 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, herehttps://portal.u-blox.com/s/question/0D72p000009bAGVCA2/detail?s1oid=00D200000001ogf&t=1651691683831&s1nid=0DB2p0000008PMD&emkind=chatterCommentNotification&s1uid=0052p00000AKKM8&emtm=1651683154013&fromEmail=1&s1ext=0and 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 thatIt 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 byteended 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 receivedwithina packet and then the binary protocol isimpossibleto 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 stillvastlyfaster 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

author: thinkfat
author_rank: Unknown
timestamp: May 05, 2022, 09:09:05 am
content: 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.

author: peter-h
author_rank: Super Contributor
timestamp: May 05, 2022, 10:55:36 am
content: 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...

author: peter-h
author_rank: Super Contributor
timestamp: May 05, 2022, 07:53:26 pm
content: 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 differI 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.

author: jc101
author_rank: Frequent Contributor
timestamp: May 05, 2022, 07:58:54 pm
content: 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.

author: peter-h
author_rank: Super Contributor
timestamp: May 05, 2022, 08:39:32 pm
content: My CAD package is Protel PCB 2.8 from 1995This one works okhttps://www.pcbway.com/pcb_prototype/impedance_calculator.html

author: thinkfat
author_rank: Unknown
timestamp: May 05, 2022, 08:43:46 pm
content: Quote from: peter-h on May 05, 2022, 07:53:26 pmThe 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 50resistor, 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.

author: nctnico
author_rank: Super Contributor
timestamp: May 05, 2022, 08:43:52 pm
content: 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.

author: peter-h
author_rank: Super Contributor
timestamp: May 05, 2022, 08:48:27 pm
content: Sorry - I meant the track from the GPS module to the SMA socketIt is about 3cm long.

author: thinkfat
author_rank: Unknown
timestamp: May 05, 2022, 08:57:38 pm
content: Quote from: nctnico on May 05, 2022, 08:43:52 pmI have used a M8T with nav rates up to 4 Hz, but only in a stationary use case. The M8T is a timing module and I use 4Hz measurement rate during the survey-in to converge faster on a precise position.

author: peter-h
author_rank: Super Contributor
timestamp: May 05, 2022, 09:04:27 pm
content: The M9N is supposed to go up to 25Hz.I am running some mesages at 5Hz and some at 1Hz.It is fairly obvious that for 25Hz you would have to cut the output right down, to perhaps just one message, otherwise the data would never get outA lot of applications I work with need 5Hz e.g. avionics.

author: nctnico
author_rank: Super Contributor
timestamp: May 05, 2022, 09:08:11 pm
content: Quote from: peter-h on May 05, 2022, 08:48:27 pmAh, that makes sense. If you know the stackup of the board then you can use the Saturn tool to get a rough estimate of the trace width you need. For a regular 4 layer board (not impedance controlled) the dielectric between the outer and inner layers will be thick enough not to cause a very large error. Formula based tools like the one from Saturn have large errors with really thin (<0.1 mm) dielectrics which are typically used on very high speed layouts. In the end it is not super critical anyway but you want to be in the right ballpark. If you check the datasheet, the impedance of the GPS module's antenna input likely has a tolerance of 10%.

author: peter-h
author_rank: Super Contributor
timestamp: May 05, 2022, 09:10:43 pm
content: I make it 0.014", for a 0.2mm thick outer FR4 laminate and 1oz copper.

author: thinkfat
author_rank: Unknown
timestamp: May 05, 2022, 09:14:19 pm
content: Quote from: peter-h on May 05, 2022, 09:10:43 pmSounds about right for a microstrip line.

author: nctnico
author_rank: Super Contributor
timestamp: May 05, 2022, 09:16:22 pm
content: 'My' PCB package which uses a field solver says to use 0.31mm

author: peter-h
author_rank: Super Contributor
timestamp: May 05, 2022, 09:21:09 pm
content: That is 0.0122 which is close enough for government work, as they sayWhich relative permittivity did you use for FR4? It isn't well controlled anyway.This is a commercial devkit for the module, which uses a much thicker track there but then it has a copper pour close to it

author: nctnico
author_rank: Super Contributor
timestamp: May 05, 2022, 09:50:09 pm
content: In my experience (based on measurements) 4.5 is a good number to use.

author: thinkfat
author_rank: Unknown
timestamp: May 06, 2022, 08:37:33 am
content: Looking at the footprint you use for the SMA connector - it looks a bit off. The launch zone is too wide and there's a discontinuity when it hits your 50\$\Omega\$ line.I'm just saying that to give you more to fuzz about. It won't matter, actually :-)

author: peter-h
author_rank: Super Contributor
timestamp: May 11, 2022, 07:07:07 am
content: For SPI, I have given up trying to implement the 0xFF handling while reading the UBX-NAV-SAT binary packets. The code gets just too messy (basically treating 0xFF as real data once the header is identified, all the way to the verified packet end, but excluding the very end) and I found I was able to extract all the info I need from the ASCII-only packets likePUBX,00 (position etc) - ASCII packetPUBX,03 (status) - ASCII packetG*RMC Recommended minimum data - ASCII packet - this one also works with a generic (non UBLOX) GPSI have a sample UBX-NAV-SAT packet which actually contains 0xFF (three of them):Code:0xB5, 0x62, 0x01, 0x35, 0xD4, 0x00, 0xB0, 0xAD, 0xB2, 0x21, 0x01, 0x11, 0x00, 0x00, 0x00, 0x0A,0x15, 0x28, 0x8D, 0x00, 0x04, 0x00, 0x1C, 0x19, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x12, 0x2F, 0x00,0x00, 0x00, 0x11, 0x12, 0x00, 0x00, 0x00, 0x15, 0x15, 0x1F, 0x12, 0x01, 0xEA, 0xFF, 0x1C, 0x09,0x00, 0x00, 0x00, 0x19, 0x13, 0x23, 0x5C, 0x00, 0x38, 0x00, 0x1C, 0x09, 0x00, 0x00, 0x00, 0x1F,0x13, 0x3C, 0xD4, 0x00, 0xCE, 0xFF, 0x1C, 0x19, 0x00, 0x00, 0x00, 0x20, 0x00, 0x42, 0x2F, 0x00,0x00, 0x00, 0x11, 0x12, 0x00, 0x00, 0x01, 0x85, 0x00, 0x29, 0xC2, 0x00, 0x00, 0x00, 0x01, 0x07,0x00, 0x00, 0x01, 0x87, 0x00, 0x18, 0xEC, 0x00, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x01, 0x89,0x00, 0xDF, 0x28, 0x01, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x06, 0x05, 0x1D, 0x26, 0x5E, 0x00,0x4B, 0x00, 0x1F, 0x09, 0x00, 0x00, 0x06, 0x06, 0x00, 0x3D, 0x5B, 0x01, 0x00, 0x00, 0x11, 0x12,0x00, 0x00, 0x06, 0x07, 0x00, 0x11, 0x34, 0x01, 0x00, 0x00, 0x11, 0x12, 0x00, 0x00, 0x06, 0x09,0x00, 0x12, 0xBD, 0x00, 0x00, 0x00, 0x10, 0x12, 0x00, 0x00, 0x06, 0x0F, 0x1C, 0x2A, 0x2B, 0x00,0x6F, 0x00, 0x1F, 0x19, 0x00, 0x00, 0x06, 0x10, 0x1A, 0x3D, 0x97, 0x00, 0xC1, 0xFF, 0x1C, 0x19,0x00, 0x00, 0x06, 0x15, 0x18, 0x0A, 0xFC, 0x00, 0x00, 0x00, 0x14, 0x12, 0x00, 0x00, 0x06, 0x16,0x00, 0x12, 0x2C, 0x01, 0x00, 0x00, 0x11, 0x12, 0x00, 0x00, 0x3A, 0x8A,A query has gone out to U-BLOX (via their UK disti) but it looks like it will be a while. I will update this thread with any solution they offer to this bizzare issue

author: jc101
author_rank: Frequent Contributor
timestamp: May 11, 2022, 07:40:04 am
content: I don't know how your reading in the packet, but from that example packet it should be simple...Read data until you get 0xB5, 0x62, throwing away anything until you get that pair. Read the next two bytes which identify the type of packet it is for processing later on, read the next two to tell you there are n more bytes to read (0x00D4 or 212 in this case), add 2 for the checksum. Read (212 + 2) bytes, verify the checksum, frame complete and start again. The code snippet I posted earlier in the thread is part of a function that takes a mix of ASCII and U-Blox packets, and passes the received packets onwards for processing.Yes, 0xFF can be a byte in a packet, but then it is data. The whole U-Blox protocol and ASCII is packet driven, do you ever see an 0xFF mid stream when receiving an ASCII packet over SPI?I have a couple of U-Blox dev modules somewhere, I might hook one up and give it a try via SPI and see if I can generate an under/over run on the buffers. As I'm just getting over COVID and waiting for a dental abscess to be sorted out, it should prove a distraction from the pain!

author: peter-h
author_rank: Super Contributor
timestamp: May 11, 2022, 08:30:04 am
content: You are right - it can be done that way.Unfortunately in my case it is a bit harder because I am running the whole thing co-operatively under an RTOS. I have a loop which calls ipqcount() which, for a serial port, returns mostly 0, in which case I yield to the RTOS. If ipqcount returns >0 then I call fgetc and get the byte, and off it goes to a state machine to sort out the rest (looking for various packet types, etc). That yields to RTOS after each byte.Now, with SPI, you cannot implement an ipqcount like you can with an interrupt-driven UART RX queue. You read the SPI (writing an FF at the same time, which the modem ignores) and if you get FF then you chuck it away and return ipqcount=0except when decoding the inner part of a binary packet. If you get non-FF then you save that char for the subsequent fgetc call, and return ipqcount=1.So it isn't hard, but you have to test that code, with binary data containing FFs in every possible place, and especially at the very endIt would take time to generate packets which have an FF at the very end.I decided to not bother because while I am parsing and checking that binary packet, I am not actually extracting data from it, and it doesn't look like my project will need it. And it is quite a rabbit hole to spend a day or so on this, when we areentirely speculatinghow this stupid interface is supposed to work.QuoteI may do that test, but as I say this whole scheme is speculation, based on a crappy data sheet.I find it pretty amazing that U-BLOX really and truly expected users to do a stunt like this. If affirmative, it looks like a cockup i.e. somebody forgetting that there are binary packets. And if it wasn't a cockup then anybody with a brain would have documented it.Interestingly, with ASCII-only packets, there is no SPI speed limit (apart from the overriding 5.5MHz max clock). Well, there is actually: for theinitialisationof the GPS, to whichone again presumesthe 125kbytes/sec limit applies also.One workaround is to init the GPS separately somehow and save the config to its FLASH. The problem with that is that these U-BLOX units have no "factory reset" so if you end up saving some "wrong stuff" you have no way to clean up the unit other than create a huge list of all possible config packets and send them all inBrainless? You bet!

author: jc101
author_rank: Frequent Contributor
timestamp: May 11, 2022, 08:49:19 am
content: Yes, I do it much the same way under FreeRTOS. The 'packet finder' is a task that sleeps until it receives a byte via a stream buffer. Does it stuff, then sleeps until another byte is received. Once it has a whole packet, it drops it into queue to be picked up and processed in another task. That queue data is a union struct with all the different expected packet types in, so it's very easy to identity the packet type and then pull out the data as needed. Again that task uses no CPU until a fully formed and verified packet is passed to it. If it doesn't recognise it as a packet it is interested in is junks it.This way the packet finding is interface agnostic. Though it is a 1:1 as I'm using stream buffers, so I'd need a separate instance of the packet-finder per physical interface. I generally have a serial interrupt send stream the data via the stream buffer to the task, so neither take any CPU when there is no data. I guess it's tricker with SPI and the need to poke the interface to get a byte back, I think with the PIC32's I normally use I could trigger an interrupt on a SPI RX and just send the SPI poke byte out as often as I needed to, also possibly inside a transmit interrupt linked to a timer.It's an interesting problem, I like the U-Blox modules, so it would be worth me spending the time to write some library code suitable for SPI I can use in future projects. Might not be too readable given painkillers I'm on though...

author: peter-h
author_rank: Super Contributor
timestamp: May 11, 2022, 03:04:40 pm
content: I've just been wrapping up the code for when my SPI U-BLOX PCB arrives... Due to the RF side I am not birdsnesting it.The initialisation of the GPS is not a problem because one can intentionally space out the bytes sent to it. I am putting in osDelay(2) since osDelay(1) delivers a delay of 0 to 1ms. This is FreeRTOS.So it is easy to run the SPI at 5.5MHz. I have a 5.25MHz option so will use that. That will generate lots of FFs on the receiving side but might make the RTOS thread run better. Basically it will deliver a much faster executing ipqcount() - the input queue size query.EDIT: just checking the SPI timing, and it seems weird how they spec it. Every SPI device I have used has some requirement on how long you have to wait after setting CS=0, before you can start clocking. And similarly from the last clock to CS=1 at the end.For example I have a STLED316 display controller where these times are of the order of microseconds!But this data sheet contains the bizzare statement that this is dependent on the Master. Well, it is, but the Master needs to meet the Slave's timing requirements!!!

author: peter-h
author_rank: Super Contributor
timestamp: May 17, 2022, 06:09:25 am
content: Does anyone have any ideas on the above SPI timing?

author: jc101
author_rank: Frequent Contributor
timestamp: May 17, 2022, 06:30:06 am
content: Is it not "A" - MISO data valid time (CS), given for difference bus capacitance values?

author: peter-h
author_rank: Super Contributor
timestamp: May 17, 2022, 07:11:21 am
content: These parameters are normally specified for an SPI slave, and the Master /CS timing has to be arranged to achieve it. But U-BLOX don't specify it, instead giving that strange note about it being determined by the masterFor example this chip specifies themas 400ns and 1us respectively (the STLED316 clocks the data on the +ve clock edge, so the 1st one is implicit in the min clock width of 400ns).

author: peter-h
author_rank: Super Contributor
timestamp: May 19, 2022, 02:59:30 pm
content: Well, I have a report on testing this bizzare SPI interfaceIt does work.Due to limitations on SPI clock divisors I am running it at 650kHz SPI clock, which is a max of 81250 bytes/sec. This keeps it within the 125000 bytes/sec speed limit in the data sheet.It's been speculated that exceeding this read rate returns 0xFF byteswithinpackets (which can be safely discarded on ASCII packets) but actually not exceeding this speed limit is more important on data goingtothe GPS. If one runs the SPI at the next speed up (1.3MHz) then the GPS really slows down and is basically useless. Consequently I was not able to really test "SPI underruns" beyond confirming that with a 1.3MHz SPI clock I was not seeing any 0xFFs within the RMC packet.I suspect this GPS has the SPI RX wired to an ISR so when you send it a byte (which is usually 0xFF, except when you are initialising it) that triggers some code which doesn't run all that fast.And with SPI one has to send datatothe GPS in order to read data out of it, obviously.The end result is a lot faster than the serial interface: 650000 versus say 38400 (the default) or 115200.I did not detect any 0xFF bytes within packets, at 650kHz SPI clock, and at faster clocks it didn't work anyway. I am not using any binary packets.To run the SPI faster, up to the 5.5MHz in the data sheet, one would need to sync the SPI to a timer so that whatever the SPI clock is, the above byte rate is not exceeded. That is completely pointless unless you have to run the SPI fast for some other reason.As regards the crappy data sheet and the SPI /CS timing, I tried basically no delay and that still runs, so I put in 1 us.

author: clive.one
author_rank: Newbie
timestamp: May 19, 2022, 04:29:57 pm
content: For context there's half a dozen threads over at the u-blox forum on thishttps://portal.u-blox.com/s/question/0D52p0000CL5I0OCQV/neom9n-and-spi-does-it-work-with-proprietary-ubx-packetshttps://portal.u-blox.com/s/question/0D52p0000CMtsm5CQB/neom9n-spi-master-timing-data-sheet-is-strangehttps://portal.u-blox.com/s/question/0D52p0000AOH1lzCQD/neom9n-spi-am-i-reading-the-manuals-correctlyLet me summarize..SPI on these receivers is a stream interface, it is not like a peripheral read/writing registers.SPI is a symmetrical interface, one clock moves data in both directions.The availability of data on each side of the interface may be asymmetrically, usually the receiver generates new data continually, and the host just wants to consume that.The interface needs to be clocked/pumped to move the data.Data movement in each direction is expected to be complete, intact packets.When no packet data is available a dummy / stuff byte of 0xFF is used.The packets have defined/predictable structure, and can include any 8-bit byte patterns, in any number of combinations.The burst rate can be high, allowing for reduced latency (time to get actionable / usable data)The packets are assembled on the receiver side, and serviced from a common memory pool, in a scatter-gather fashion.If you stall the interface, ie ignore it so data backs up and log jams, you typically send a polled/query type command to indicate that you're ready to actually pull the data in a semi-continuous fashion. ie as fast as it is generated, and not in a way that you run the data dry.If the receiver doesn't have data for the host, it stuffs it's side with 0xFF, but this causes a lot more friction and load on the processor, especially if you keep playing "Are we there yet?" at 5.5 MHz wire rates.

author: peter-h
author_rank: Super Contributor
timestamp: May 19, 2022, 04:35:23 pm
content: Indeed; those threads were started by meSome of the info was helpful, while in others I was told that an octet has 8 bits, or that I should not post "deep" questions in the U-BLOX forum and instead ask my distributor's field engineer (an idea which died out about 40 years ago).Most questions scroll off very fast. That forum is full of desperate people posting questions and mostly not getting answers. Same as thehttps://community.st.com/forum actually.QuoteMy tests show that you can't do that anyway; sending the 0xFF "have you got data" poll at about 160kbytes/sec (1.3MHz SPI clock) buggers up the NEO-N9M pretty well. It is still doing something but the packets which are supposed to be say 5Hz come out at about 0.5Hz.Looks like the 125000 bytes/sec data sheet limit is quite a hard limit (in that 160000 bytes/sec does not work) for all SPI ops regardless of whether the intention is- write to the GPS (sending a non-FF byte)- polling the GPS for data (sending a FF byte and looking at what came back)

author: clive.one
author_rank: Newbie
timestamp: May 19, 2022, 08:57:05 pm
content: >>That forum is full of desperate people posting questions and mostly not getting answers. Same as thehttps://community.st.com/forum actually.It's a user-to-user forum, and the quality of the users is pretty low. We do what we can..

author: peter-h
author_rank: Super Contributor
timestamp: May 19, 2022, 09:08:50 pm
content: Indeed, but really themanufacturersshould participate. They are making the $$$ after all, while all us poor bastards are just wasting our time getting their chips to workIt's an old problem, going back to the earliest days of the "internet" (say mid-1990s, with Usenet) which has never been addressed. Manufacturers generally hate social media. I run a "tech" forum (not electronics) and we have huge problems getting "trade" people to participate.Big users get direct support, and everybody else wastes months googling for bug fixes which, when they develop+implement them, they rarely post because it was done in company timeI feel sorry for the few clever users who provide support, presumably unpaid, on these forums, and I am very grateful to them. However in this case I suspect the SPI feature is used by almost nobody.BTW I never established an upper limit on how fast one can send GPS init stringstothe module. That was another Q of mine. It isn't time-critical so I just do it at 650kHz and put a osDelay(2) - a delay of 1-2ms - after each byte sent. It is very likely one could then run the SPI at the full 5.5MHz but there is not likely to be any point. It's true that osDelay() yields to the RTOS, and shortening theblocking(SPI has to be blocking so you can drop and raise /CS) SPI operation accordingly might help in some cases, but one is not initialising the GPS all the time... plus I have no data sheet spec on the /CS timing before/after the clocking, so I am wasting 1us before and 1us after, rendering the benefit of anything at "5.5MHz" dubious.Probably the slickest way to implement the SPI interface is with a FIFO, like a UART, and with a hardware-limited means of driving the SPI at a specific rate of 125kHz. This - an interrupt every 8us - is a bit too fast for a timer ISR though, especially as access to the 32F417 peripherals is very slow, so perhaps a timer triggering a 1-byte DMA transfer. I don't know if the 32F417 is capable of interrupting on received SPI data (non-FF value).

author: peter-h
author_rank: Super Contributor
timestamp: May 21, 2022, 07:06:11 pm
content: I've been thinking about this some more, regarding the context-dependent 0xFF non-discarding on binary packets.It is easy enough to implement, by detecting the packet header and thennotdiscarding any FFs until the packet length has been fulfilled.The problem is that if you did get an underrun you will never know, other than the checksum will come up duff (well, 1 in every 256 duff packets will have a valid checksum).If the data sheet guaranteed a minimum internal buffer fill speed, then you could time the SPI precisely (with a timer, say) to make sure the SPI actions do not happen faster, and also do not happen slower than the internal buffer size would overflow.The problem is that U-BLOX do not specify the internal buffer fill speed, and do not specify the buffer size.One could assume that by the time the header is available, the whole buffer has been filled, but that is really unlikely.So basically you cannot develop a product which reads non-ASCII packets using SPI and be sure there is any kind of margin.One day I will be looking at their 4G modules and if they do the same thing, that won't work either because UDP packets definitely can contain FFs.The other thing I have just found is that the initialisation can also contain an FF (see 1st line):Code:uint8_t neo_m9n_init_data[] ={0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x23,// disable GGA0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2A,// disable GLL0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x31,// disable GSA0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x38,// disable GSV0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x46,// disable VTG0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x5B,// disable ZDAHow the hell does the module deal with that, when all FFs senttoit are discarded?

author: thinkfat
author_rank: Unknown
timestamp: May 21, 2022, 07:50:36 pm
content: Well. It's not unreasonable to assume that the module has the same state machine built-in that you describe above. It is obvious that they have to parse packets, and also verify the checksum. Though I'd have used a CRC-16 at least, instead of a simple summing of bytes. Also, the documentation does not say that the module will discard all 0xFF bytes it receives. I think you misinterpret something. It would be extremely dumb, knowing that the UBX protocol requires that the channel is "transparent".PS: the only sane response to a checksum error is discarding the packet without even looking at it.

author: peter-h
author_rank: Super Contributor
timestamp: May 21, 2022, 08:55:16 pm
content: From the Integration manual, UBX-19014286 - R073 Receiver functionality Page 29 of 95The 0xFF to the GPS is the "disable GGA sentence" config which, if it doesn't work, will simply cause that sentence to be emitted, and since I am not looking for it, discarded.The only thing in the doc that you can hang your coat on is the 125000 byte/sec max SPI speed. The entire edifice here is based on the speculation that the programmer carefully made sure that not exceeding this speed will never cause an underrunwithina packet (which is probably quite difficult looking at the huge complexity of the code inside) and at the same time made sure that the buffers allocated to the packets are big enough to hold the longest possible packets for the case where the SPI speed isless than125000 bytes/sec. There is no minimum speed specified...The English in the doc is terrible (gramatically fine but poor for disambiguating what are IMHO obvious questions from anyone writing code for it) which doesn't help.

author: thinkfat
author_rank: Unknown
timestamp: May 21, 2022, 09:52:29 pm
content: The manual says to discard all 0xFF bytes "which are not part of a message", right? So, 0xFF bytes within a message are perfectly fine.

author: peter-h
author_rank: Super Contributor
timestamp: May 21, 2022, 10:10:24 pm
content: For receiving datafromthe GPS, yes, but please read my timing explanation/concerns. It isn't simple.All I can say is that it works fine, with ASCII packets and with a 650kHz SPI clock (81250 bytes/sec max data rate). I cannot tell with what margin, and it isn't easy to margin-test it because the SPI clock is settable only in powers of two. At 162500 (81250 * 2) bytes/sec the GPS is quite unhappy. I will try lower speeds but it will obviously work because other RTOS tasks run fine with it.The text screenshot I posted above refers to data senttothe GPS. It implies initialisation data senttothe GPS must not contain FFs and any such are discarded. I would hope that this text is BS and actually once the GPS sees the start of an init packet (0xB5,0x62,0x06...) itdoesaccept FF bytes.SPI is always "back to back write/read" and this is what gives rise to all these issues. You have to have a means of sending a bytetothe device and discarding what naturally comes back on SPI RX (which is trivial; read it and discard it) and a means of getting a bytefromthe device but without sending it one (which is impossible with SPI, and in this case is achieved by sending an FF).With a UART, it's all fine.EDIT: lower SPI speeds tested. I did a breakpoint on an NMEA checksum error counter increment and go zero at 650kHz, 325kHz, 162.5kHz and can't go any lower. Interestingly I also don't get any errors at 1.3MHz but the GPS really slows down and cannot maintain the specified 5Hz rate. At 2.6MHz itreallyslows down, to about 0.5Hz, but still no NMEA checksum errors. This suggests that the SPI generates an internal interrupt which the CPU is only just about able to service at the specified 125kbyte/sec rate (equivalent to SPI clock of 1MHz).With the NEO-M9N costing probably under $5 in volume, it won't have a 168MHz ARM32 insideIt's probably an 8051 core of some sort, next to the hardware GPS implementation.

author: thinkfat
author_rank: Unknown
timestamp: May 22, 2022, 11:45:41 am
content: Quote from: peter-h on May 21, 2022, 10:10:24 pmI see no constraint on 0xFF bytes within a message, expressed or implied. You assume too much, I reckon. Can you pinpoint the sentence you base your assumption on?

author: peter-h
author_rank: Super Contributor
timestamp: May 22, 2022, 12:21:01 pm
content: The yellow bit above.This is the inherent way SPI works. You cannot read data without also writing the same amount of data. This issue arises with all SPI devices which "accept" data e.g. an ADC for config purposes (look up ADS1118, which deals with this by you sending it the same 16 bits of config data every time you read out the 16 bit value), while other devices are read-only (e.g. MCP3550) and have just the MISO output (no MOSI input).So when reading this U-BLOX module (a GPS module is mostly just read, not written) it ignores 0xFF bytes written to it.

author: jc101
author_rank: Frequent Contributor
timestamp: May 22, 2022, 12:23:39 pm
content: Quote from: thinkfat on May 22, 2022, 11:45:41 amThere is a constraint, in 11.6.2 (of my protocol guide anyway) it says...QuoteThis implies that providing you don't send more than 50 0xff in the payload of any packet all should be fine. But there is a limit, software settable, with a default of 50 0xff's before the RX in the module just chucks the data away until a non 0xff arrives.When sending CFG commands to the modules, it will either ACK or NAK it has received and processed the command.QuoteSo, for me, I send the CFG, and only move to the next CFG command once I've had the corresponding ACK back. If I get a NAK, I try again and if I still get a NAK I report a comms error. It doesn't matter that 0xFF may be in the payload of the CFG packet, the module knows it's receiving a packet.QuoteThis is also pretty clear, to me anyway, that receiving an 0xff is perfectly fine within a packet.

author: thinkfat
author_rank: Unknown
timestamp: May 22, 2022, 12:56:21 pm
content: Quote from: peter-h on May 22, 2022, 12:21:01 pmBut SPI does not mandate the discarding of 0xFF bytes within a packet. The 0xFF are "idle" bytes only, you need to send them when you want to receive messages while you don't have anything else to tell the receiver. While you're sending a message, there is no implication that the receiver will discard them.In fact:Quote from: jc101 on May 22, 2022, 12:23:39 pmExactly. No more than mode.ffCntconsecutive0xFF byte in any message and you're fine.

author: peter-h
author_rank: Super Contributor
timestamp: May 22, 2022, 02:32:45 pm
content: That all sounds ok then and explains why it is workingThe only thing I don't do is checking for the ACK after sending it the config. I just send the config every 2 secs until recognisable NMEA packets start appearing.

author: camerart
author_rank: Newbie
timestamp: November 06, 2022, 02:07:40 pm
content: Quote from: clive.one on May 19, 2022, 08:57:05 pmHi C1,I'm one of those low quality uses, you speak about. (No offence felt, as I can't help it)However behind me are high 'quality' people who are helping me, I'm just who you 'speak' to.Cheers, Camerart

author: camerart
author_rank: Newbie
timestamp: November 06, 2022, 02:13:25 pm
content: Quote from: peter-h on May 22, 2022, 02:32:45 pmHi P,Do you mean that you have gotten the M9N to send $NMEA messages using SPI, back to your 'microcontroller' ?We've been trying for months!Would you be good enough to post the key lines of CODE, that produce this please?Cheers, Camerart

author: peter-h
author_rank: Super Contributor
timestamp: November 06, 2022, 05:46:23 pm
content: Firstly you have to config SPI to run slow enough to assure the 125kbytes/sec tx rate is not exceeded (a lot of BS is written online about this, but it is real)Code:m_spi.Init.Direction = SPI_DIRECTION_2LINES;m_spi.Init.DataSize = SPI_DATASIZE_8BIT;m_spi.Init.CLKPolarity = SPI_POLARITY_LOW;m_spi.Init.CLKPhase = SPI_PHASE_1EDGE;m_spi.Init.NSS = SPI_NSS_SOFT;m_spi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;// 64: 650kHz (max 1MHz for 125kbyte/sec max data rate)m_spi.Init.FirstBit = SPI_FIRSTBIT_MSB;m_spi.Init.CRCPolynomial = 7;m_spi.Init.Mode = SPI_MODE_MASTER;m_spi.Instance = NEO_M9N_SPI;HAL_SPI_Init(&m_spi);This is the init codeCode:void neo_m9n_init(){// Initialise internal (SPI) GPS{#ifndef TEST_DATAuint8_t tmp;for (uint16_t i=0; i < sizeof(neo_m9n_init_data); i++){kde_neo_m9n_spi3_write_read_byte(neo_m9n_init_data, &tmp);osDelay(2);// this delay removes any need for SPI speed limit when feeding the GPS}#endifdebug_thread_printf("GPS init sent to SPI");}Code:/** NEO-M9N GPS byte write+read over SPI.* For normal data read, transmit 0xFF. If you get 0xFF back, that indicates an under-run so discard it.* The read speed is limited to 125kbytes/sec and this is supposed to avoid under-runs *within* packets, which is* necessary otherwise binary packets could not be received! This issue has been sidestepped by not implementing* any binary packets.* We achieve the 125kbyte/sec limit (equivalent to a 1MHz SPI clock) by running SPI3 at 650kHz clock which is* the nearest value below 1MHz. However since we aren't processing binary packets (GET_UBX_NAV_SAT not defined)* we could run SPI a lot faster, except that will overspeed the SPI *to* the GPS.* It is a truly shit interface, but much faster than a UART even at 115kbaud, and avoids using up any of our* four serial ports. In any case, none of the four serial ports come out on the two expansion connectors.* In normal operation, this function will return solid FFs during the inter-packet gaps (every 200ms) and* should return few if any FFs during the packets.**/static void kde_neo_m9n_spi3_write_read_byte(uint8_t out_value, uint8_t * ret_value){// These are static so DMA can be usedstatic uint8_t outv = 0;static uint8_t inv = 0;outv = out_value;kde_neo_m9n_cs(0);hang_around_us(1);SPI3_DMA_TransmitReceive(&outv, &inv, 1, false, false, RTOS_YIELD);hang_around_us(1); // 1 microsecondkde_neo_m9n_cs(1);*ret_value = inv;}I am not posting the DMA code; you don't really need it since the speed here is so low.The code shows SPI3 is mutexed; you may not need to do that if not sharing SPI3.Here is the init data and you tweak that to select which packets you wantCode:/*** Transmit config data block to the GPS.* This disables various default NMEA messages (sentences) and selects three proprietary U-BLOX messages* which were chosen to return not just location but also HDOP and VDOP, and whether SBAS is being used.* The GPS is set to run, and emit the basic position and HDOP/VDOP, at 5Hz which is important for high quality* positioning purposes.* The satellite status messages come out at 1Hz because they are not needed as often, and due to their size* would overrun the 38k serial baud rate.* This configuration results in about 1.4kbytes/sec coming from the GPS, which is manageable at 38k.* Working out this config was a bastard. Each config message below ends with a checksum and U-BLOX have* special software for composing these and calculating the checksums. I managed to extract these messages* from their tech support.** Port is 1 2 3 4 for serial ports 1 2 3 4. 3 is not used because it is 2-wire RS485.* Port of -1 means internal (SPI) GPS.** Unless SPI GPS is used, the size of the init block must be no bigger than opqspace(g_gps_port)! This* was done to avoid a blocking call and yet another timeout, etc.* Currently the opqspace is 1k.**/static const uint8_t neo_m9n_init_data[] ={//0xB5,0x62,0x06,0x01,0x03,0x00,0xF0,0x08,0x01,0x03,0x20,// enable ZDA0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x23,// disable GGA0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2A,// disable GLL0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x31,// disable GSA0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x38,// disable GSV//0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x3F,// disable RMC0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x46,// disable VTG0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x5B,// disable ZDA#ifndef RMC_ONLY0xB5,0x62,0x06,0x01,0x03,0x00,0xF1,0x00,0x01,0xFC,0x13,// enable PUBX,00#endif0xB5,0x62,0x06,0x08,0x06,0x00,0xC8,0x00,0x01,0x00,0x01,0x00,0xDE,0x6A,// GPS rate 5 Hz// UBX-NAV-SAT (0x01 0x35) at 5Hz - satellite data, binary// B5 62 06 01 03 00 01 35 01 41 AD#ifndef RMC_ONLY// above at 1Hz - preferred for less data#ifdef GET_UBX_NAV_SAT0xB5, 0x62, 0x06, 0x01, 0x03, 0x00, 0x01, 0x35, 0x05, 0x45, 0xB1,// enable UBX-NAV-SAT at 1/5 of rate = 1Hz#endif// PUBX,03 (Satellite data, ASCII) and at 5Hz// B5 62 06 01 03 00 F1 03 01 FF 19// above at 1Hz - preferred for less data0xB5, 0x62, 0x06, 0x01, 0x03, 0x00, 0xF1, 0x03, 0x05, 0x03, 0x1D// enable PUBX,03 at 1/5 of rate = 1Hz#endif// This saves the config in flash, UBX-CFG-CFG// NOT doing this on new devices because there is no evident factory reset!// 0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1D, 0xAB};Hope this helps.The SPI interface on this module is a bodge. They probably stuck it on the front of their UART, sort of.

author: camerart
author_rank: Newbie
timestamp: November 06, 2022, 06:26:36 pm
content: Quote from: peter-h on November 06, 2022, 05:46:23 pmHi P-h,Yes, it will! I haven't seen much proof, that SPI works with these modules, it's a pity it's a bodge.I have forwarded it to my mate who is multilingual.Thanks very much.C

author: peter-h
author_rank: Super Contributor
timestamp: November 06, 2022, 09:29:56 pm
content: It certainly works and at 650kbits/sec SPI, is much faster than RS232 would be.There is a problem if you enable packetswhich may contain 0xff within the data(NMEA ones don't but the U-BLOX ones can do) and then you need to write a much more complex state machine, plus I am not sure if this even works at all over SPI.

author: camerart
author_rank: Newbie
timestamp: November 07, 2022, 08:49:53 am
content: Quote from: peter-h on November 06, 2022, 09:29:56 pmHi P-h,My method so far is to program the GPS wih U-center, then as all I need is the $GNRMC sentences, I've been sending what I think is the 'request' series of BYTES (24 50 55 42 58 2C 30 30 2A 33 33 0D 0A) via SPI, then 0xffs.D_sel high for programming, D_SEL low before (power on) and CS, SCK.So far, I haven't received a $ yet.C

author: peter-h
author_rank: Super Contributor
timestamp: November 07, 2022, 09:56:45 am
content: You may need a scope and look at the SPI signals.

author: camerart
author_rank: Newbie
timestamp: November 07, 2022, 10:39:02 am
content: Quote from: peter-h on November 07, 2022, 09:56:45 amHi P-h,This time I tried (U-CENTER) UBX-NAV-POSLLH and POLLED it, using a digital analyser. Copied the BYTES, into my program.Result: I see $GNRMC and the time on the MISO, which is NOW. If I'm not mistaken I'ts working.What do you think?C

author: camerart
author_rank: Newbie
timestamp: November 07, 2022, 11:03:51 am
content: Hi,False alarm, this is Serial dataC

author: camerart
author_rank: Newbie
timestamp: November 13, 2022, 09:33:49 am
content: Hi P-h,The modules I have at present are M8Ns, and in desperation to find SPI information, tried M9Ns where I found this forum. I now find that the two are not quite the same, so and added difficulty.As I have a back-up way if splitting the 2x UART inputs, by using the second PIC on my units, I have chosen to go this direction instead of the SPI route.Thanks for your CODE.It's a pity that the mighty Ublox acts in this way!Thanks C.