- #1
Bryan_S
- 1
- 0
I am working with an analog devices AD9851 which is controlled by a Pic microcontroller. I need to calculate an offset frequency for calibrating the AD9851. Typical calibration procedure is to set output of the AD9851 to exactly 10Mhz out. Output is then measured with a frequency counter. Any difference between the set frequency and measured frequency needs to be entered into the Pic as a calibration factor when other frequencies are chosen.
Formula for calculating the proper control code for the AD9851 is as follows.
Code = freq*(2^32/(180E6 + offset)
(freq) in Mhz to set the output of the AD9851
(offset) is in hz
(180E6) is the actual clock frequency. A crystal at 30Mhz with a 6 times multiplier is used.
an example is 238609294 = 10E6*(2^32/180E6 + 0) no offset here
another one 238606908 = 10E6*(2^32/180E6 + 1800) offset is 1800 because at 10 Mhz
an offset of 100 hz was measured
so we multiply 100 hz by 18
Both examples would provide correct control codes to the AD9851.
My problem is performing these calculations with limited floating point routines in a Pic microcontroller. I can only use 7 significant digits within any calculations.
So, I tried it this way. Let's take my second example.
I need to output a code to the AD9851 of 238606908.
2^32 = 4294967296 //I divide this by two to make it smaller to work with.
4294967296/2 = 2147483648
2147483648/180001800 = 11.9303454 //div it by clock freq+offset
11.9303454 * 2 = 23.8606908 // mult it back up by 2
10E6 * 23.8606908 = 238606908 // mult by freq set by unit is correct here
Still this will not work within the confines of my Pic microcontroller code because it exceeds 7significant digits in many places.
For example 11.9303454 is 9 significant digits I cannot use it a 32bit floating point representation of it. 238606908 is a long integer so it is OK to use. Only floating point numbers can be used with other floating point numbers. I cannot use integers with floating point numbers when performing calculations such as + - / or * for example. These are the rules I have to use. So, I thought of doing it another way. Which works but only if I don't have an offset frequency to add to 180E3. This is where I think I need some help. Here is what I did. How I initially set the frequency to the AD9851 is by using two constants. One is 11 and the other is .9304647 together it is 11.9304647.
If I multiply 11 by 10mhz and then .9304647 and add them together I get
110000000 + 9304647 = 119304647
119304647 * 2 = 238609294 <-- correct code for 10mhz output.
I make 11 a float and also .9304647 after multiplying them they remain floats because 110000000 has only 2 siginificant digits and is actually 11E7 and 9304647 contains 7 significant digits. All good there.
Seeing I am going to be working with small values for offset frequencies for example like
116 hz I figured all I really need to work with is just the decimal portion of the number
like .9304647 and leave the 11 out of the calculation till end will I will just add it back.
Well it works but only for frequencies with no offsets. Once I add an offset to the calculation I get incorrect results. Here is what I did hope it makes some sense.
The result of this is to get a constant I can use that represents an offset in my crystal or clock driving the AD9851.
2^32/2 = 2147483648
Next I try to eliminate 11 out of this by
11 * 180E6 = 198E7
subtract above value from 2147483648 (This I know is where my problem is)
2147483648 - 198E7 = 167483648
The following is performed by a Pic microcontroller
5E6 represents 1/36 of clock frequency 180mhz
167E6/5E6 = 33.4
33.4/36 = .9277777
483E3/5E6 = .0966
.0966/36 = .0026833
648/5E6 = .0001296
.0001296/36 = .0000036
lets add them all up
.9277777
.0026833
.0000036 +
---------
0.9304646
now we add 11 back
11.9304646
we are off by 1 due to rounding but it is acceptable should be 11.9304647
11.9304646 * 2 = 23.8609292
23.8609292 * 10E6 (10Mhz) = 238609292 good but off value by two but still acceptable. Should be 238609294.
Well this isn't bad until I try to add an offset to the calculation.
For example. A measured offset of 100 hz at 10Mhz will be 50Hz at 5Mhz. This is the way it is with this device and it's clock. So we have.
167E6/(5E6 + 50) = 33.39966
33.39966/36 = 0.9277683
483E3/(5E6 + 50) = 0.096599
0.096599/36 = .0026833
648/5E6 = .0001295
.0001295/36 = .0000036
add them up it is
0.9304552
Add 11 to make it
11.9304552
then we mult it by 2
23.8609104
then mult it by 10E6
238609104 is incorrect should be 238606908
This is incorrect because of doing this I believe as posted above.
2^32/2 = 2147483648
Next I try to eliminate 11 out of this by
11 * 180E6 = 198E7
subtract above value from 2147483648 (This I know is where my problem is)
2147483648 - 198E7 = 167483648
Would greatly appreciate it if anyone has any idea how I can do this correctly. I'm not a wizard at something like this. Just have to keep in mind using only 7 significant digits when the Pic has to perform any floating point calculations. 32bit long integers can be used also but you cannot combine the two types in any operation. I can convert long integers into floats and back the other way. Again the objective is to arrive at a decimal constant like
.9304646 that will represent the value of frequency offset of the clock.
Thanks again for any help it is greatly appreciated.
Bryan_S
Formula for calculating the proper control code for the AD9851 is as follows.
Code = freq*(2^32/(180E6 + offset)
(freq) in Mhz to set the output of the AD9851
(offset) is in hz
(180E6) is the actual clock frequency. A crystal at 30Mhz with a 6 times multiplier is used.
an example is 238609294 = 10E6*(2^32/180E6 + 0) no offset here
another one 238606908 = 10E6*(2^32/180E6 + 1800) offset is 1800 because at 10 Mhz
an offset of 100 hz was measured
so we multiply 100 hz by 18
Both examples would provide correct control codes to the AD9851.
My problem is performing these calculations with limited floating point routines in a Pic microcontroller. I can only use 7 significant digits within any calculations.
So, I tried it this way. Let's take my second example.
I need to output a code to the AD9851 of 238606908.
2^32 = 4294967296 //I divide this by two to make it smaller to work with.
4294967296/2 = 2147483648
2147483648/180001800 = 11.9303454 //div it by clock freq+offset
11.9303454 * 2 = 23.8606908 // mult it back up by 2
10E6 * 23.8606908 = 238606908 // mult by freq set by unit is correct here
Still this will not work within the confines of my Pic microcontroller code because it exceeds 7significant digits in many places.
For example 11.9303454 is 9 significant digits I cannot use it a 32bit floating point representation of it. 238606908 is a long integer so it is OK to use. Only floating point numbers can be used with other floating point numbers. I cannot use integers with floating point numbers when performing calculations such as + - / or * for example. These are the rules I have to use. So, I thought of doing it another way. Which works but only if I don't have an offset frequency to add to 180E3. This is where I think I need some help. Here is what I did. How I initially set the frequency to the AD9851 is by using two constants. One is 11 and the other is .9304647 together it is 11.9304647.
If I multiply 11 by 10mhz and then .9304647 and add them together I get
110000000 + 9304647 = 119304647
119304647 * 2 = 238609294 <-- correct code for 10mhz output.
I make 11 a float and also .9304647 after multiplying them they remain floats because 110000000 has only 2 siginificant digits and is actually 11E7 and 9304647 contains 7 significant digits. All good there.
Seeing I am going to be working with small values for offset frequencies for example like
116 hz I figured all I really need to work with is just the decimal portion of the number
like .9304647 and leave the 11 out of the calculation till end will I will just add it back.
Well it works but only for frequencies with no offsets. Once I add an offset to the calculation I get incorrect results. Here is what I did hope it makes some sense.
The result of this is to get a constant I can use that represents an offset in my crystal or clock driving the AD9851.
2^32/2 = 2147483648
Next I try to eliminate 11 out of this by
11 * 180E6 = 198E7
subtract above value from 2147483648 (This I know is where my problem is)
2147483648 - 198E7 = 167483648
The following is performed by a Pic microcontroller
5E6 represents 1/36 of clock frequency 180mhz
167E6/5E6 = 33.4
33.4/36 = .9277777
483E3/5E6 = .0966
.0966/36 = .0026833
648/5E6 = .0001296
.0001296/36 = .0000036
lets add them all up
.9277777
.0026833
.0000036 +
---------
0.9304646
now we add 11 back
11.9304646
we are off by 1 due to rounding but it is acceptable should be 11.9304647
11.9304646 * 2 = 23.8609292
23.8609292 * 10E6 (10Mhz) = 238609292 good but off value by two but still acceptable. Should be 238609294.
Well this isn't bad until I try to add an offset to the calculation.
For example. A measured offset of 100 hz at 10Mhz will be 50Hz at 5Mhz. This is the way it is with this device and it's clock. So we have.
167E6/(5E6 + 50) = 33.39966
33.39966/36 = 0.9277683
483E3/(5E6 + 50) = 0.096599
0.096599/36 = .0026833
648/5E6 = .0001295
.0001295/36 = .0000036
add them up it is
0.9304552
Add 11 to make it
11.9304552
then we mult it by 2
23.8609104
then mult it by 10E6
238609104 is incorrect should be 238606908
This is incorrect because of doing this I believe as posted above.
2^32/2 = 2147483648
Next I try to eliminate 11 out of this by
11 * 180E6 = 198E7
subtract above value from 2147483648 (This I know is where my problem is)
2147483648 - 198E7 = 167483648
Would greatly appreciate it if anyone has any idea how I can do this correctly. I'm not a wizard at something like this. Just have to keep in mind using only 7 significant digits when the Pic has to perform any floating point calculations. 32bit long integers can be used also but you cannot combine the two types in any operation. I can convert long integers into floats and back the other way. Again the objective is to arrive at a decimal constant like
.9304646 that will represent the value of frequency offset of the clock.
Thanks again for any help it is greatly appreciated.
Bryan_S