Gyroscope, theoretical discussion

BESQUEUT

Senior Member
I now removed the scaling altogether as it is not strictly needed before the calculations. This did not really change a thing in the fact that the angles jump some seemingly arbitrary number back and forth instead of increasing or decreasing with turning the vehicle.

Help, please :(

Edmunds
Please publish raw data (Excel format)
+ your code

M_quot = MX_Word / MY_Word * 100
Picaxe Math problem(s) !
Here MX>MY
if MX is close to MY, then MX/MY is 1 or at least 2
So MX/MY *100 is 100 or 200, nothing between...

Remember : for the ATAN picaxe function
X must be between 0 and 100...

For my ATAN2 function, I used an auto-scaling divide :
Code:
#MACRO ATAN2(dx,dy)	' result in Alpha
	Xm=dx
	Ym=dy
	gosub ATAN2_Function
#ENDMACRO


#MACRO Quadrant(Qxm,Qym)	' Result ==> Alpha
	if Xm>Ym then
		gosub ATAN_Xm
		Alpha=Qxm
	else				' Xm < Ym
		gosub ATAN_Ym
		Alpha=Qym
	endif
#ENDMACRO


ATAN2_Function:
' Input Xm & Ym are 2 complement encoded
' Xm and YM can be anything from -32767 to + 32767
' So you can use Xm=X1-X2 
' even if X2 greater than X1
'
	if Ym <32768 then					' Ym > 0
		if Xm<32768 then				' Xm > 0
			Quadrant(Alpha,90-Alpha)	
		else 						' Xm < 0
			Xm=-Xm
			Quadrant(180-Alpha,90+Alpha)
		endif

	
	else 							' Ym < 0
		Ym=-Ym
		if Xm<32768 then				' Xm > 0
			Quadrant(360-Alpha,270+Alpha)
		else 						' Xm < 0
			Xm=-Xm
			Quadrant(180+Alpha,270-Alpha)
		endif
	endif
RETURN
}

{ 'reduce too big numbers
ATAN_Xm:
	select case Ym		' Ym < Xm
	case < 655			' Ym < 655
		Alpha=100*Ym/Xm
		
	case < 6553			' 655 < Ym < 6553 donc Xm > 655
		Q=Xm/10
		Alpha=10*Ym/Q
		
	else				' 6553 < Ym donc Xm > 6553
		Q=Xm/100
		Alpha=Ym/Q
	end select

	Alpha=ATAN Alpha
RETURN


ATAN_Ym:
	select case Xm		' Xm < Ym
	case < 655			' Xm < 655
		Alpha=100*Xm/Ym
		
	case < 6553			' 655 < Xm < 6553
		Q=Ym/10
		Alpha=10*Xm/Q
		
	else				' 6553 < Xm
		Q=Ym/100
		Alpha=Xm/Q
	end select

	Alpha=ATAN Alpha
RETURN
}
 
Last edited:

edmunds

Senior Member
M_quot = MX_Word / MY_Word * 100
Picaxe Math problem !
if MX is close to MY, then MX/MY is 1 or at least 2
So MX/MY *100 is 100 or 200, nothing between...
OK! That makes sense! Thank you, thank you, thank you.
Now I remember, why I wanted to scale the numbers right out of the magnetometer - to be able to multiply the dividend with 100 and then divide. However, this was not a very good solution either, because a lot of resolution was lost even when not very needed. I will look if I can understand and implement something from your code.

Now I can get forward again.

Edmunds
 

edmunds

Senior Member
I have about 50% of the angles that match very well with excel and the rest is way off. I decided to take the strange ones on one by one, because when I look at it, it seems my trig is fine and also running things in simulator do not reveal anything strange.

Here is an interesting dataset:
Code:
   X;	            Y;	            Z;	   PreATAN;	 ATAN;	Heading;		rad;	                deg
63488;	53239;	48638;	16;	           9;	            9;		0.697819597;	39.98211778
The first three columns are raw data. I have disabled filters and offsets. The PreATAN is the number supplied to standard ATAN function, ATAN is the result of that function and Heading is with 'correct' octant applied. rad is ATAN2 result in excel. deg is rad*180/Pi.

