PDA

View Full Version : Degrees to decimal conversion



RFsolution
- 12th November 2010, 20:54
Hi all

I have a decimal readout from a device which is giving me

a 16bit value (65535) for 1 resolution (360 deg)

I want to enter serially degrees.xx and convert this to a 16 bit value and also to a 12bit value

Decimal_value_16bit var word '(0-65535)
Decimal_value_12bit var word '(0-4098)
degrees var word '(0-360)
degrees_fraction var byte '(.xx)
serin2 rxd,84,[degrees,wait ".",degrees_fraction]

Any idea how this can be done ? pse I dont want to use "longs"

Darrel Taylor
- 13th November 2010, 17:52
No longs? ... We don't need no stinking Longs ... :)
But a little N-Bit_MATH will definitely help. http://www.picbasic.co.uk/forum/showthread.php?t=12433

To go from decimal degrees to 16-bit binary it would take ...

65535 * degrees / 35999
If you were using an 18F with PBPL ... that's all you would need.

But if you don't want LONGs, then ...
65535 * anything bigger than 1 will take more than 16-bits.
And since DIV32 is really DIV31/15 ... 35999 is too big for the divisor (max is 32767).
So N-Bit_Math to the rescue.


rxd var PORTC.7
txd var PORTC.6
HIGH txd

Decimal_value_16bit var word '(0-65535)
Decimal_value_12bit var word '(0-4098)
degrees var word '(0-360)
degrees_fraction var byte '(.xx)
degree_Total var word


'----[N-Bit Math]-----------------------------------------------------------
PRECISION CON 4 SYSTEM ; 4 bytes=32-bit
INCLUDE "N-Bit_MATH.pbp"

Temp1 VAR BYTE[PRECISION]
Temp2 VAR BYTE[PRECISION]

'----[Main Program Loop]----------------------------------------------------
Main:
serout2 txd,84,[13,10,"Enter Degrees (Max=359.99): "]
serin2 rxd,84,[DEC degrees,DEC2 degrees_fraction]
Degree_Total = degrees * 100 + degrees_fraction

ASM
MOVE?WP _degree_Total, _Temp1 ; copy degrees to a PVAR
MOVE?CP 65535, _Temp2 ; put multiplier in a PVAR
MATH_MUL _Temp1, _Temp2, _Temp1 ; Temp1 = DEG * 65535
MOVE?CP 35999, _Temp2
MATH_DIV _Temp1, _Temp2, _Temp1 ; Temp1 = Temp1 / 35999 (16-bit result)
MOVE?PP _Temp1, _Temp2 ; copy result to Temp2
MATH_ROR _Temp2 ; rotate right 4 times
MATH_ROR _Temp2
MATH_ROR _Temp2
MATH_ROR _Temp2 ; Temp2 is now 12-bits
MOVE?PW _Temp1, _Decimal_value_16bit ; copy PVAR's to WORDs
MOVE?PW _Temp2, _Decimal_value_12bit
ENDASM
serout2 txd,84,[13,10,"16-bit: ",HEX4 Decimal_value_16bit," ",DEC Decimal_value_16bit,13,10]
serout2 txd,84,["12-bit: ",HEX4 Decimal_value_12bit," ",DEC Decimal_value_12bit,13,10]
GOTO Main

And here's some of the output from a 16F876A ...

4941

RFsolution
- 13th November 2010, 21:53
Hi Darrel,

Thanks a lot this is working perfect

Imagine if I would like to do the opposite

so from a 10 or 12bit value (representing 1 revolution) to deg.xx
Can you put me on the right tracks to do that ?

Decimal_value_10bit var word '(0-1024)
Decimal_value_12bit var word '(0-4098)
degrees var word '(0-360)
degrees_fraction var byte '(.xx)
degree_Total var word

Darrel Taylor
- 14th November 2010, 17:12
Imagine if I would like to do the opposite

so from a 10 or 12bit value (representing 1 revolution) to deg.xx
Can you put me on the right tracks to do that ?

It's essentially the same thing, with the order of the formula reversed.

Originally for degrees to 16-bit we had ...
65536 * degrees / 36000 (notice I've changed the constants)

The reverse would be ...
16-bit * 36000 / 65536

You can change between any of the scales by simply changing the order and the constants.

degrees to 12-bit ... degrees * 4096 / 36000
12-bit to degrees ... 12-bit * 36000 / 4096

degrees to 10-bit ... degrees * 1024/ 36000
10-bit to degrees ... 10-bit * 36000 / 1024

Here's a macro for N-Bit_Math that will let you do it easily ...

ASM
Convert macro WFrom, Frange, WTo, Trange
MOVE?WP WFrom, _Temp1 ; copy From value to Temp1 Pvar
MOVE?CP Frange, _Range1 ; put From Range in Range1 Pvar
MOVE?CP Trange, _Range2 ; put To range in Range2
MATH_MUL _Temp1, _Range2, _Temp1 ; Temp1 = From * To_Range
MATH_DIV _Temp1, _Range1, _Temp1 ; Temp1 = Temp1 / From_Range
MOVE?PW _Temp1, WTo ; copy result to word variable WTo
endm
ENDASM


Then you can convert any of the scales to any other scale by providing the macro the From value with the "range" that variable goes to, a variable to put the result in and the range that variable should span.

To convert the original degrees to 16-bit, you would ...
@ Convert _degree_Total, 36000, _Decimal_value_16bit, 65536
or to 12-bit ...
@ Convert _degree_Total, 36000, _Decimal_value_12bit, 4096

Going the other way is just as easy.

@ Convert _Decimal_value_16bit, 65536, _degree_Total, 36000
@ Convert _Decimal_value_12bit, 4096, _degree_Total, 36000


Here's a test program ...

<font color="#000000">rxd <b>VAR </b>PORTC.7
txd <b>VAR </b>PORTC.6
<b>HIGH </b>txd

Decimal_value_16bit <b>VAR WORD </b><font color="#000080"><i>'(0-65535)
</i></font>Decimal_value_12bit <b>VAR WORD </b><font color="#000080"><i>'(0-4095)
</i></font>degrees <b>VAR WORD </b><font color="#000080"><i>'(0-359)
</i></font>degrees_fraction <b>VAR BYTE </b><font color="#000080"><i>'(.xx)
</i></font>degree_Total <b>VAR WORD

</b><font color="#000080"><i>'----[N-Bit Math]---------------------------------------------------------------
</i></font>PRECISION <b>CON </b>4 SYSTEM <font color="#000080"><i>; 4 bytes=32-bit
</i></font><b>INCLUDE </b><font color="#FF0000">&quot;N-Bit_MATH.pbp&quot;

</font>Temp1 <b>VAR BYTE</b>[PRECISION]
Range1 <b>VAR BYTE</b>[PRECISION]
Range2 <b>VAR BYTE</b>[PRECISION]

<b>ASM
</b><font color="#008000">Convert macro WFrom, Frange, WTo, Trange
MOVE?WP WFrom, _Temp1 </font><font color="#000080"><i>; copy From value to Temp1 Pvar
</i></font><font color="#008000">MOVE?CP Frange, _Range1 </font><font color="#000080"><i>; put From Range in Range1 Pvar
</i></font><font color="#008000">MOVE?CP Trange, _Range2 </font><font color="#000080"><i>; put To range in Range2
</i></font><font color="#008000">MATH_MUL _Temp1, _Range2, _Temp1 </font><font color="#000080"><i>; Temp1 = From * To_Range
</i></font><font color="#008000">MATH_DIV _Temp1, _Range1, _Temp1 </font><font color="#000080"><i>; Temp1 = Temp1 / From_Range
</i></font><font color="#008000">MOVE?PW _Temp1, WTo </font><font color="#000080"><i>; copy result to word variable WTo
</i></font><font color="#008000">endm
</font><b>ENDASM

</b><font color="#000080"><i>'----[Main Program Loop]--------------------------------------------------------
</i></font>Main:
<b>SEROUT2 </b>txd,84,[13,10,<font color="#FF0000">&quot;Enter Degrees (Max=359.99): &quot;</font>]
<b>SERIN2 </b>rxd,84,[<b>DEC </b>degrees,<b>DEC2 </b>degrees_fraction]
Degree_Total = degrees * 100 + degrees_fraction

<font color="#000080"><i>;--- degrees to 16-bit ---
</i></font><font color="#008000">@ Convert _degree_Total, 36000, _Decimal_value_16bit, 65536
</font><b>SEROUT2 </b>txd,84,[13,10,<font color="#FF0000">&quot;16-bit: &quot;</font>,<b>HEX4 </b>Decimal_value_16bit,<font color="#FF0000">&quot; &quot;</font>,<b>DEC </b>Decimal_value_16bit,13,10]

<font color="#000080"><i>;--- degrees to 12-bit ---
</i></font><font color="#008000">@ Convert _degree_Total, 36000, _Decimal_value_12bit, 4096
</font><b>SEROUT2 </b>txd,84,[<font color="#FF0000">&quot;12-bit: &quot;</font>,<b>HEX4 </b>Decimal_value_12bit,<font color="#FF0000">&quot; &quot;</font>,<b>DEC </b>Decimal_value_12bit,13,10]

<font color="#000080"><i>;--- 16-bit to degrees ---
</i></font><font color="#008000">@ Convert _Decimal_value_16bit, 65536, _degree_Total, 36000
</font><b>SEROUT2 </b>txd,84,[<font color="#FF0000">&quot;Deg from 16-bit: &quot;</font>,<b>DEC </b>degree_Total/100,<font color="#FF0000">&quot;.&quot;</font>,<b>DEC2 </b>degree_Total,13,10]

<font color="#000080"><i>;--- 12-bit to degrees ---
</i></font><font color="#008000">@ Convert _Decimal_value_12bit, 4096, _degree_Total, 36000
</font><b>SEROUT2 </b>txd,84,[<font color="#FF0000">&quot;Deg from 12-bit: &quot;</font>,<b>DEC </b>degree_Total/100,<font color="#FF0000">&quot;.&quot;</font>,<b>DEC2 </b>degree_Total,13,10]

<b>GOTO </b>Main

And here's some output from the test program ...

4947