-
Notifications
You must be signed in to change notification settings - Fork 964
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
GPS: short update intervals, lock-time prediction #4070
GPS: short update intervals, lock-time prediction #4070
Conversation
Identifies a case where the GPS hardware is awake, but an update is not yet desired
I basically see the same behavior as before. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still needs work.
Not quite identical to the previous log. DEBUG | 20:55:15 8012 [GPS] GPS Lock took 8012, average 19 |
Looking at it again this morning, I can see that I've now accidentally bypassed this section of code, which definitely needs some attention. I don't think this is related to what you're seeing though? It's strange.. from that log output it looks like it's still falling through With this PR code, once it has hit that point, it seems like it has no choice (if else) but to call At the top of I can't actually see any path the code can take which matches your log output, but I might be overlooking something. Just to eliminate it as a possibility, is there any chance you pulled master again, rather than code we're working on from this pull request? I'm not sure why you're seeing The significant part of that section which I bypassed yesterday was a piece of code which aims to prevent one abnormally long lock-time from upsetting the average value. I think moving that code up to Line 889 would achieve the same behavior as before da5bca3? Right now, it keeps track of the "total time searching for lock" and "number of GPS updates", dividing the two. I'm nervous to suggest changing the code, and I'm not sure if it's worth looking at, but I actually wonder if we might get a quicker response by doing the same thing we do with the ADC readings. The original author of that section had called it a "virtual low pass filter". average = (old + latest) / 2; If possible, I think it'd be really valuable to hear from @jp-bennett about everything too. I probably should have gone straight to them for advice at the beginning; sorry about that. |
I cloned your repo and copied your GPS.cpp and GPS.h into my local folder then rebuilt the code and downloaded it to my device. More new code wierdness: INFO | 02:11:59 56 [GPS] updatePosition LOCAL pos@6667b270, time=1718071919, latI=388981961, lonI=-1075740508, alt=1914 Look here..... DEBUG | 02:12:03 60 [GPS] hasValidLocation FALLING EDGE (last read: 1) |
Any help from any source would be appreciated. |
I'm just really confused why there's no I'll look at it again with fresh eyes in an hour or two and see if anything jumps out at me. I'd want to try adding extra log at every step in between those two, but I actually can't reproduce the fault here on my T-Beam v1.2 to test:
Do you think you can try adding some extra logging on your machine through |
Those line numbers don't correspond to what I have, let me view your repo and compare it to what I've got. |
That's it When I cloned your repo I didn't check out the frequent updates branch, I had looked at GPS.cpp and saw they were different so used your GPS.cpp and GPS.h. Let me fix that and re check. |
Hey it's good we had to slow down and take a close look at it though or I would have missed that I had accidentally bypassed the code for "recovering from a long lock-time". I'll have a go at that later on and hopefully we can finish this off. |
Code which aimed to reduce the impact of outlier lock-times was probably affected by da5bca3. It think it may have relied on the fact that there was no distinction between what is now The previous system kept track of the "average lock time", and manipulated this manually if it became exceedingly long. Rather than re-implementing this, I found it conceptually easier to move to an exponential smoothing system. This is the same mechanism we are using to smooth ADC readings. The "predicted lock-time" is affected gradually by new lock-time values. A 20% weighting seems to give a reasonable balance between stability and response, but this could certainly be adjusted. prediction = (newLockTime * 0.2) + (prediction * 0.8); This does go beyond the PR's original scope of"fixing a bug". Ideally I would have avoided changing behavior, but this did feel like the easiest way to build back in the feature of handling these outliers. Please let me know if you have concerns, and we can rework this. As some assurance, I've compared the difference between the proposed "exponential smoothing" system, and the old "averageLockTime" system. Test conditions: T-Beam V1.2, indoors, 120s update interval, 80 minutes runtime.
Reading this comment again, I'm worried that it could have come across wrong. Just want to be clear that I didn't want to minimize anyone's input; I had just noticed in the git history that JP Bennet had worked on this area of the code a few months ago. |
@todd-herbert keeping an eye on this. Need to give it a test still. The initial rolling average method was crude, but generally worked. Glad to see something a bit more sophisticated. I'd like to take some time to dive into this, but don't wait on me to pull it. |
Making sure I got the proper code this time ;>)) I'm seeing expected behavior with GPS Update Interval at 10 sec. One thing I noticed is this code does not send a PMREQ with duration 0 to the GPS when Deep Sleep is initiated. I have been tracking down why the GPS kept running after this (in master) for a while and have found that the ESP32 goes into Deep Sleep before the command is finished being sent to the GPS. In addition in Deep Sleep the TX signal to the GPS goes to a low state which wakes the GPS up (if it were asleep) and caused massive frameing errors. Haven't done any testing with NRF52 as yet. |
That is the current behavior with 10 sec or less. |
With many DIY devices, the GPS is powered without a dedicated GPS power switch, sending the PMREQ would achieve a Deep Sleep like power reduction for those u-blox GPS devices. I believe that was the original intent, but with the Tx staying low and the command not completing, that doesn't work. |
I'll admit, I haven't dived super deep into all that, and I'm not sure I'm set up to test it here, but it's definitely something we need to sort out. I'll go take a look and see if I can spot anything obvious going wrong. |
Does your code intend to send a PMREQ on Deep Sleep? If so, IMHO that is the first problem to solve. I watched the serial Rx line of the GPS with a USB-Serial module with Minicom set to display Hex and wrap long lines, so I could see what was sent to the GPS.The ESP32 line going low can be fixed using gpio_hold_xxx commands, but this may expose a bigger issue of many different gpios are used for GPS Rx & Tx in various devices, How deal with that as well as how other peripherals might deal with floating outputs in Deep Sleep. |
Actually, is this something that got broken just now, or something that's been around for a while? If it's a separate issue, I might be keen to wrap this bug-fix up and tackle the PMREQ TX pin thing separately in the next few days? It'd definitely be top of my pile to work on, while all this GPS stuff is still fresh in my memory. Bonus: if something goes horribly wrong, it'll be easier to spot which PR did it.. |
Your previous version of the GPS.cpp did try and send a PMREQ and that code is still there, but I didn't see a PMREQ being sent when I put my device into Deep Sleep with the latest version. It could be that the ESP32 went to sleep sooner and the command never even started to be sent. |
I'm going to call it a night for now, but I've taken a shot-in-the-dark at getting that duration 0 PMREQ to send. I don't know if there will still be an issue with the MCU sleeping too soon, and nothing yet about holding the GPS_TX pin high, but do you think you could check if this one change is enough to get the PMREQ to send? |
I'll try to check it out before DayJob calls... |
No rush, I'll be back tomorrow 👋 |
Nope, no PMREQ at DeepSleep. ;>(( |
The Log entry "Sleep Time 0" is missing, Line 858. |
I think I've pulled out a bit of code that really needs to go back too. I'd better stop making ill-advised guesses now and wait until I can put everything back where it's meant to be, and look at it again properly. Sorry about all that. |
Hey, this isn't quite a "Ready, Fire, Aim" situation, so don't sweat it... |
I'm just looking taking a closer look at the GPS power stuff. It feels like it's been tacked on-to (exactly like we're doing here) for the past four years. I'm struggling to come up with an elegant code-path through the layers of previous fixes and features. It's also leading me back into Sleep.cpp, and there's a little bit of the same thing happening there with the Observables. Rather than bore a new hole through the code to get the GPS hardware deep-sleeping, I'm more and more tempted to suggest leaving this PR where it is, as a temporary bug fix, and planning out a major refactoring of the GPS power stuff, if that's something @jp-bennett, @thebentern, and @GPSFan would support. I'm not at all familiar with the low-level magic that goes on to support all the different GPS hardware, so it's something I'd need a lot of help / input with, unless anyone else is up to the task and wants to take charge. I'm more than happy to contribute to this, within my ability. Not a design pattern I've ever used before, but I could imagine something very similar to the PowerFSM working well here. It could greatly simplify the logic when moving all this hardware between these different states. Dare I say it, I think Sleep.cpp might need another tidy up too to support this. Some of the Observables are being notified twice, never notified at all, or followed up with duplicate code inside of Sleep.cpp itself. I'd be quite nervous to start tidying there though, given how badly it went last time I tried. Part of supporting this GPS power-saving would be manipulating GPIOs for deep-sleep, tidying or no tidying, which means it'd want a whole lot of very careful testing / oversight either way. |
A temporary fix now and bigger refactor later is the way to go. But PowerFSM is actually terrible and is one of the things that kills our ram allocation. It uses a bunch of realloc()s internally, that just wastes memory. |
I agree, a temp fix now and then a deep look at the whole GPS power management/sleep/wake structure. |
That's actually really good insight, and something I'd never realised. Thanks!
Sorry, I didn't pay pay quite enough attention to what your messages were saying. Let's wrap this fix up and then look at the power-saving stuff soon. |
Addresses #4067
Currently, a
position.gps_update_interval
of 10 seconds or less is not correctly handled.This PR refactors the
GPSPowerState
enum to mark this case, and prevent back-to-back position updates occurring.Pretty sure this fixes it, but please do double-check my work, so we don't have round-two of this issue..