News:

PROTON pic BASIC Compilers for PIC, PIC24, dsPIC33

Main Menu

FP but with only three of four bytes?

Started by SCV, Jan 26, 2022, 10:25 AM

Previous topic - Next topic

SCV

A GNSS/AHRS module supplies me three 32bit FP variables for latitude, longitude as signed degrees and minutes (ddd mm.mmmmmm) and elevation as +/- metres. I can read them, show on LCD etc so happy with that, but need to forward them over a telemetry link which only has 9 spare bytes arranged as 3x 24bit variables. There are a few options...

1) If I dropped the low byte of each FP variable, I would decimate the mantissa resolution but still have 15bits to resolve a reasonable accuracy. But how accurate?

2) Send degrees as signed (9bits), send minutes multiplied up by 100 to get two decimal points worth into 15bits. Resolution is 1/100 of one minute or 1/100 of one Nautical Mile (+/- 18.52 metres).

3) Employ a multiplexing method where each FP is encoded in turn. Time resolution falls off which could have an impact!

4) Compression?


The project is to run on 16bit dsPIC/PIC24. I would like the highest resolution possible that can fit in 9bytes. The telemetry packet is only sent every 16.6 or 20mS (video frame rate), GNSS/AHRS updates much quicker.

Any suggestions welcome.

Thanks,
Tim.

top204

#1
You could use a fixed point type format based upon the original Floating Point value, for transmission. But not a true Fixed Point for calculations etc. It will be more accurate because it will be a representation of the Floating Point value

For example, the value 52.1234 would be transferred to 3 bytes, where the first byte contains the integer value "52", and bytes 2 and 3 contain the integer value "1234". The decimal point will always be after the first byte within the format, so you could have the values -128 to 127 . 0 to 65535. If you want the resolution to be a little less, you could have the whole number as a signed integer 16-bit value, and the fraction as a byte variable, then you would be able to hold the values -32768 to 32767 . 0 to 255.

For less resolution, you could convert it into a 8x8 fixed point, instead of the 16x8 or 8x16 format, or 7x8 or 15x8 or 7x16 for signed fixed point. With fixed point, the left and right values of the decimal point are always in the same positions and always take the same amount of bytes, so the decimal point's position is always known. Converting it back to true floating point once it has been transmitted is simplicity itself. :-)

For the time, it will fit into a 3 byte BCD format for Hours/Minutes/Seconds.

trastikata

In my GPS telemetry over LoRa applications, I convert the NMEA coordinates to FP degrees and then the degrees become signed 32b integers.

In your case you need only 8 bytes to transmit the Latitude and Longitude including the hemispheres (N/S and W/E):

- Convert the coordinates to FP degrees only
- N and E become positive, S and W become negative
- Multiply by 10 000 000  to keep the maximum possible 7 digits accuracy
- Pass the integer values to two signed DWords
- Pass the 8 bytes from the DWords to 8 of the 9 free bytes
- Transmit the 9 bytes as 3x24bit variables
- Reassemble the DWords from the received 3x24bit variables
- Recover the coordinates from the signed DWords

Cheers.

SCV

Thanks for your ideas, but a couple of things, signed longitude requires 9bits (its +/- 179 degrees) and although lat & lon can be compressed to 8bytes, there still remains the altitude.

I did consider converting degrees & minutes to minutes then multiplying up to get as many digits past the decimal point as possible.
eg 151 degrees 12.1234 minutes E = 9072.1234 minutes E
9072.1234 * 100 = 907212 centi-minutes!
One centi-minute equates to 1/100 of a minute or around 18 metres - a bit too corse and I would have liked to multiply up by 1000.

My thoughts were to use a FP variable and chucking half the mantissa away but I was struggling to work out the likely error/resolution as per Les' information.

Tim

trastikata

#4
Ok, I missed the altitude requirement. My suggestion, if I may, is to drop the floating point and use integers with bit manipulation, here's a thought.

Convert (ddd mm.mmmmmm) to (ddd.dddddd)

You have 9 bytes spare or 72 bits in total:

8  bits represent degrees for Longitude (0 to 180) - up to 10110100
7  bits represent degrees for Latitude (0 to 90) - up to 1011010
1  bit for E/W
1  bit for N/S
14 bits for Altitude ( 0 to 16383) - up to 11111111111111
1  bit for Altitude sign
20 bits for Longitude degrees fractional part as integer with 6 digits precision (Note1) (0 to 1048575) - up to 11111111111111111111
20 bits for Latitude degrees fractional part as integer with 6 digits precision (Note1) (0 to 1048575) - up to 11111111111111111111
   
Total 72 bits or 9 bytes used.

Note1: ddd.dddddd - the fractional part is represented as an integer, i.e. 89.999999 - get 999 999 which is less than 1 048 576 and can fit within 20 bits.