![]() |
Forum Index : Microcontroller and PC projects : Updated Boat Computer
![]() ![]() ![]() ![]() |
|||||
Author | Message | ||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10315 |
If you are using the flat earth approximations (which use sqrt) it may be worth using the full versions (which don't) |
||||
davematt Regular Member ![]() Joined: 27/09/2011 Location: AustraliaPosts: 55 |
Geoff: Yes, version 2 uses the same 'Distance to POI' equation, which I believe is the problem. If my Excel sheet is correct, my location needs the POIs to be initialised to something more than 8 deg (lat and lon) and this will work for most of Australia. By the way, I shouldn't have called it a crash, the program actually exits gracefully with a useful error message and an automatic restart. Pretty impressive... Oh, and I hope others have as much fun as I have, chasing this tiny insect! Dave. |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6283 |
The problem appears if the difference in Latitude between the GPS location and the POI is greater than 39.5 degrees. Thats a long way to go to get a feed of fish. This replacement function has a simple sanity check to catch the SQR(neg) problem. variable a becomes greater than 1 so (1-a) is the problem. I added "IF a>1 THEN a = 1 'sanity check" FUNCTION POIDistance(POIlat AS INTEGER, POIlon AS INTEGER) AS STRING LOCAL FLOAT y, x, lat1, lat2, n, m, a 'if abs(POIlat-lat)<0.000001 then POIlat=lat lat1 = RAD(lat / 36000) lat2 = RAD(POIlat / 36000) n = RAD((POIlat / 36000) - (lat / 36000)) m = RAD((POIlon / 36000) - (lon / 36000)) a = SIN(m/2) * SIN(m/2) + COS(lat1) * COS(lat2) * SIN(n/2) * SIN(n/2) IF a>1 THEN a = 1 'sanity check n = (2 * atan2(SQR(a), SQR(1 - a))) ' convert the distance to the current units (nautical miles, kilometers, etc) SELECT CASE SpeedMode CASE 0 n = 3440 * n CASE 1 n = 6371 * n CASE 2 n = 3958 * n END SELECT ' convert the distance to a four digit string SELECT CASE n CASE >= 1000 POIDistance = STR$(n, 1, 0) CASE >= 100 POIDistance = STR$(n, 4, 0) CASE >= 10 POIDistance = STR$(n, 1, 1) CASE ELSE POIDistance = STR$(n, 1, 2) END SELECT END FUNCTION The function used for bearing and distance are really only valid for near distances. If you want to navigate to the other side of the world, other formulas are needed. If Geoff had used his Boat Computer when he visited Tasmania, he would have discovered the problem himself! I don't have a GPS (or boat) handy so my mod needs testing. Jim VK7JH MMedit |
||||
palcal![]() Guru ![]() Joined: 12/10/2011 Location: AustraliaPosts: 1993 |
I have only entered one POI so far and the distance works OK but the Port/Starboard heading was varying all over the place, it certainly was not directing me to my POI. I will enter some more POIs and do further checking. Paul. "It is better to be ignorant and ask a stupid question than to be plain Stupid and not ask at all" |
||||
davematt Regular Member ![]() Joined: 27/09/2011 Location: AustraliaPosts: 55 |
Jim, I should have thought of that... Paul, the bouncing is due to the gps calculating a direction traveled in the previous second, which for a stationary or slowly moving unit, does swing wildly. For a plane or car, no problem, but for a yacht or walking, annoying. My project this weekend is to add a rolling average function to the speed and direction result for exactly that reason... Dave |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6283 |
Paul, If your GPS is stationary, the natural movement of the GPS readings will make the 'mite think you are wandering about in all directions. That might explain the strange directions you are getting. Jim VK7JH MMedit |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10315 |
Rolling average of directions is hard because of going through from 359 to 0 Here is the way I do it - may save you some time ![]() '
' 'rolling average of angles (0-359) ' const MA=10 'number of elements in moving average array dim float angleSMAcos(MA-1),angleSMAsine(MA-1) dim integer temp%=0 ' 'rolling average of angles (0-359) ' ctemp=cos(rad(angle)) stemp=SIN(rad(angle)) angleMAc=angleMAc-angleSMAcos(temp%)/MA angleMAs=angleMAs-angleSMAsine(temp%)/MA angleMAc=angleMAc+ctemp/MA angleMAs=angleMAs+stemp/MA angleSMAcos(temp%)=ctemp angleSMAsine(temp%)=stemp angleMA=deg(atan2(angleMAs,angleMAc)) temp%= (temp% +1) mod MA |
||||
palcal![]() Guru ![]() Joined: 12/10/2011 Location: AustraliaPosts: 1993 |
I was travelling at about 20Kph. Paul. "It is better to be ignorant and ask a stupid question than to be plain Stupid and not ask at all" |
||||
davematt Regular Member ![]() Joined: 27/09/2011 Location: AustraliaPosts: 55 |
Hi Peter, many thanks for this, it would save me time if I could understand it. ![]() |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10315 |
Hope this helps '
' 'rolling average of angles (0-359) ' const MA=10 'number of elements in moving average array dim float angleSMAcos(MA-1),angleSMAsine(MA-1) 'set up 10 element arrays to hold the sine and cosine values dim integer temp%=0 'set the index to the next element to write dim float angleMAc 'variable to hold the moving average of the cosines dim float angleMAs 'variable to hold the moving average of the sines ' ' This section called each time the angle is updated ' ' 'rolling average of angles (0-359) ' ctemp=cos(rad(angle)) 'get the cosine of the new angle into a temporary variable stemp=SIN(rad(angle)) 'get the sine of the new angle into a temporary variable ' Now we remove from the rolling average of the sines and cosines the value in the array positions to be updated. ' In the example we have 10 readings in the moving average so we do this by subtracting 1/10th of the oldest value from each average angleMAc=angleMAc-angleSMAcos(temp%)/MA angleMAs=angleMAs-angleSMAsine(temp%)/MA ' Now we add into the two rolling averages 1/10th of the new value angleMAc=angleMAc+ctemp/MA angleMAs=angleMAs+stemp/MA ' Next we put the new values into the arrays so that in 10 loops time we can use them to remove from the avarages angleSMAcos(temp%)=ctemp angleSMAsine(temp%)=stemp ' We now convert the newly updated moving average sine and cosine values back to an angle ' Note we must use atan2 not atan in order not to lose information angleMA=deg(atan2(angleMAs,angleMAc)) ' Finally we update the index value for the next write, modulus the number of elements in the array temp%= (temp% +1) mod MA AFAIK this is the only completely robust mechanism of averaging angles such that the number of rotations is completely unconstrained |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6283 |
20k is certainly fast enough to minimise errors due to jitter. 20k/h is 5.5 metres second. GPS readings can drift up to 10 metres but rarely will they move more that a metre between readings. Geoff has code in place to detect very slow speeds but you are well above that threshold. Does the heading change much while you are traveling with the display in 'heading' mode? What is the location of your POI and what is your (approx) location? I wrote a Windows program to do much the same as the boat computer but gave up on it because I found it too risky, playing with computers while driving. I hope you are using a navigator.... Jim VK7JH MMedit |
||||
davematt Regular Member ![]() Joined: 27/09/2011 Location: AustraliaPosts: 55 |
Peter, I think I'm getting there... The attached is thanks to your help in several different areas, I'm sure you'll recognise the derivation. And yes, I would have completely missed the GPS solution. Back to work... ![]() |
||||
rogersan Regular Member ![]() Joined: 10/04/2015 Location: AustraliaPosts: 79 |
Hi Geoff Have you considered the option of displaying Grid References (Eastings and Northings) as an alternative to Lats and Longs to make the Boat Computer more useful on land? Roger Sanderson |
||||
palcal![]() Guru ![]() Joined: 12/10/2011 Location: AustraliaPosts: 1993 |
@ TassyJim Heading is OK in Heading mode. My location is 19.0277° S, 146.4167° E and I am heading to a POI only about one Km. away. Paul. "It is better to be ignorant and ask a stupid question than to be plain Stupid and not ask at all" |
||||
Geoffg![]() Guru ![]() Joined: 06/06/2011 Location: AustraliaPosts: 3292 |
Well no, this is a boat computer. As I understand it Grid References are referenced to some point - and there are lots of possible points. It sounds very complicated to me. One of the important features of these Micromite based projects is that you can get in there and change the code to suit your requirements. Now please don't misunderstand, I'm not trying to be cute here, but this sounds like a perfect opportunity for you to get in there and modify the code yourself and come up with a land specific computer. In fact I invite anyone, please feel free to improve the device and post the code here. Geoff Geoff Graham - http://geoffg.net |
||||
CircuitGizmos![]() Guru ![]() Joined: 08/09/2011 Location: United StatesPosts: 1427 |
Don't average the absolute angles, average the deltas/changes. Micromites and Maximites! - Beginning Maximite |
||||
davematt Regular Member ![]() Joined: 27/09/2011 Location: AustraliaPosts: 55 |
This can't be right! With a bit of smoothing the heading values settled down nicely at walking speed, but the compass needle behaved very strangely. So as a test, I disabled the GPS stuff, and set the main loop to increment the heading by one. The compass needle started pointed West, and then rotated smoothly a full circle in 60 degrees. As I say, this can't be right! Either I've made a silly mistake (v possible) or there is something amiss with the needle drawing routine. Please can someone smarter than me take a look? David |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6283 |
In the Function GetX(), change GetX = 250 + Cos(Rad(t * 6)) * r to GetX = 250 + Cos(Rad(t)) * r The same for GetY() change GetY = 160 + Sin(Rad(t * 6)) * r to GetY = 160 + Sin(Rad(t)) * r These Functions were use for a clock and still assumed 60 ticks per circle. In the Sub DrawCompassNeedle change ldeg = 90 - deg to ldeg = deg - 90 This puts the compass display in step with the bearing. I haven't tried to simulate the bearing to POI yet. Jim VK7JH MMedit |
||||
davematt Regular Member ![]() Joined: 27/09/2011 Location: AustraliaPosts: 55 |
Bingo!! Many thanks Jim |
||||
palcal![]() Guru ![]() Joined: 12/10/2011 Location: AustraliaPosts: 1993 |
@ TassyJim You asked if heading needle was steady in heading mode, I replied that it was but that was before I updated the code. When I was using Geoff's original Boat Computer Code I was running MM.V5.0 and the heading was good and steady both in heading mode and in POI mode. However I had the problem that the POI would not save. I updated to the new Boat Computer Code and also updated to MM.V5.1 and now I have the problem of the heading needle jumping all over the place. The actual heading readout in degrees is rock solid. I don't still have a copy of the original Boat Computer Code but maybe I can get it from Silicon Chip. I would like to reload it and see how it behaves with MM.V5.1 Paul. "It is better to be ignorant and ask a stupid question than to be plain Stupid and not ask at all" |
||||
![]() ![]() ![]() ![]() |
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |