PDA

View Full Version : 16bit variable and degrees conversion



RFsolution
- 18th April 2005, 21:51
Hi all

I need some help on a 16bit variable

I receive serial at 9600 bd N8,1 a string with 2 positions each 16bit

example:
21 AD 34 01 22 EF 23 02

where:
21 is indicating the 1st position request
AD 34 16bit position 1
01 not used

22 is indicating the 2nd position request
EF 23 16bit position 2

Now I need to display both positions on a LCD in degrees

So AD 34 is 44340 decimal

65536 / 360 = 182.04444444 Per degree

So 44340 / 182.0444444 = 243,56689453125 degrees

I need to display 243 and 566 on a LCD

Same for the 2nd position

How can I handle those variables in PBP ?


Thanks Walter

Ingvar
- 19th April 2005, 10:13
Hi,

IntPartOfPos1 = 16bitPosition1 ** 360
FracPartOfPos1 = 16bitPosition1 * 360
FracPartOfPos1 = FracPartOfPos1 ** 1000
LCDOUT DEC3 IntPartOfPos1, ".", DEC3 FracPartOfPos1

The code above starts with two multiplications by 360, one of them isn't really necessary. However i'm a bit unsure of wich internal register contains what after a multiplication. I think the code below will work, but i'm not 100% sure it's the right register. Try it and see.

FracPartOfPos1 = 16bitPosition1 * 360
IntPartOfPos1 = R0
FracPartOfPos1 = FracPartOfPos1 ** 1000
LCDOUT DEC3 IntPartOfPos1, ".", DEC3 FracPartOfPos1

/Ingvar

Luciano
- 19th April 2005, 13:29
Hi!

What precision do you need?
Describe your project.

The three conversions below (44340, 13107 and 13)
are performed using the solution of the user Ingvar.
(See his previous post).

From the PicBasic Pro manual:

PicBasic Pro multiply (*) function
operates as a 16-bit x 16-bit multiply
yielding a 32-bit internal result.

4.17.1. Multiplication
PBP performs unsigned 16-bit x 16-bit multiplication.

The '*' operator returns the lower 16 bits of
the 32-bit internal result. This is the typical
multiplication found in most programming languages.

The '**' operator returns the upper 16 bits of
the 32-bit internal result. These two operators
can be used in conjunction to perform 16-bit x 16-bit
multiplication that produces 32-bit results.

========================================
(See original post of the user Walter/RFsolution)
With the Windows calculator:
65535/360 = 182.04166666666666666666666666667

========================================
44340 conversion

44340 * 360 = 15962400

15962400 = 00000000111100111001000100100000 (32-bit internal result)
-----------0000000011110011-1001000100100000
-------------(upper 16 bits )-----(lower 16 bits )

Upper 16 bits of the 32-bit internal result = 0000000011110011 = 243 decimal
Lower 16 bits of the 32-bit internal result = 1001000100100000 = 37152 decimal

37152 * 1000 = 37152000

37152000 = 00000010001101101110010100000000 (32-bit internal result)
-----------0000001000110110-1110010100000000
-------------(upper 16 bits )-----(lower 16 bits )

Upper 16 bits of the 32-bit internal result = 0000001000110110 = 566 decimal
Lower 16 bits of the 32-bit internal result = 1110010100000000 = 58624 decimal

Display = 243.566

With the Windows calculator:
44340 / 182.04166666666666666666666666667
= 243.57061112382696269169146257725

========================================
13107 conversion (65535/5 = 13107 ---- 360 / 5 = 72 degrees)

44340 * 360 = 4718520

4718520 = 10001111111111110111000
1000111-1111111110111000
(up.part)---(lo. part)

Upper part 1000111 = 71 decimal
Lower part 1111111110111000 = 65464 decimal

65464 * 1000 = 65464000

65464000 = 11111001101110011011000000
1111100110-1110011011000000
(up.part)---(lo. part)

Upper part = 1111100110 = 998 decimal
Lower part = 1110011011000000 = 59072 decimal

Display = 71.998

With the Windows calculator:
13107 / 182.04166666666666666666666666667
= 72

========================================
13 conversion

13 * 360 = 4680

4680 = 0-0001001001001000
-------(up.part)---(lo. part)

Upper part 0 = 0 decimal
Lower part 1001001001000 = 4680 decimal

4680 * 1000 = 4680000

4680000 = 10001110110100101000000
1000111-0110100101000000
(up.part)---(lo. part)

Upper part = 1000111 = 71 decimal
Lower part = 1110011011000000 = 59072 decimal

Display = 0.071

With the Windows calculator:
13 / 182.04166666666666666666666666667
= 0.071412222476539253833829251544976

========================================

* * * * * * * *

About precision

Example with earth's longitude:

A degree of longitude at the equator is 111.2 kilometers
a minute is 1853 meters and a second is 30.9 meters.

* * * *
Convert degrees to decimal degrees:

Example 09°59'58" (9 degrees, 59 minutes, 58 seconds).
= Decimal degrees 9.9994


Example 09°59'57" (9 degrees, 59 minutes, 57 seconds).
= Decimal degrees 9.9991


Example 09°59'56" (9 degrees, 59 minutes, 56 seconds).
= Decimal degrees 9.9988

* * * *

Convert decimal degrees to degrees:

9.999 > 09°59'56"
9.998 > 09°59'52"
9.997 > 09°59'49"

* * * *

Above conversions done with:

http://www.beg.utexas.edu/GIS/tools/DMS_DD.htm
http://www.beg.utexas.edu/GIS/tools/dd_dms.htm


Best regards,

Luciano

RFsolution
- 19th April 2005, 20:42
Thank you All ,

I will have a look and give it a try this weekend, but both Ingvar and Luciano
pointed me in the direction

I only need to check the SERIN2 command to see how to handle the incomming string in my previous msg

Precision is 2 decimals

The project is to read out 2 position absolute encoders
which are polled by a controller over a RS485 line at 9600bd

Thanks again to everyone who helped me

Walter

Ingvar
- 20th April 2005, 09:16
Ok, since you only need 2 decimals and my code gives 3 you can use the extra precision to round the result .......

IntPartOfPos1 = 16bitPosition1 ** 360
FracPartOfPos1 = 16bitPosition1 * 360
FracPartOfPos1 = FracPartOfPos1 ** 1000
FracPartOfPos1 = (FracPartOfPos1 + 5) / 10
LCDOUT DEC3 IntPartOfPos1, ".", DEC2 FracPartOfPos1

..... should give you a correctly rounded result with 2 decimals.

/Ingvar

RFsolution
- 21st April 2005, 20:51
Hmm looks that I'm doing something wrong


I receive serial at 9600 bd N8,1 the following in hex

example:
21 AD 34 01 22 EF 23 02

loop:
AZ var word
EL var Word

Serin2 portb.2,84,[wait ("!"),AZ] => "!" is the ascii represenataion of 21 hex
would like to store AD 34 in variable AZ, 01 dont care
then the same for EF 23 in EL

Use an SP485 RS485 driver in front

Luciano
- 22nd April 2005, 11:13
Hi,

Your example data:
21 AD 34 01 22 EF 23 02

===============================================
' The code (Not tested)

my_array VAR BYTE[7] ' Define array variable with 7 locations

SERIN2 IN_PIN, BAUD,[WAIT("!") STR my_array\7]

' Waits for the string "!", then collects the next 7 characters.
' (21 HEX = ASCII !)


===============================================

This could be valid data:
21 21 21 01 22 21 21 02

Make sure you verify that "01" "22" "02" are in the
right position in the array.

* * * * * *

From PicBasic manual:

An optional Timeout and Label may be included to allow the program
to continue if a character is not received within a certain amount of time.
Timeout is specified in 1 millisecond units. If the serial input pin stays in
the idle state during the Timeout time, the program will exit the SERIN2
command and jump to Label.

* * * * * *

PicBasic Pro Code that demonstrates the use of modifiers
with the Serin2 and Serout2 commands.

http://www.microengineeringlabs.com/resources/samples/pbp/ser2mod.bas


Luciano

RFsolution
- 2nd May 2005, 17:27
Everything is working

I would like to thank those who post some replys

If someone is in the Belgian Area, I will certainly offer a Beer

Walter