Now, X and Y are both negative numbers in this case. So the result has to be in octants 4 or 5. How is it possible to get 40 degrees (excel) in octants 4 or 5? I understand 9 is no good either, but I don't understand what to aim for here :).

Thank you for your time,

Edmunds
 
Last edited:

BESQUEUT

Senior Member
I have about 50% of the angles that match very well with excel and the rest is way off. I decided to take the strange ones on one by one, because when I look at it, it seems my trig is fine and also running things in simulator do not reveal anything strange.

Here is an interesting dataset:
Code:
   X;	            Y;	            Z;	   PreATAN;	 ATAN;	Heading;		rad;	                deg
63488;	53239;	48638;	16;	           9;	            9;		0.697819597;	39.98211778
The first three columns are raw data. I have disabled filters and offsets. The PreATAN is the number supplied to standard ATAN function, ATAN is the result of that function and Heading is with 'correct' octant applied. rad is ATAN2 result in excel. deg is rad*180/Pi.

Now, X and Y are both negative numbers in this case. So the result has to be in octants 4 or 5. How is it possible to get 40 degrees (excel) in octants 4 or 5? I understand 9 is no good either, but I don't understand what to aim for here :).

Thank you for your time,

Edmunds
Can you point me to the magnetometer data sheet ?
 

edmunds

Senior Member
For what its worth, I have timed the GetHeading procedure (which, admittedly, still contains bugs or some other phantom problem, but nothing that I can see that would have to make it much slower) and it takes 6.5ms including the necessary I2C calls to get data and start the next measurement at 64MHz. Plenty fast for what I need on condition I can get consistent and meaningful data. It can take double that and it should still work.

Also, I had missed the fact BNO055 from Bosch included 32bit Cortex processor and fusion algorithms to output 'robust heading'. Could not resist ordering two pieces.


Cheers,

Edmunds
 
Last edited:

edmunds

Senior Member
Dear @Besqueut,

I now copied your algorithm and I'm getting the same strange results as with mine. Very good in some sectors and then a jump to a different sector by some 180 (or 90 or not either) degrees even though the car turned only a few degrees past some threshold. There must be something strange coming out of that magnetometer!

Despite it does not work, this puts a smile on my face, because this means I have worked through the trig correctly or at least as correct as you have and that is a lot :).

Edmunds

EDIT: BUT, your procedure takes only 1.2ms compared to my 6.5ms including the I2C calls!!!
 
Last edited:

edmunds

Senior Member
Since I cannot find anything else wrong, I'm blaming calibration. I'm trying to write a calibration procedure. In the process of doing it, my mind is kind of exploding, so I need a break and some distraction, which will be this forum entry.

The calibration is a 'simple' procedure. Record output values for some time, find MIN and MAX for each axis, add them up, divide by two and here you are. Turns out you need to store the result in eeprom, because the magnetometer looses them at power cycling, but whatever. Does not sound too difficult. But hell it is. When you add signed numbers.

Your previous MIN value can be positive or negative. The same goes for MAX and, of course, your current reading can be both - positive and negative. Both MIN and MAX values for a given axes can come out both positive, both negative or MAX positive and MIN negative (but not the other way around - this is where you loose one sign permutation). So, altogether, there are 8 sign permutations possible and for most of them you have to figure out if this is not a new MAX or new MIN.

This navigation is, sure, not a boring project :)

If anyone has some idea on how to handle this easier than some 4 or 5 level deep if or select statements, I'm very interested.


Cheers (literally),

Edmunds
 

BESQUEUT

Senior Member
When I look at data from #105, something seems very strange :
theses numbers are 8 bits not 16.
The second octet is all zero, or sometimes all 1.
I suspect a problem reading data...
Code:
X	Y	Z	Alpha		X	Y
13824	29183	12544	-98,9		+011011000000000	+111000111111111
17152	27903	13568	-91,1		+100001100000000	+110110011111111
23040	27647	12800	-78,4		+101101000000000	+110101111111111
24576	29439	13824	-74,1		+110000000000000	+111001011111111
27648	30207	13056	-66,9		+110110000000000	+111010111111111
31744	30719	13056	-58,4		+111110000000000	+111011111111111
-30720	32511	12800	-50,9		-111100000000000	+111111011111111
-28672	-29697	13056	-42,6		-111000000000000	-111010000000001
-26112	-26881	13824	-34,1		-110011000000000	-110100100000001
-24064	-26625	13056	-31,3		-101111000000000	-110100000000001
-22528	-23297	12800	-23,5		-101100000000000	-101101100000001
-22272	-17921	14080	-12		-101011100000000	-100011000000001
-22272	-16897	14592	-9,7		-101011100000000	-100001000000001
-21760	-14337	13568	-3,8		-101010100000000	-011100000000001
-21760	-10241	14336	5,5		-101010100000000	-010100000000001
-23808	-6145	14336	15,7		-101110100000000	-001100000000001
-23296	-2817	14592	22,6		-101101100000000	-000101100000001
-26112	-1281	15616	28,5		-110011000000000	-000010100000001
-27392	2560	14336	37,6		-110101100000000	+000101000000000
-27904	3072	15104	39,2		-110110100000000	+000110000000000
-31744	7168	16128	51,9		-111110000000000	+001110000000000
30208	6656	17152	57,9		+111011000000000	+001101000000000
28928	8960	15872	63,3		+111000100000000	+010001100000000
25856	12032	16896	72,2		+110010100000000	+010111100000000
20224	10240	16896	83,8		+100111100000000	+010100000000000
17664	10496	16384	90		+100010100000000	+010100100000000
12288	12544	17664	101,6		+011000000000000	+011000100000000
8960	11264	16128	109,3		+010001100000000	+010110000000000
6656	9472	16128	115,6		+001101000000000	+010010100000000
4096	8704	17408	121,5		+001000000000000	+010001000000000
512	7680	16896	129,1		+000001000000000	+001111000000000
-769	5632	17408	134,2		-000001100000001	+001011000000000
-3073	3840	16896	140,5		-000110000000001	+000111100000000
-4865	512	17920	148,8		-001001100000001	+000001000000000
-7169	-2305	16640	156,6		-001110000000001	-000100100000001
-6913	-5121	16128	162,3		-001101100000001	-001010000000001
-8449	-9985	17152	173,9		-010000100000001	-010011100000001
-6913	-11265	15616	176,6		-001101100000001	-010110000000001
-6401	-17409	15616	-168,5		-001100100000001	-100010000000001
-6145	-18945	15104	-164,7		-001100000000001	-100101000000001
-5377	-22785	14592	-155,6		-001010100000001	-101100100000001
-3585	-24065	14592	-151		-000111000000001	-101111000000001
-1281	-27137	14848	-141,7		-000010100000001	-110101000000001
512	-29185	14080	-135,1		+000001000000000	-111001000000001
1792	32767	13312	-127,3		+000011100000000	+111111111111111
4096	32767	13056	-123,1		+001000000000000	+111111111111111
7936	29951	13568	-112,3		+001111100000000	+111010011111111
 

edmunds

Senior Member
This is a very good idea. I read a byte of a word, but while I'm reading it, the second byte disappears or is actually from the next sample. There is a BDU setting in one of the control registers to prevent this. Will look into it.


Thank you for your input,

Edmunds
 

edmunds

Senior Member
When you look at this, it is a strange sentence...

OUTX_L_REG_M, OUTX_H_REG_M (68h - 69h)
The data output X registers are two 8-bit registers, data output ch1 MSB register (69h) and output X LSB register (68h).

What is 'data output ch1 MSB' as opposed to 'output X LSB'?

The application note, however, is much clearer:

The measured magnetic data are sent to the OUTX_H_REG_M, OUTX_L_REG_M, OUTY_H_REG_M, OUTY_L_REG_M, OUTZ_H_REG_M, and OUTZ_L_REG_M registers. These registers contain, respectively, the most significant part and the least significant part of the magnetic signals acting on the X, Y, and Z axes.
The complete output data for the X, Y, Z channels is given by the concatenation OUTX_H_REG_M & OUTX_L_REG_M, OUTY_H_REG_M & OUTY_L_REG_M, OUTZ_H_REG_M & OUTZ_L_REG_M and it is expressed as a two's complement number.
Magnetic data is represented as 16-bit numbers, called LSB. It must be multiplied by the proper sensitivity parameter, M_So = 1.5, in order to obtain the corresponding value in mG.

Edmunds
 

BESQUEUT

Senior Member
Nothing strange
MSB is most significant byte, IE most significants bits
LSB is least ...
With a Picaxe you read b0 b1, And use w0
But y ou have to take care of updates...
 

edmunds

Senior Member
Nothing strange
MSB is most significant byte, IE most significants bits
LSB is least ...
Yes, sure, I was more concerned about MSB belonging to ch1 and LSB to X. Probably looking for something that isn't there.

With a Picaxe you read b0 b1, And use w0
I'm quite sure it is the other way around. w0 = b1 : b0. MSb of w0 is b1 and LSb is b0.

But y ou have to take care of updates...
Lets see what I manage to do.


Thank you for your time,

Edmunds
 

edmunds

Senior Member
Dear @Besqueut,

I have a question about your ATAN2 code. You are working with quadrants, i.e. 90 degree sectors instead of octants, 45 degree sectors. Since picaxe ATAN only returns 0 to 45 degree angles, I'm looking for a place where you take care of this in your code and I cannot find it. Can you pls explain?


Thank you,

Edmunds
 

edmunds

Senior Member
Well, at 02:00AM I might be digging deep. Or too deep...

But the symptoms of my problem with magnetometer part of LSM303AGR are at least twofold. I have 'stuck' MSB output registers for magnetometer and I'm unable to run the device in proper 'continuous' measurement mode. It is supposed to load a new measurement, when I have read the MSBs from output registers continuously, but the only way I can get this to happen is to reset the mode (to any, single or continuous) to make it think it was just switched on. When this is happening properly fast, it looks like continuos mode, but it isn't.

This last thing lead me to thinking, the sensor does not feel like I have read the MSBs. Although I have. I know I have. Or not ...

I'm using picaxe I2C and its been a few years, since I really looked under the hood there. And I don't have a logic analyser available right now, but there is a place in the data sheet of LSM303AGR and data sheet of Microchip that might not match exactly or rather the Microchip data sheet explains quite a lot of work (some bits in some registers in timely manner) would have to be done to achieve what LSM303AGR data sheet requires.

More exactly, the page 38 in the data sheet of LSM303AGR explains that multiple byte read would have to be terminated by NMAK condition before SP condition. I will make an assumption here, picaxe read terminates with MAK condition before SP condition based on what I read in Microchip data sheet irrespective of how many bytes have been read.

While I'm trying to think where have I used multiple byte reads to check the respective data sheets, if anyone knows or has the means to check (multiple byte read) would be great.


Thank you for your inputs,

Edmunds
 
Last edited:

lbenson

Senior Member
Quote Originally Posted by BESQUEUT:

"With a Picaxe you read b0 b1, And use w0"

I'm quite sure it is the other way around. w0 = b1 : b0. MSb of w0 is b1 and LSb is b0.
Edmunds
I'm pretty sure that what BESQUEUT was saying was that in ram, picaxe b0 (LSB) physically preceeds b1 (MSB) in constituting w0. (Little Endian arrangement.)
 

BESQUEUT

Senior Member
I'm pretty sure that what BESQUEUT was saying was that in ram, picaxe b0 (LSB) physically preceeds b1 (MSB) in constituting w0. (Little Endian arrangement.)
LSB is 68H
MSB is 69H
So IHMO, you first read b0, then b1. (but, as soon as b0 and b1 are corectly filled, you can try and revert...)
I have a question about your ATAN2 code. You are working with quadrants, i.e. 90 degree sectors instead of octants, 45 degree sectors. Since picaxe ATAN only returns 0 to 45 degree angles, I'm looking for a place where you take care of this in your code and I cannot find it. Can you pls explain?
YES I CAN !
 
Last edited:

BESQUEUT

Senior Member
Ah ! ... You want me to explain...
If you look at the Quadrant macro, you can see that there are 2 parts :
- Xm > Ym
- Ym >= Xm (of course)
So each Quadrant is subdivised by two "Octants"
There are two arguments to this macro :
they are the two possibles ways of returning Alpha, for example :
Alpha = 180+Alpha
or
Alpha = 270-Alpha
Is that clear ?

Note that if Xm>Ym then 100*(Ym/Xm)<100
Also note that if Xm>Ym and Ym<>0 then Xm<>0
So, no need for a special case.

And Vace Versi,
 
Last edited:

BESQUEUT

Senior Member
I do not know if this can help. This is an extract from a program to read two words from hdc1080 via I2C bus :
HI2Cout $00,($01)
pause 200
HI2CIN (b1,b0,b3,b2)

Note that for hdc1080, MSB is First
 

edmunds

Senior Member
Dear @Besqueut,

The datasheet of your device has the same NACK (same as NMAK in mine) requirement for multiple byte read. If this works for your device, it should work for mine. I'm leaving for the long weekend now, but I should have BNO055 arriving on Monday. I will give up on this for now as BNO055 seems a lot more suitable device.

Edmunds
 

edmunds

Senior Member
Is 350° more or less that 5° ?
Dear all,

I'm trying to get ahead of myself here and write some basic code structure for converting expected heading data from the IMU with sensor fusion mentioned before (hoping to receive it tomorrow) into heading error. I have at least three questions to answer and after reading tons of stuff on the web, I'm still in doubt how to proceed.

Q1:
The thing can output heading in degrees or radians. The result is signed for pitch and roll, but 0 to 360 or 0 to 2pi for yaw, which is what I'm interested in. There is also quaternion option, but I don't know what to do with it if I cannot handle vectors and matrices easily, which I think is difficult without good handling of memory arrays. Also, no floating point kind of makes it hard. Correct me if I'm wrong, but this is what my little research has left me with. Back to angle then. 16LSB for a degree or 900LSB for a radian. Would degrees or radians be more convenient? Depends. I know. Read on, please.

Q2:
My heading error can be a few degrees at most. If it is any more than that, the car should stop operation and cry for help. This is mandated by the fact the car is Ackermann steering vehicle and cannot turn with infinitely small radius infinitely fast. In fact, it has quite serious minimum radii and it has to go quite slow to be able to hold into the minimum curve. Thus, I'm not interested in heading errors like 90 degrees or 45 degrees or God forbid - 274 degrees per measurement iteration. +/- 7 deg should be plenty. However, these +/-7 can travel all around the rhumb as I'm dealing with data that is driven by true heading. So if my 'map' says, step #2032 of the trip should be heading for 358 deg and my actual heading is 2 deg what do I do? Depends, I know. Read on, please.

Q3:
Obviously from above, I need a signed data solution with an 'automatic' overflow management at least for the additions and subtractions. In that sense, making 360/655356 deg the unit seems a good idea. Its a pity that isn't what is coming out of the BNO055. However, this does not give a pretty looking result and more importantly - the rounded numbers per degree or radians will not add up to a full circle. So with every zero crossing there will be an error which will accumulate over time. What to do?


Thank you for your inputs,

Edmunds
 

edmunds

Senior Member
The following code might do it, but the questions remain. A: if this is the best way and B: what to do with not converging to a full circle?

Code:
diff = t_heading - heading       'calculate difference between target and actual headings
if diff >= $8000 then            'cater for overflow situation - negative subtraction result
  absdiff = -diff
else
  absdiff = diff
endif

if absdiff = 180 then             'take care of special case first
  error = absdiff                 'set error to abs value
elseif absdiff < 180 then
  error = diff                    
elseif heading > t_heading then
  error = absdiff - 360
else
  error = 360 - absdiff
endif
EDIT: Ran manual simulator on the code above. No access to a PC right now :). Seems to work.

t_h = 2; h = 5; diff = -3; absdiff = 3; error = -3; OK
t_h = 5; h = 2; diff = 3; absdiff = 3; error = +3; OK
t_h = 179; h = 184; diff = -5; absdiff = 5; error = -5; OK
t_h = 184; h = 179; diff = 5; absdiff = 5; error = +5; OK
t_h = 358; h = 2; diff = 356; absdiff = 356; error = -4; OK
t_h = 2; h = 358; diff = -356; absdiff = 356; error = +4; OK

Edmunds
 
Last edited:

BESQUEUT

Senior Member
The following code might do it, but the questions remain. A: if this is the best way and B: what to do with not converging to a full circle?

Code:
diff = t_heading - heading       'calculate difference between target and actual headings
if diff >= $8000 then            'cater for overflow situation - negative subtraction result
  absdiff = -diff
else
  absdiff = diff
endif

if absdiff = 180 then             'take care of special case first
  error = absdiff                 'set error to abs value
elseif absdiff < 180 then
  error = diff                    
elseif heading > t_heading then
  error = absdiff - 360
else
  error = 360 - absdiff
endif
EDIT: Ran manual simulator on the code above. No access to a PC right now :). Seems to work.

t_h = 2; h = 5; diff = -3; absdiff = 3; error = -3; OK
t_h = 5; h = 2; diff = 3; absdiff = 3; error = +3; OK
t_h = 179; h = 184; diff = -5; absdiff = 5; error = -5; OK
t_h = 184; h = 179; diff = 5; absdiff = 5; error = +5; OK
t_h = 358; h = 2; diff = 356; absdiff = 356; error = -4; OK
t_h = 2; h = 358; diff = -356; absdiff = 356; error = +4; OK

Edmunds
a little shorter suggestion :
Code:
[color=Blue]Symbol [/color][color=Purple]Diff[/color][color=DarkCyan]=[/color][color=Purple]w0[/color]
[color=Blue]Symbol [/color][color=Purple]absdiff[/color][color=DarkCyan]=[/color][color=Purple]w1[/color]
[color=Blue]symbol [/color][color=Purple]Error[/color][color=DarkCyan]=[/color][color=Purple]w2[/color]
[color=Blue]symbol [/color][color=Purple]Heading[/color][color=DarkCyan]=[/color][color=Purple]w3[/color]
[color=Blue]symbol [/color][color=Purple]t_heading[/color][color=DarkCyan]=[/color][color=Purple]w4[/color]

[color=Navy]#simspeed 50
#macro [/color][color=Black]CalcErr[/color][color=Blue]([/color][color=Black]t_h,H[/color][color=Blue])
      [/color][color=Purple]t_heading[/color][color=DarkCyan]=[/color][color=Black]t_h
      [/color][color=Purple]heading[/color][color=DarkCyan]=[/color][color=Black]H
      [/color][color=Blue]gosub [/color][color=Black]C_E
      [/color][color=Blue]sertxd ([/color][color=Navy]13[/color][color=Black],[/color][color=Navy]10[/color][color=Black],#[/color][color=Purple]t_heading[/color][color=Black],[/color][color=Red]" "[/color][color=Black],#[/color][color=Purple]heading[/color][color=Black],[/color][color=Red]"==>"[/color][color=Black], [/color][color=Navy]#Error)
      [/color][color=Blue]gosub [/color][color=Black]C_E2
      [/color][color=Blue]sertxd ([/color][color=Red]"-->"[/color][color=Black], [/color][color=Navy]#Error)
#endmacro[/color]

[color=Blue]sertxd([/color][color=Navy]13[/color][color=Black],[/color][color=Navy]10[/color][color=Blue])[/color]
[color=Black]CalcErr[/color][color=Blue]([/color][color=Navy]2[/color][color=Black],[/color][color=Navy]5[/color][color=Blue])[/color]
[color=Black]CalcErr[/color][color=Blue]([/color][color=Navy]5[/color][color=Black],[/color][color=Navy]2[/color][color=Blue])[/color]
[color=Black]CalcErr[/color][color=Blue]([/color][color=Navy]179[/color][color=Black],[/color][color=Navy]184[/color][color=Blue])[/color]
[color=Black]CalcErr[/color][color=Blue]([/color][color=Navy]184[/color][color=Black],[/color][color=Navy]179[/color][color=Blue])[/color]
[color=Black]CalcErr[/color][color=Blue]([/color][color=Navy]358[/color][color=Black],[/color][color=Navy]2[/color][color=Blue])[/color]
[color=Black]CalcErr[/color][color=Blue]([/color][color=Navy]2[/color][color=Black],[/color][color=Navy]358[/color][color=Blue])
end[/color]


[color=Black]C_E:
      [/color][color=Purple]diff [/color][color=DarkCyan]= [/color][color=Purple]t_heading [/color][color=DarkCyan]- [/color][color=Purple]heading       [/color][color=Green]'calculate difference between target and actual headings
      [/color][color=Blue]if [/color][color=Purple]diff [/color][color=DarkCyan]>= [/color][color=Navy]$8000 [/color][color=Blue]then            [/color][color=Green]'cater for overflow situation - negative subtraction result
            [/color][color=Purple]absdiff [/color][color=DarkCyan]= -[/color][color=Purple]diff
      [/color][color=Blue]else
            [/color][color=Purple]absdiff [/color][color=DarkCyan]= [/color][color=Purple]diff
      [/color][color=Blue]endif

      if [/color][color=Purple]absdiff [/color][color=DarkCyan]= [/color][color=Navy]180 [/color][color=Blue]then             [/color][color=Green]'take care of special case first
             [/color][color=Purple]error [/color][color=DarkCyan]= [/color][color=Purple]absdiff                 [/color][color=Green]'set error to abs value
      [/color][color=Blue]elseif [/color][color=Purple]absdiff [/color][color=DarkCyan]< [/color][color=Navy]180 [/color][color=Blue]then
            [/color][color=Purple]error [/color][color=DarkCyan]= [/color][color=Purple]diff                    
      [/color][color=Blue]elseif [/color][color=Purple]heading [/color][color=DarkCyan]> [/color][color=Purple]t_heading [/color][color=Blue]then
            [/color][color=Purple]error [/color][color=DarkCyan]= [/color][color=Purple]absdiff [/color][color=DarkCyan]- [/color][color=Navy]360
      [/color][color=Blue]else
            [/color][color=Purple]error [/color][color=DarkCyan]= [/color][color=Navy]360 [/color][color=DarkCyan]- [/color][color=Purple]absdiff
      [/color][color=Blue]endif

return[/color]



[color=Black]C_E2:
      [/color][color=Purple]Error [/color][color=DarkCyan]= [/color][color=Purple]t_heading [/color][color=DarkCyan]- [/color][color=Purple]heading
      [/color][color=Blue]if [/color][color=Purple]error [/color][color=DarkCyan]<[/color][color=Navy]32768 [/color][color=Blue]then
            if [/color][color=Purple]error [/color][color=DarkCyan]>[/color][color=Navy]180 [/color][color=Blue]then
                  [/color][color=Purple]error[/color][color=DarkCyan]=[/color][color=Navy]360[/color][color=DarkCyan]-[/color][color=Purple]error
            [/color][color=Blue]endif
      else
            if [/color][color=Purple]error [/color][color=DarkCyan]< [/color][color=Navy]65356 [/color][color=Blue]then
                  [/color][color=Purple]error[/color][color=DarkCyan]=-[/color][color=Purple]error[/color][color=DarkCyan]-[/color][color=Navy]360
            [/color][color=Blue]endif
      endif
return[/color]
 
Top