-
Notifications
You must be signed in to change notification settings - Fork 93
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ESP-IDF with GNSS over I2C with bus already open #194
Comments
Hi there, and sorry you're having problems with this. The effect of setting The implementation of uPortI2cAdopt() for ESP-IDF just calls the Can you confirm that at least i2c_driver_install(), and probably i2c_param_config(), have been called before |
I can confirm the i2c bus is correctly configured as GNSS shares the bus with 10 other peripherals which are working fine. From tracing, i have managed to isolate the cause in the send() function from u_port_i2c.c, line 204, which is a bit weird (did not do bus sniffing yet). In fact, several commands are sent over to the GNSS device via i2c_master_cmd_begin however only one returns ESP_TIMEOUT hence the write fails according to ESP-IDF I made sure there are no other tasks competing for i2c bus, but afaik esp-idf has mutexes on i2c_master* functions and are thread safe. In any case, my i2c init code:
with looks the same as the uPortI2cOpen When it's not working i get from the lib: U_GNSS: sent command b5 62 0a 06 00 00 10 3a. But when i let ubxlib handle the idc, i get an answer to that U_GNSS: decoded UBX response 0x0a 0x06: 0e 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 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 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [body 120 byte(s)]. |
Hmph, that is very odd. When there's an I2C issue ESP-IDF usually spits out some log text of its own: do you see anything of that nature when this problem occurs? EDIT: which version of ESP-IDF is this with, just for information? |
Maybe this is just a typo, but in your I2C init code that you pasted-in above you have:
...whereas in the
|
Not a typo, just wrong section of the code ... i use both i2c hardware ports with same settings but different pins, that's just the initial config object with the I2C0 pins, i have I2C1 pins later in the code ;-) ESP-IDF is 5.1.2 |
You are on a slightly later version of ESP-IDF than we test with; we test with 5.0.1, had to stop there because something went wrong inside ESP-IDF for one of our module types, meaning that ESP-IDF no longer recognizes the flash. But ESP-IDF is usually pretty good about backwards-compatibility and any major changes would likely have landed in v5, not in v5.1. If you are able to, I think sniffing is the thing. Should you be able to Saleae probe it, we can read that. |
Best i can do is Digital Discovery 2 :) |
On the DD2 trace, i see diferent behavior (device is on 0x42): With I2C Port already initialized before: Start, h85 [ h42 | RD ], Error! WIth ubxlib handling i2c initialization: |
Looks like my calculation of the i2c_set_timeout value was wrong and not enough. Sorry for the confusion :) |
Ah, is this the ESP32S? If so Espressif changed the way timing works on that chip but didn't document it...? EDIT: this was the Github issue that resolved it: espressif/esp-idf#11397 (comment). |
It's not an S but looks like 5ms timeout was not enough, i did not look at the NEO9 datasheet in depth, perhaps this is not enough, as my other peripherals work fine, hence the confusion :) |
Got it, glad it is working for you now. |
Thanks for your time, closing issue |
@RobMeades Looking at this issue further, but I cannot seem to find any useful info in any of the M9 datasheets, whith the higher timeout set, is it normal that M9 responds in about 1 second ? Thanks |
Section 5.3 of the NEO-M9N data-sheet would seem to be the reference for I2C timing, where the longest time value is the maximum of 20 ms clock stretching that the GNSS device might apply, so I wouldn't expect an I2C transaction to ever be longer than about that long. Maybe it depends which timeout we are talking of? Not sure I follow the picture, but the default "epoch" of the GNSS device, i.e. the interval at which it will try to make a navigation solution, emitting, say, a |
No need for faster location retrieval, however, the M9 shares the I2C bus with other devices which are read more often. Put aside the fact that uGnssPosGet has a timeout of 240 seconds waiting for a proper nav solution from the device, i did bypass the timeout mechanism. Long story short, out of cold start it takes some time for a proper solution, same happens when there's no sky visibility, antenna is disconnected, whatever. Let's take UBX-NAV-STATUS for example, i send that with uGnssMsgSend and it takes 1s for the device to respond and uGnssMsgReceive to actually return from the call. So it looks to me that at least both UBX-NAV-STATUS and UBX-NAV-PVT takes 1s, which makes sharing the bus a pain if i need other faster reads. Either i'm doing something wrong (config, whateaver) or that's how the device works, it's my first time with these devices and i have no spare pins on the CPU to have the M9 on it's own bus. What you're seeing in the picture above is exactly that, the command is sent: Start, h84 [ h42 | WR ], hB5, h62, h01, h07, h00, h00, h04, h0D, Stop and then it takes almost a second for the answer to be sent by the M9 Thanks |
Usually the times when you are polling with a command and awaiting a response would be the exception rather than the rule; e.g. for configuration-type transactions. Once done, the device would be set up to emit something, e.g. the location, periodically. Since you are using I2C the master still needs to pull the data, of course; if you're concerned about bus occupancy you could configure the GNSS device to set a |
How would this work ? Send a 0x1 0x03 message and don't read anything until TX_READY is asserted, and then send 0x01 0x03 message again and read back the answer immediately ? |
I started to write a reply to this but realised that I still don't fully understand the core of the problem. I will set some HW up and have a sniff of the I2C lines myself but, how it is meant to work, is that, when this code is expecting to receive something it calls uGnssPrivateStreamFillRingBuffer() which calls uGnssPrivateStreamGetReceiveSize() which, for I2C, reads the two bytes from address 0xFD of the GNSS chip that indicate how much data the chip has to send, then reads that data. So first there will be an I2C transaction which reads the amount of data that the GNSS chip already has in its output buffer, waiting to be sent, then there will be an I2C transaction to read that data. There should be no I2C transactions that take a whole second unless, for some reason the GNSS chip is indicating that it has data to send in its output buffer and then is not actually sending that data for some reason, or this code is somehow misinterpreting the length of the data. We need to bear in mind that the GNSS chip will, by default, also be emitting data in NMEA format, so this code will be reading that and throwing it away (it has to because the data it wants is behind it); if you care about bus occupancy and your application has no interest in NMEA-format data (this code doesn't use it) then you may switch it off with:
I'll go find the right HW and my probe... |
OK, I now have a MAX-M10S connected over I2C to an ESP32 and I'm calling uGnssPosGet() with no antenna connected. The debug output from
I've attached the Saleae capture (which you can read by downloading and installing their application if you wish). What you will see is patterns like this: ...i.e., since this is a blocking call and the underlying transport is I2C, there are polls to ask the GNSS device if it has any data to send and, about once a second, it does, hence the thicker parts in this zoomed-out trace. Zooming in to one of the polls, this is a "have you got any data to send? No I haven't" exchange: ...and this is a "have you got any data to send? Yes I have" exchange, i.e. at the start of one of the thicker blobs in the zoomed-out picture: Between the polls, the I2C bus is not occupied, you should be able to do other stuff, provided i2c_master_cmd_begin() is thread-safe, which it says it is...? EDIT: could the issue be that, when the GNSS code is trying to receive something, it tries really hard, resting for only 10ms between tries, which may be too short for another task of yours to get in? If this is the problem then a quick fix would be to make the duration of the wait a conditional compilation value that you could override? Or perhaps we could have two values (both as overridable conditional compilation flags), one for use when the I2C port is adopted and another for use when it is not, which would allow the former to be longer than the latter. |
Your trace and my trace look similar, i just wonder if the polling actually holds the bus mutex or not, as esp-idf i2c_master* are thread safe and mutex enabled. I did a bit of testing with having EXTINT pin assert when data is ready, i just can't figure out how to properly read that data over i2c, as if i send a receive message with 0x0107 it just polls the device for one second again before receiving the data (it's either that or i really screwed something up while testing this). Long story short during that second needed for the polling, it's pretty much stopping my task. Disabling NMEA and just sticking to UBX helps a very little, during data read, but the second it takes to actually receive the data is something i can't seem to find a good solution (yet) to get around. |
Understood: as an experiment, could you try hacking the 10 ms here to be, say 50 ms or 100 ms and see if that helps? If it does, we know that it is the I2C "do you have any data" poll rate that is getting in your way and I will make it properly configurable. |
I'll try just to confirm, maybe in th is case, the workaround would be to have a separate task read the GNSS while another task holds the mutex and does all the dirty i2c jobs ... in the end, if it works, it works, just a matter of propagating a variable delay based on what's expected from the device, since not all messages take ~1s to get an answer Keep you posted |
Hi @synologic , I’m currently working on integrating ubxlib with ESP-IDF for my project, and I noticed your successful integration mentioned in issue #194. I would greatly appreciate it if you could share some insights on the integration process you followed. Specifically, I’m interested in:
Any additional tips or guidance you could provide would be extremely helpful. |
@nasihnazer ubxlib already works with ESP-IDF 5.1 (tested) it does not work with 5.3 due to i2c driver, not sure about 5.2 but i think it doesnt. All i did was to copy ubxlib to my project root, then i just copied CMakeLists.txt and component.mk from ubxlib/port/platform/esp-idf/mcu/esp32/components/ubxlib/ to a folder called "ublox" in my project's components folder and required it in my main's CMakeFiles.txt ... nothing else, it just works (tm) |
Hi @synologic , Thank you for your guidance on integrating ubxlib. I followed your instructions and tried various methods to resolve the build issues, but I’m still encountering problems. Despite my efforts, I haven’t been able to get it to work. Could you please provide detailed steps on integrating ubxlib? Any additional help or specific advice would be greatly appreciated. Thank you! |
If you encounter issues with using ubxlib it may be a good idea to open a separate issue rather than polluting this issue |
I’ve already opened a separate issue regarding the problems I’m facing with ubxlib. To better understand and resolve the issues, could you please share the detailed steps you followed while integrating ubxlib into your project? Any specific configurations or adjustments you made would be very helpful. is this the steps you followed to integrate ubxlib |
Hi all,
i'm having an issue when trying to initialize a NEO9 via i2c, where my application has already initialized the I2C bus:
returnCode is U_ERROR_COMMON_PLATFORM
If i try the same but with alreadyOpen set to false, there's no problem
Any suggestions ?
Thanks
The text was updated successfully, but these errors were encountered: