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
Powered by vBulletin® Version 4.1.7 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.