[Ovmsdev] SIM808/SIM908 GPS accuracy
mark at webb-johnson.net
Thu Feb 2 14:23:10 HKT 2017
First I’ve heard of this, but it doesn’t surprise me.
Testing this sort of stuff is not particularly easy. What we have done in the past is put in a DIAG mode command to allow this function to be called with a given string parameter, and then to print the result. Then, we can script up something to feed in a bunch of input and see what the output is like. But, that does require physical hardware.
Perhaps also the function could just be run in a standalone C program on the mac? So long as the type sizes are the same, the results should be equivalent (perhaps with some float rounding differences in the original version).
> On 2 Feb 2017, at 4:38 AM, Edward Cheeseman <cheesemanedward at gmail.com> wrote:
>> On 23/01/2017, at 8:12 PM, Edward Cheeseman wrote:
>> I’ve started rewriting gps2latlon() to use a long long (64bit) integer multiply and divide.
>> I see reference to SIM808 and 908 on an arduino shield, so I might have a look to see what they have done.
> I totally overestimated the pic18F capability.
> So it turns out the C18, and for that matter, the XC8 compilers treat long long the same as long - 32bit.
> This of course isn’t news to anyone who has been working with this processor.
> So, given the floating point library has been pulled in anyway, I think the current implementation isn’t too bad.
> Floating point accuracy:
> - The equatorial circumference of the Earth is 40,075,017 meters.
> - Divided by 23bit, resolution is 4.8meters
> The math is probably unrounded, so probably the best you could hope for is within 10 meters.
> I think the following is an improvement in speed (no divides), variables used and accuracy (should be as good as received from the GPS), but these claims are yet to be proved. Readability has taken a hit.
> I’ve tried to set up the ide on a mac. I’ve got it to compile with the following code but haven’t tested it yet (can’t figure out how to simulate or view assembler output, don’t have a programmer)
> If you think this is worth adding in please point me in a direction that I can test it. At some point I will get a programmer, but I only have the one unit for my car so bench testing is a bit hard.
> --------------utils.c snip--------------------
> // Convert GPS coordinate form to internal latlon value
> // SIM908: DDDMM.MMMMMM (separate South/West handling, see net.c)
> // SIM808: +-ddd.dddddd
> long gps2latlon(char *gpscoord)
> signed int degrees;
> unsigned int rem;
> long frac;
> char *s;
> degrees = atoi(gpscoord); //use built-in to read integer value
> #ifdef OVMS_SIMCOM_SIM908 // SIM908: DDDMM.MMMM
> frac = degrees % 100; // extract minutes
> degrees /= 100; // fix degrees
> rem = 4;
> #define GPS_DIVIDER ((unsigned long) 3221225) //(3600 * 2048 / 600000) * 2**18
> #else //SIM808: (-)DDD.DDDDDD
> frac = 0;
> rem = 6;
> #define GPS_DIVIDER ((unsigned long) 1932735) //(3600 * 2048 / 1000000) * 2**18
> #endif //OVMS_SIMCOM_SIM908
> if ( (s = strchr(gpscoord, '.')) )
> while (*++s) //read and scale fractional part
> if( (unsigned char)(*s - '0') > (unsigned char) 9 )
> break; //check for non-decimal
> frac = frac * 10 + (*s - '0');
> if(--rem==0) //check for too many decimal places
> while (rem--!=0) //make up missing digits with zeros
> frac = frac * 10;
> //fractional part is at most 20bits (999999 < 2^20)
> //multiply 10bits at a time with 22bit constant to keep within 32bits
> //then bit shift into place and accumulate
> //(reuse rem here to reduce memory requirement)
> rem = (unsigned long)(((int)frac & 0x03FF) * GPS_DIVIDER) >> 18 ;
> frac = (((frac & 0x000FFC00)>>10) * GPS_DIVIDER) >> 8 ;
> frac += rem;
> if(degrees <0)
> frac = -frac;
> return degrees * 2048 * 3600 + frac;
> --------------utils.c snip end--------------------
> OvmsDev mailing list
> OvmsDev at lists.teslaclub.hk
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the OvmsDev