u-blox / ubxlib

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

Untethered Dead Reckoning and odometer use with cellular module integration #255

Open atiaisaac opened 2 weeks ago

atiaisaac commented 2 weeks ago

I have a custom esp32 board with a neo-m8u and sara u201 cellular module. The goal is to have the cellular module control the neo-m8u GNSS module and its functionalities. The specific functionalities I want to use are;

  1. AssistNow Autonomous
  2. UDR
  3. Odometer
  4. HTTPS client

From the library I can easily configure and use 1 and 4. However I see no explicit mention of how to use 2 and 3 from the library even though the documentation for the GNSS module (neo-m8u) says it has the capability.

RobMeades commented 2 weeks ago

Hi, and thanks for posting. You are correct that (2) and (3) aren't explicitly mentioned in the ubxlib world, it is getting kind of specialist, but hopefully ubxlib gives you the tools you need to "DIY".

Your application would use the functions of the u_gnss_msg.h API, things like uGnssMsgSend(), uGnssMsgReceive(), uGnssMsgReceiveStart() etc. to exchange/read messages with the GNSS device, potentially along with the u_gnss_dec.h API, chiefly pUGnssDecAlloc(), should you find that approach of use.

pUGnssDecAlloc() won't "know" about all of the message types etc., you would need to refer to the interface manual for the NEO-M8 as you went in terms of understanding the required UBX message contents, so you don't have to use pUGnssDecAlloc(), only do so if you find it helpful; you can just "manually" decode the UBX messages yourself.

RobMeades commented 2 weeks ago

Alternatively, if you can think up the API that you might like in ubxlib we would be happy to implement it.

atiaisaac commented 1 week ago

It would be nice if you could implement the odometer and UDR capabilities. I can already thing of a plethora of use-cases.

atiaisaac commented 1 week ago

Now after following the _main_loc_gnsscell.c in the examples folder and adapting it to my use case. I run into errorcode -4 when I call uDeviceOpen. Upon debugging step by step I realize it is uDevicePrivateCellAdd in uDeviceOpen that is causing the error. Here is the configuration settings for the cellular device I am using

static const uDeviceCfg_t device_Cfg = {
    .deviceType = U_DEVICE_TYPE_CELL,
    .deviceCfg = {
        .cfgCell = {
            .moduleType = U_CELL_MODULE_TYPE_SARA_U201,
            .pSimPinCode = NULL,
            .pinEnablePower = -1,
            .pinPwrOn = pinPWROn, // GPIO01 pin of ESP32 chip
            .pinVInt = -1,
            .pinDtrPowerSaving = pinDTR, // GPIO16 pin of ESP32
        },
    },
    .transportType = U_DEVICE_TRANSPORT_TYPE_UART,
    .transportCfg = {
        .cfgUart = {.uart =  U_CFG_APP_CELL_UART, .baudRate = U_CELL_UART_BAUD_RATE, .pinTxd = pinTXD, .pinRxd = pinRXD, .pinCts = -1, .pinRts = -1, .pPrefix = NULL},
    },
};

The code is running as part of my own code written in esp-idf.

RobMeades commented 1 week ago

Error code -4 is U_ERROR_COMMON_NOT_SUPPORTED. I think this is likely because you have a pin set there for pinDtrPowerSaving and SARA-U201 does not support DTR power saving; from the AT commands manual, section 20.1.7, see the note for SARA-U2:

image

Set pinDtrPowerSaving to -1 and you should hopefully get further.

[Ooops, looks like I didn't press send on this]

RobMeades commented 1 week ago

It would be nice if you could implement the odometer and UDR capabilities. I can already thing of a plethora of use-cases.

Understood: the issue will be testing as we have no way at all to regression test this. I will think of what we can do.

atiaisaac commented 1 week ago

Error code -4 is U_ERROR_COMMON_NOT_SUPPORTED. I think this is likely because you have a pin set there for pinDtrPowerSaving and SARA-U201 does not support DTR power saving; from the AT commands manual, section 20.1.7, see the note for SARA-U2:

image

Set pinDtrPowerSaving to -1 and you should hopefully get further.

[Ooops, looks like I didn't press send on this]

Right, that actually worked. But now running into another error code errorCode -257

RobMeades commented 1 week ago

Very good: following the guidance here you will see from the number that that is a cellular error code U_CELL_ERROR_NOT_CONFIGURED.

Searching the ubxlib code for that it occurs in only two places, both of which are in u_cell_pwr.c: one in uCellPwrOffHard(), which I guess is not what you're doing, which leaves us with moduleConfigure(); this sets all the static/initialisation things up with the module when it is powered-up or reset, likely one of those AT commands is failing.

Can you paste in here a log of the AT sequence emitted by ubxlib at power-up?

EDIT: I just realised you say above "that actually worked", so you're probably not seeing this errorCode -257 back from uDeviceOpen(), in which case please paste the AT sequence that leads up to the failure.

atiaisaac commented 1 week ago
U_CELL: initialising with enable power pin not connected, PWR_ON pin 1 (0x01) (and is toggled from 1 to 0) and VInt pin not connected.
I (4271) gpio: GPIO[1]| InputEn: 0| OutputEn: 1| OpenDrain: 1| Pullup: 1| Pulldown: 0| Intr:0 
AT

OK
U_CELL_PWR: powering on, module is already on.
ATE0

OK
AT+CMEE=2

OK
AT+UDCONF=1,0

OK
ATI9

23.60,A01.01

OK
AT&C1

OK
AT&D0

OK
AT&K0

OK
AT+UPSV=1,1300
U_CELL_PWR: power saving not supported.
AT+CPSMS?
AT+UGPRF?
AT+CFUN=0

This appears twice and it just hangs.

RobMeades commented 1 week ago

Thanks for that: as part of the power-on sequence the ubxlib code is asking the SARA-U201 module to enable UART power saving, which is what AT+UPSV=1,1300 does, but the SARA-U201 module is unresponsive after that.

How important is power saving in your application? If it is not particularly important you can define U_CFG_CELL_DISABLE_UART_POWER_SAVING when building ubxlib and ubxlib will not try to switch UART power saving on in the module.

If power saving is important the next thing to do is to put a monitor of some form (e.g. a Saleae probe) on the UART lines (i.e. TXD, RXD, CTS and RTS) to (a) confirm that the module really is unresponsive, rather than something else going wrong and (b) see if something like the state of the CTS output line from the module is somehow preventing the UART of your MCU sending things to it (seems unlikely, since the problem is a "lack of response from the module" problem).

RobMeades commented 1 week ago

Update: if UART power saving is important to you, I think I've found out what's up, hopefully no need to probe the UART lines.

The SARA-U201 integration manual says "on SARA-U2 modules, when the AT+UPSV=1 command is issued by the DTE, the UART is immediately disabled", i.e. it doesn't, sometimes, even respond with OK, it just stops dead as soon as the command enabling UART power saving arrives. This also means that the module is immediately in power-saving mode, it doesn't wait for the 6 seconds implied by the value 1300 to expire, which all our other module types do.

I have modified the ubxlib code to handle this little chicane on a preview branch that you can find here:

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

We haven't been testing SARA-U201 with UART power saving enabled so I've modified that to enable it and run the change through our testing; it seems to pass but it would be good if you could confirm this "for real".

EDIT: unfortunately there still seems to be a problem with writing files into the SARA-U201 module file system if UART power saving is enabled, and this is required for HTTPS to operate; the correct number of characters are written to file but reading the characters back shows that the file contents are garbage. I will try to find out if this is a known issue with SARA-U201 that might have a workaround.

atiaisaac commented 3 days ago

Just tested and my module is able to pass the initial power stages. I am able to set my GNSS constellation to a preferred choice to hex number 0x45 and it works. Now I am running into another error when calling uNetworkInterfaceUp. Upon debugging it seems to produce an errorCode -5 at uDeviceGetInstance(). Below is the full output log.

AT
AT

OK
AT
AT

OK
U_CELL_PWR: powering on, module is already on.
ATE0
ATE0

OK
AT+CMEE=2

OK
AT+UDCONF=1,0

OK
ATI9

23.60,A01.01

OK
AT&C1

OK
AT&D0

OK
AT&K0

OK
AT+UPSV=1,1300

OK
AT
AT
AT
AT
AT+CFUN=0
AT
[7f]s[00][00][02][08][00][00][00][00] [00][00][00][01][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00]AT
AT
AT
AT
AT
AT
AT
AT
U_CELL_PWR: powering on.
U_CELL_PWR: powering on, module is alive.
ATE0
ATE0

OK
AT+CMEE=2

OK
AT+UDCONF=1,0

OK
ATI9

23.60,A01.01

OK
AT&C1

OK
AT&D0

OK
AT&K0

OK
AT+UPSV=1,1300

OK
AT
AT

OK
AT+UGPRF?

+UGPRF: 2,0,""

OK
AT+CFUN=0
?[bd][19][7f][08][02][00][00]@ [80]H$[12][00][04][00][05][00][04][00][04][80]@[80][01][00][10][00]@[00][80][08][00][09][10][10][00][00]@[80][00]H[00]@[00]$[90][00]D[00][09][00][10][82][00][00][00][00][00][00][00][04][00][00][08][00][08][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00]AT
[00][00][00][00][00][00][00]

and this is the network configuration I am using

static const uNetworkCfgGnss_t gnss_Cfg = {
    .type = U_NETWORK_TYPE_GNSS,
    .moduleType = U_GNSS_MODULE_TYPE_M8,
    .devicePinPwr = 23,
    .devicePinDataReady = 24,
};
RobMeades commented 3 days ago

When you say "just tested", is this using the preview branch?

There's something very strange indeed going on with your setup though: the AT+CFUN=0 command from ubxlib puts the cellular module into a minimum-power state until the application asks it to connect to the cellular network; SARA-U201 should respond with OK. However, instead you get a string of garbage:

7f]s[00][00][02][08][00][00][00][00] [00][00][00][01][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00]

...and the second time:

?[bd][19][7f][08][02][00][00]@ [80]H$[12][00][04][00][05][00][04][00][04][80]@[80][01][00][10][00]@[00][80][08][00][09][10][10][00][00]@[80][00]H[00]@[00]$[90][00]D[00][09][00][10][82][00][00][00][00][00][00][00][04][00][00][08][00][08][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00][00]AT [00][00][00][00][00][00][00]

I've absolutely no idea what this is but it looks like the cellular module is resetting: you will see that, after the first case, the log shows:

ATE0
ATE0

This is AT-echo having come back on again (i.e. ubxlib only sent one ATE0, and that out-going command was echoed straight back to it); this can only happen if the cellular module has reset, since AT echo is switched on by default at power-on and the very first thing ubxlib does is switch it off.

There is nothing that ubxlib is doing to cause this: it would be worth you investigating the HW to see what might be upsetting it.

atiaisaac commented 3 days ago

Yes I am using that preview branch. And I do agree that there's something weird going on. Upon running it a second time, this is the output log this time round.

AT
AT
AT
AT
U_CELL_PWR: powering on.
AT
AT
AT
AT
AT
AT
AT

OK
U_CELL_PWR: powering on, module is alive.
ATE0
ATE0

OK
AT+CMEE=2

OK
AT+UDCONF=1,0

OK
ATI9

23.60,A01.01

OK
AT&C1

OK
AT&D0

OK
AT&K0

OK
AT+UPSV=1,1300

OK
AT
AT

OK
AT+UGPRF?

+UGPRF: 2,0,""

OK
AT+CFUN=0

OK
AT+UGPS?

+UGPS: 0

OK
AT+UGPS?

+UGPS: 0

OK
AT+UGPS?

+UGPS: 0

OK
AT+UGPS?

+UGPS: 0

OK
The connected GNSS constellations are: 69 // hex 0x45
AT
AT

OK
AT+CMUX=0,0,,128

OK
ATE0
ATE0

OK
AT+CMEE=2

OK
AT+UPSV?

+UPSV: 1,1300

OK
AT+UPSV=0

OK
U_GNSS: initialising with ENABLE_POWER pin not connected, transport type Virtual Serial.
ATI

SARA-U201-03B-00

OK
AT+UGPS?

+UGPS: 0

OK
AT+UGPIOC=23,3

OK
AT+UGPIOC=24,4

OK
AT+UGIND=0

OK
AT+UGPS?

+UGPS: 0

OK
AT+UGPIOC=23,3

OK
AT+UGPIOC=24,4

OK
AT+UGPS=1,15,127

ERROR
AT+UGPS=1,15,127

ERROR
AT+UGPS=1,15,127

ERROR
AT+UPSV=1,1300

OK
GNSS network did not come up
U_CELL_NET: preparing to register/connect...
AT
AT

OK
AT+CREG=2

OK
AT+CGREG=2

OK
AT+CIMI

I am tempted to think it is more of a hardware issue.

RobMeades commented 3 days ago

Ah, that's a lot better. The issue now is the 127 in the AT+UGPS=1,15,127 command: it selects the GNSS systems to be used and, depending on the cellular module and the GNSS module, it can behave differently. ubxlib generally asks for all of them by default (so 0x7f/127) and most of our cellular modules will enable as many of the GNSS systems as they can, in a best effort kind of way (then you can read back which ones it actually enabled). However, some of our cellular modules don't, they require you to set only ones that the GNSS device supports.

In this case I think that SARA-U201 is doing the latter, so we need to set the 127 to the right number. I'd suggest for the moment setting it to just 1, which is the GPS system. Can you try again, compiling ubxlib with the conditional compilation flag U_CELL_LOC_GNSS_SYSTEM_TYPES set to 0x01?

atiaisaac commented 2 days ago

So I am still getting the same error when I changed to 0x01 and recompiled ubxlib and after doing some digging, it appears sara u201 is not able to maintain gpio23 (my power pin to gnss module) at high voltage. It provides a high and shortly after goes low.

RobMeades commented 2 days ago

Hmph. It so happens that I have a board with a SARA-U201 and an M8 (not sure which sort) on it in front of me, let me see if it works for me.

RobMeades commented 2 days ago

Darn, no, the M8 on the board I have is connected directly to the MCU and not to SARA-U201. Let me try a different approach...

RobMeades commented 2 days ago

While I try to get a setup similar to yours here, it seems to me that the most likely issue, from your description, is that the cellular module is unable to communicate with the GNSS device over I2C: that would fit with it turning the power to the GNSS device on and then turning it off again when it has failed to communicate.

Do you happen to have anything like a Saleae probe that you could monitor the I2C lines between the cellular module and the GNSS device with, so that we can see what is going on there?

RobMeades commented 1 day ago

I can confirm that powering up an M8 module attached to a SARA-U201 module works for me here, see AT log below of exampleLocGnssCell() running, so I think the next step would be to monitor the I2C interface between the SARA-U201 and the M8 to find out what is happening there.

2024-07-03 08:51:57 U_CELL_PWR: powering on, module is alive.
2024-07-03 08:51:57 ATE0
2024-07-03 08:51:57 OK
2024-07-03 08:51:57 AT+CMEE=2
2024-07-03 08:51:58 OK
2024-07-03 08:51:58 AT+UDCONF=1,0
2024-07-03 08:51:58 OK
2024-07-03 08:51:58 ATI9
2024-07-03 08:51:58 23.60,A01.06
2024-07-03 08:51:58 OK
2024-07-03 08:51:58 AT&C1
2024-07-03 08:51:58 OK
2024-07-03 08:51:58 AT&D0
2024-07-03 08:51:58 OK
2024-07-03 08:51:58 AT&K0
2024-07-03 08:51:58 OK
2024-07-03 08:51:58 AT+UPSV=1,1300
2024-07-03 08:51:58 OK
2024-07-03 08:51:58 AT
2024-07-03 08:51:58 AT
2024-07-03 08:51:58 OK
2024-07-03 08:51:58 AT+UGPRF?
2024-07-03 08:51:58 +UGPRF: 2,0,""
2024-07-03 08:51:58 OK
2024-07-03 08:51:58 AT+CFUN=0
2024-07-03 08:51:58 +UMWI: 0,1
2024-07-03 08:51:59 +UMWI: 0,2
2024-07-03 08:51:59 +UMWI: 0,3
2024-07-03 08:51:59 +UMWI: 0,4
2024-07-03 08:51:59 OK
2024-07-03 08:51:59 Opened cellular device with return code 0.
2024-07-03 08:51:59 Bringing up GNSS...
2024-07-03 08:51:59 AT+CMUX=0,0,,128
2024-07-03 08:51:59 OK
2024-07-03 08:52:00 ATE0
2024-07-03 08:52:00 OK
2024-07-03 08:52:00 AT+CMEE=2
2024-07-03 08:52:00 OK
2024-07-03 08:52:00 AT+UPSV?
2024-07-03 08:52:00 +UPSV: 1,1300
2024-07-03 08:52:00 OK
2024-07-03 08:52:00 AT+UPSV=0
2024-07-03 08:52:00 OK
2024-07-03 08:52:00 U_GNSS: initialising with ENABLE_POWER pin not connected, transport type Virtual Serial.
2024-07-03 08:52:00 ATI
2024-07-03 08:52:00 SARA-U201-04B-00
2024-07-03 08:52:00 OK
2024-07-03 08:52:00 AT+UGPS?
2024-07-03 08:52:00 +UGPS: 0
2024-07-03 08:52:00 OK
2024-07-03 08:52:00 AT+UGPIOC=23,3
2024-07-03 08:52:00 OK
2024-07-03 08:52:00 AT+UGPIOC=24,4
2024-07-03 08:52:00 OK
2024-07-03 08:52:00 AT+UGIND=0
2024-07-03 08:52:00 OK
2024-07-03 08:52:01 AT+UGPS?
2024-07-03 08:52:01 +UGPS: 0
2024-07-03 08:52:01 OK
2024-07-03 08:52:01 AT+UGPIOC=23,3
2024-07-03 08:52:01 OK
2024-07-03 08:52:01 AT+UGPIOC=24,4
2024-07-03 08:52:01 OK
2024-07-03 08:52:01 AT+UGPS=1,15,127
2024-07-03 08:52:02 OK
2024-07-03 08:52:02 U_GNSS: sent command b5 62 01 07 00 00 08 19.
2024-07-03 08:52:02 U_GNSS: decoded UBX response 0x01 0x07: e8 03 00 00 dd 07 09 01 00 00 01 f0 ff ff ff ff 00 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 98 bd ff ff ff ff ff ff 00 76 84 df 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 20 4e 00 00 80 a8 12 01 0f 27 00 00 ac 4c 22 00 00 00 00 00 ff 00 00 00 [body 92 byte(s)].
2024-07-03 08:52:02 U_GNSS: sent command b5 62 01 07 00 00 08 19.
2024-07-03 08:52:03 U_GNSS: decoded UBX response 0x01 0x07: d0 07 00 00 dd 07 09 01 00 00 02 f0 ff ff ff ff 00 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 98 bd ff ff ff ff ff ff 00 76 84 df 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 20 4e 00 00 80 a8 12 01 0f 27 00 00 ac 4c 22 00 00 00 00 00 ff 00 00 00 [body 92 byte(s)].
...
atiaisaac commented 1 day ago

The closest thing I have is an oscilloscope; and taking a look at my circuit, it appears the pullup resistors for the i2c bus on the GNSS side is absent. That is the only reason I can think of at the moment. But I could swear that the datasheet for neo-m8u mentioned something about internal pullups already on said i2c line. Either way I am just going to hand solder some resistors on that line and try again.

RobMeades commented 1 day ago

I am just going to hand solder some resistors on that line and try again.

Sounds sensible.