Buggy GPS code for the EM406

Hi all.

I was messing around with my simulator some time ago, and found that the ground course, returned from the binary GPS decoder, in GPS_EM406.pde returned false heading between 300 and 360 degrees. This is also mentioned in the comment.

The problem is that the number returned from the GPS module is returned times 100, as the comment suggest, this means values between 0 and 36000.

if(ground_speed >= 50){

//Only updates data if we are really moving...

intUnion.byte[1] = gps_buffer[j++];

intUnion.byte[0] = gps_buffer[j++];

ground_course = intUnion.word; // degrees * 100

ground_course = abs(ground_course);//The GPS has a BUG sometimes give you the correct value but negative, weird!!

}else{



Since the integer used in the intUnion is a 16 bit signed integer, only numbers up to 32768 is supported, this fact yields negative values when the value is above, from the bit pattern interpretation.


The solution is to use the longUnion instead of the intUnion. This solves the buggy ground course.



if(ground_speed >= 50){

//Only updates data if we are really moving...

longUnion.byte[1] = gps_buffer[j++];

longUnion.byte[0] = gps_buffer[j++];

ground_course = longUnion.dword; // degrees * 100

//ground_course = abs(ground_course); //The GPS has a BUG sometimes give you the correct value but negative, weird!!

}else{


I hope that this helps somebody.


Best regards

Niklas

E-mail me when people leave their comments –

You need to be a member of diydrones to add comments!

Join diydrones

Comments

  • Developer
    Thanks again for finding this.
  • No, as far as I have know, the only buggy reading was in the ground course. The rest should work correctly.
  • Hi Jason,
    Looking at Niklas code that the top shouldn't these be longUnion?? not intUnion??
    Also just below this code there is also :-
    j = 45;
    intUnion.byte[1] = gps_buffer[j++];
    intUnion.byte[0] = gps_buffer[j++];

    should these be longUnion too??

    Tony
  • Developer
    This would be a great bug report for the Issues list on the google code site.
    http://code.google.com/p/ardupilot/issues/list

    The correct code should be :
    if(ground_speed >= 50){        //Only updates data if we are really moving... 
    intUnion.byte[1] = gps_buffer[j++];
    intUnion.byte[0] = gps_buffer[j++];
    ground_course = (unsigned int)intUnion.word; // degrees * 100
    }
  • Developer
    Ok, so it should be an unsigned int union. I'll make the update. This is a really old bug, before my time. Nice catch.
  • That's right Jason. Actually a unsigned integer would do the job. As far as I know there isn't a way to use a union to produce a three byte number. The easiest thing is just to use the long union, from already existing code. And just set the two least significant bytes (byte 2 and 3 will remain 0x00). This produces the right result.
This reply was deleted.