Calculating a frequency offset using a PIC

  • Thread starter Thread starter Bryan_S
  • Start date Start date
  • Tags Tags
    Frequency
AI Thread Summary
The discussion revolves around calculating a frequency offset for an AD9851 controlled by a PIC microcontroller, focusing on achieving accurate calibration despite limited floating-point capabilities. The standard calibration procedure involves setting the AD9851 to 10 MHz and measuring the output against this frequency, with any discrepancies needing to be factored into the PIC as a calibration constant. The user struggles with maintaining precision due to the 7 significant digit limit in calculations, particularly when offsets are introduced. Suggestions include using fixed-point arithmetic to improve precision without exceeding the significant digit constraints. The conversation emphasizes the need for a reliable method to accurately calculate the offset while adhering to the limitations of the PIC microcontroller.
Bryan_S
Messages
1
Reaction score
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
 
Engineering news on Phys.org
Sorry, I don't have the brain cells left to follow all your arithmetic, but if the range of your result is fairly small perhaps you can consider using Fixed Point arithmetic instead of Floating Point. With Fixed Point you multiply everything by some factor before doing regular integer operations and then divide the result by the same factor. In binary the multiply/divide can be done with bit shifts and are quite efficient. For instance, shifting everything up by 4 bits gives you a precision of 1/16. You do have to have 4 bits of headroom on your values however...
 
Did a quick google and found Microchips floating-point library for PIC16/17:

http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1824&appnote=en010961
 
Last edited by a moderator:
Very basic question. Consider a 3-terminal device with terminals say A,B,C. Kirchhoff Current Law (KCL) and Kirchhoff Voltage Law (KVL) establish two relationships between the 3 currents entering the terminals and the 3 terminal's voltage pairs respectively. So we have 2 equations in 6 unknowns. To proceed further we need two more (independent) equations in order to solve the circuit the 3-terminal device is connected to (basically one treats such a device as an unbalanced two-port...
suppose you have two capacitors with a 0.1 Farad value and 12 VDC rating. label these as A and B. label the terminals of each as 1 and 2. you also have a voltmeter with a 40 volt linear range for DC. you also have a 9 volt DC power supply fed by mains. you charge each capacitor to 9 volts with terminal 1 being - (negative) and terminal 2 being + (positive). you connect the voltmeter to terminal A2 and to terminal B1. does it read any voltage? can - of one capacitor discharge + of the...
Back
Top