Keyboard Shortcuts
ctrl + shift + ? :
Show all keyboard shortcuts
ctrl + g :
Navigate to a group
ctrl + shift + f :
Find
ctrl + / :
Quick actions
esc to dismiss
Likes
Search
Si5351a issues with frequency resolution (step size) at 144MHz (or even lower frequencies)
I'm very confused about what frequencies can be set on the Si5351a in terms of what frequency you ask for and what frequency you actually get. I'm not concerned so much about the actual frequency as the accuracy of frequency step sizes which are requested.? I've read the spec sheet, which pretty much numbs my brain after a while. I've read lots of web articles, none of which actually answer the questions I have.? I'm certainly confused by the ability to specify the desired frequency with 0.01Hz resolution in the Arduino libraries. Presumably this is specifications of the Si5351a frequency determining registers rather than any actual ability to generate frequencies in 0.01Hz steps. Most of the arduino sketcchs seem to suggest at least 1Hz accuracy, even though it seems hard to even get exact 1Hz steps. The Si Labs clockbuilder utility for the Si5351 actually has the frequency input in steps of 0.001Hz.
The application is for a low power Q65 beacon on 144MHz. I can handle the Q65 with no problem. I can handle the frequency accuracy and stability with no problem. The problem comes in generating a set of tones with, for example, 6.667Hz spacing.? I have seem people reporting 2m WSPR transmitters, which have tight specs and need 1.4648Hz tone spacing, so 6.667Hz should be possible. For this application and with tone spacing this wide, the frequency step size doesn't have to be accurate to 3 decimal places. In fact anything around 6.6 +/- 0.5Hz would work. I can generate a set of tones which will, in fact, decode correctly, but the tones can be 1 or 2 Hz from where they should be, and that's not going to be a good thing when decoding weak signals. However Q65 tone spacing can be anything from 0.289 to 26.667Hz, depending on the period and submode, so the more accurately the frequency step size can be set, the better. For now I'm just interested in 6.667Hz tone spacing and frequencies set to the nearest 0.1Hz would be fine. Even to the nearest 0.5Hz would probably be OK. The problem is that, using something like the NT7S Si5351a Arduino library, I can't even get step sizes of 10Hz to me monotonic. They can be anything from 8Hz to 12Hz (though over enough steps they do average out to 10Hz). I have tried a few other arduino sketches and libraries, with similar results. I don't know if this is a fundamental limitation of the Si5351 (I don't think it is) or it's a limitation of the libraries in the way they calculate the values it sends to the Si5351 registers. Or maybe I'm just doing something stupid that I'm not seeing.? I'm just using one clock output (0) and currently I'm using a 25MHz crystal (mainly because I have an ultra stable 25MHz frequency reference source available). and I'm using an Arduino UNO3. I understand that the exact frequencies which can be generated (and hence exact step size) is related to the crystal frequency, though again I have seen reports (on this group) that WSPR beacons for 2m have been built using a 25MHz xtal and my frequency requirements are quite a bit less critical. I don't have to be on an exact sync frequency either, 144.18 or 144.2 or 144.27 (or pretty much anything else) would be equally good. It would not be channelized operation. So to generate signals at 144MHz with fairly uniform 6.7Hz steps do I need a different Arduino library (if such a library exists). I now there is a WSPR library, but in it it has the commentt line: "#define WSPR_FREQ2m? ? ? ? ? ? 14449500000ULL? ?//2m? ? 144.490,000MHz //Not working. No decode in bench test with WSJT-X decoding Software" Or do I need to write my own code which directly addresses the Si5351 registers (a task I'm not sure I want to try!) or do I need a different reference frequency - or perhaps all of the above? I could work using the 3rd harmonic of a 48MHz signal with 1/3 the tone spacing if doing things at 48MHz is easier, but then the tone spacing gets 3x smaller, plus it involves even more filtering and amplification, so 144 direct is certainly preferable. Any help, comments, pointers etc. would be most welcome. As you can probably guess, my knowledge of the inside workings of frequency synthesizers is somewhat limited! Thanks, Bob, KA1GT |
Bob,
toggle quoted message
Show quoted text
There are a few articles written by Hans Summers about the SI551 and the methods used to set the frequencies. They are in the files section and elsewhere on the QRPLabs site. They are required reading for people, like yourself, who wish to 'understand' the chip. On 22 Jan 2023 at 15:44, Bob Atkins wrote:
I'm very confused about what frequencies can be set on the Si5351a in terms of what frequency you ask for and what frequency you actually get. I'm not concerned so much about the actual frequency as the accuracy of frequency step sizes which are requested.? I've read the spec sheet, which pretty much numbs my brain after a while. I've read lots of web articles, none of which actually answer the questions I have.? I'm certainly confused by the ability to specify the desired frequency with 0.01Hz resolution in the Arduino libraries. Presumably this is specifications of the Si5351a frequency determining registers rather than any actual ability to generate frequencies in 0.01Hz steps. Most of the arduino sketcchs seem to suggest at least 1Hz accuracy, even though it seems hard to even get exact 1Hz steps. The Si Labs clockbuilder utility for the Si5351 actually has the frequency input in steps of 0.001Hz. The application is for a low power Q65 beacon on 144MHz. I can handle the Q65 with no problem. I can handle the frequency accuracy and stability with no problem. The problem comes in generating a set of tones with, for example, 6.667Hz spacing.? I have seem people reporting 2m WSPR transmitters, which have tight specs and need 1.4648Hz tone spacing, so 6.667Hz should be possible. For this application and with tone spacing this wide, the frequency step size doesn't have to be accurate to 3 decimal places. In fact anything around 6.6 +/- 0.5Hz would work. I can generate a set of tones which will, in fact, decode correctly, but the tones can be 1 or 2 Hz from where they should be, and that's not going to be a good thing when decoding weak signals. However Q65 tone spacing can be anything from 0.289 to 26.667Hz, depending on the period and submode, so the more accurately the frequency step size can be set, the better. For now I'm just interested in 6.667Hz tone spacing and frequencies set to the nearest 0.1Hz would be fine. Even to the nearest 0.5Hz would probably be OK. The problem is that, using something like the NT7S Si5351a Arduino library, I can't even get step sizes of 10Hz to me monotonic. They can be anything from 8Hz to 12Hz (though over enough steps they do average out to 10Hz). I have tried a few other arduino sketches and libraries, with similar results. I don't know if this is a fundamental limitation of the Si5351 (I don't think it is) or it's a limitation of the libraries in the way they calculate the values it sends to the Si5351 registers. Or maybe I'm just doing something stupid that I'm not seeing. I'm just using one clock output (0) and currently I'm using a 25MHz crystal (mainly because I have an ultra stable 25MHz frequency reference source available). and I'm using an Arduino UNO3. I understand that the exact frequencies which can be generated (and hence exact step size) is related to the crystal frequency, though again I have seen reports (on this group) that WSPR beacons for 2m have been built using a 25MHz xtal and my frequency requirements are quite a bit less critical. I don't have to be on an exact sync frequency either, 144.18 or 144.2 or 144.27 (or pretty much anything else) would be equally good. It would not be channelized operation. So to generate signals at 144MHz with fairly uniform 6.7Hz steps do I need a different Arduino library (if such a library exists). I now there is a WSPR library, but in it it has the commentt line: "#define WSPR_FREQ2m? ? ? ? ? ? 14449500000ULL? ?//2m? ? 144.490,000MHz // *Not working. No decode* in bench test with WSJT-X decoding Software" Or do I need to write my own code which directly addresses the Si5351 registers (a task I'm not sure I want to try!) or do I need a different reference frequency - or perhaps all of the above? I could work using the 3rd harmonic of a 48MHz signal with 1/3 the tone spacing if doing things at 48MHz is easier, but then the tone spacing gets 3x smaller, plus it involves even more filtering and amplification, so 144 direct is certainly preferable. Any help, comments, pointers etc. would be most welcome. As you can probably guess, my knowledge of the inside workings of frequency synthesizers is somewhat limited! Thanks, Bob, KA1GT |
Hi Bob Getting a frequency out of an Si5351A is a relatively straightforward thing to do. There are numerous code examples to look at and libraries to use. But unfortunately if you start to want more detailed, more specific outcomes... Then it can get a lot more complicated. I'm in my 8th year playing with this Si5351A chip and still learning new stuff. Back when I started I realized the main library available at that time was just junk derived from a Linux PC driver with little thought for how a microcontroller may have different needs. I believe it has been improved some over the years. But still if you want accurate results or anything special then, as you found, you're going to need to dig in.? The Si5351A is capable of very high orecision, you can achieve better than a milli-Hz at 144MHz and I suspect a few orders of magnitude higher precision than that.? The PLL feedback and the Division down from the internal PLL VCO are both fractional, of the form a + b / c. Both b and c are 20-bit integers.? Most code and libraries you see just fix c at 0xFFFFF and just vary b. This is what limits the resolution.? For example if you needed to represent a number like 35 + 2 / 3... then if you set b to 2 and c to 3 then you'd get your desired result with zero error. If you chose b=7 and c=10 it wouldn't be a good approximation. In the QDX manual i mentioned that QDX uses the rational best approximation algorithm to choose the best b and c for any target frequency. You'll need to Google got more details of it though.? Even then, as we found, there are still a lot of further details to consider, because 32-bit integer or single precision floating point isn't enough. 73 Hans G0UPL http://qrp-labs.com https://www.buymeacoffee.com/g0upl -------- Original message -------- From: Bob Atkins <bobatkins@...> Date: Mon, Jan 23, 2023, 6:36 AM To: [email protected] Subject: [QRPLabs] Si5351a issues with frequency resolution (step size) at 144MHz (or even lower frequencies) I'm very confused about what frequencies can be set on the Si5351a in terms of what frequency you ask for and what frequency you actually get. I'm not concerned so much about the actual frequency as the accuracy of frequency step sizes which are requested.? I've read the spec sheet, which pretty much numbs my brain after a while. I've read lots of web articles, none of which actually answer the questions I have.? I'm certainly confused by the ability to specify the desired frequency with 0.01Hz resolution in the Arduino libraries. Presumably this is specifications of the Si5351a frequency determining registers rather than any actual ability to generate frequencies in 0.01Hz steps. Most of the arduino sketcchs seem to suggest at least 1Hz accuracy, even though it seems hard to even get exact 1Hz steps. The Si Labs clockbuilder utility for the Si5351 actually has the frequency input in steps of 0.001Hz. |
Bob,
It looks as though to generate signals in the 144mhz range, the Si5351 will be using a fixed output divider of 6.? A simple Si5351 library that uses fixed point and does nothing fancy but does allow fractional frequencies should have a 1/6 hz accuracy, in that the PLL frequency is calculated to the nearest hz using fixed point.? To get a one hz change at 144mhz the PLL will change by 6 hz.? ( divider is 6 ).? To do better would require calculating the PLL frequency to a fractional frequency.? The NT7S library uses the target frequency scaled up by 100 for fractional frequencies, but I didn't look to see if it was scaling up the PLL frequency also.? I also found two NT7S libraries, one under etherkit which I think is the one everyone uses and some older C code that is aimed at Arduino.? I wonder which you tried. Ron? KE1MU Does anyone know where to download the old version of clockbuilder?? The new Pro version is crippled and no longer allows assigning PLL's to outputs or allows integer output dividers. |
Ron,? I don't know if any links exist to the original Clockbuilder Desktop, but I have the installation .zip file and can send you a copy if you need one.? I've used it and the new Clockbuilder Pro. The desktop version seems easier to use, but the Pro version (once you figure it out) seems to provide more information. I have not used either one enough to be aware of their limitations. It hasn't helped me so far. I can generate a set of bit values, which could then be assembled into bytes and uploaded to appropriate?registers, but I'm still struggling?with register names and sizes which don't always seem to correlate between the spec sheet and the Clockbuilder Pro output. No doubt it's my mistake and eventually I'll start to understand it better. It would be nice if some code (Arduino/C++) existed that took the Clockbuilder Pro register bit calculation results, assembled them into bytes and uploaded them to the Si5351. I guess parts of the required?code must already exist as parts of the Arduino library.? I did make an attempt at using?si5351.set_freq_manual, using the VCO frequency that clockbuilder found and hoping that the librartycode would do the rest, It seemed to work for one frequency, but for another it generated a very ugly, very wide spread signal, so obviously there's more to it than what I tried. Still learning here, only been battling with it for about a week!? I'm using 64 bit integers (ULL) and appropriate(?) coding, but I'm still doing no better then getting within a couple of Hz of the desired frequency, with significant variation in step size when trying to make equal steps of a few Hz. Bob, KA1GT On Mon, Jan 23, 2023 at 12:35 PM Ron Carr <rcarr@...> wrote: Bob, |
Yes Gyula, that seems to be it, thanks.?? It doesn't allow assigning even integer output dividers but I probably remember wrong.? It does seem to use even integer output dividers if possible.
Bob,? Do you have an example of two frequencies that have the the 8hz or 12 hz step instead of 10. Or a copy of the program you used for that test?? I could try to verify the error you are seeing although I am not sure my scope will count frequencies that high. Ron |
Hi Ron.? I don't think those frequency error examples are the best I can do if I switch to the Adafruit library, which seems to allow easier direct? manual control of some of the parameters
Using the Adafruit library and using the clockgen.setupPLL function, you can setup something like this clockgen.setupPLL(SI5351_PLL_A, 34, 463868, 762939); This sets PLL_A to the reference frequency (25MHz) * (34 +?463868/762939), which is what ClockBulder Desktop suggests. ClockBulder pro suggests? 34.6080016 but gives no integer divider in the report. Presumably it incorporates integer dividers in the suggests C++code for the SI5351 registers. It presumably used the same fraction as ClockBuilder Desktop. PLL A
?Input Frequency (MHz) = 25.000000000
?VCO Frequency (MHz) =? 865.200040002
?Feedback Divider = 34? 463868/762939
?SSC disabled
?
Output Clocks
Channel 0
?Output Frequency (MHz) = 144.200006667
?Multisynth Output Frequency (MHz) = 144.200006667
?Multisynth Divider = 6
This works with the Adafruit library, but the problem is that it doesn't quite give the desired output frequency (144.200006667). The problem is that the Frequency Divider should actually be 34.6080016, and that's not quite the same as the fraction given by Clockbuilder desktop. 463868/762939 = 0.608002736784985431338...
so the xtal is multiplied to (25*34.60800142606420) = 865.20003565160517...
when this is divided by 6 gives 144.200005942, an error of 0.725Hz
I think 463868/762939 is the best you can do with 20-bit registers (I think they are 20bit?), so using this method you may get close to the desired frequency, but still nowhere near the 0.001 or even 0.01Hz accuracy that you see quoted for the Si5351 in various places. The other issue is coming up with a good algorithm for calculating the nearest set of 20-bit numbers to use for the fractional divider. How do you turn? 0.6080016 into a fraction (nearest the correct value) using only 20-bit numbers? That's what ClockBuilder does, but if you have to run ClockBuilder for every frequency you want to generate (and codes like JT65 and Q65 have 65 frequencies) it gets a bit tedious, even for just one sync (base) frequency.? And you are still not exactly on frequency for? of the tones.? The final divider in the chain from PLL_A to the output frequency is an integer (Multisynth Divider = 6).? I guess in order to get higher frequency resolution, you would have to use a fractional divider, and from what I can see, this has to be somewhere between 8 and 900. I don't then see any way to use a fractional divider to generate a signal near 144MHz.? If the PLL limit is 900MHz and the Multisynth Divider can be integers 4, 6 or 8, or fractions between 8 and 900, you can never use fractions above 900/8 = 112.5MHz and so probably never generate signals above 144MHz to better then the nearest 1Hz.? You might be able to generate a particular frequency with the right crystal and fractional divider, but you can't then step the frequency in uniform sub-Hz steps. This would make WSPR on 144 a difficult task, though maybe you can get close enough to the 1.465Hz tone spacing to get it to work (sometimes?). I think I've seen posts saying that it is possible, though I've also seen comments in code that it doesn't). Am I understanding this correctly? If so then the only way to generate 144Mhz signals with high accuracy and resolution, would probably by using harmonics, probably working at 48MHz and looking at the 3rd harmonic. Accuracy abd step size would be 1.3 of that at 48MHz, but probably still better than directly synthesizing at 144MHz. Or am I still missing something? |
Hi Bob,
I think you have a good understanding of the limitations of working above 112.5 mhz where you need to use a fixed output divider of 4,6, or 8.? Finding the correct denominator is what Hans mentioned, rational best approximation. What I have done with one of my WSPR projects is divide the XTAL frequency by my output divider and then divide again by my desired step, in my case 1.4648 and use that number for my value for c? in the a + b/c equation.? What this does is make each increment of b? in the equation result in the output frequency changing by the desired step, and then I have manipulated b directly to send the WSPR signals.? In your case if you divide 25mhz by 6 and then by 6.66666667 you get the somewhat magic value (rounded) of 625000. 0.6080016 * 625000 is 380001 exactly.? The downside of this method is that setting your base frequency will have error, but the steps up from that frequency will be accurate.? ( must be careful using this approach? as c needs to be below 1048575, but works for 6.6667 steps on 144mhz ). I took a look at the Adafruit library and it is an interesting way to approach things.? It does use float calculations for the divisions so I think it will have some error. My WSPR code using this method is here: The Si5351 routines would need changes to work on 144mhz with the fixed divider of 6.? This project also used an R divider for the transmit which would need to be removed. |
Another similar way to generate accurate offsets from a base frequency is to manipulate the solution P1, P2, P3 terms directly.? I have been using this method just recently and I think it works.? The way this works is to generate a solution for a base frequency and save the P1,P2 and P3 terms in some global variables.?? If you make P3( the c term of the equations ) equal to the crystal frequency divided by the output divider, you have again the b term such that a change of b by 1 will result in a change of 1 hz in the final output frequency.? Of interest is that changing b by one changes the P2 term by 128.? The frequency resolution on HF will be 1/128 hz.
For vhf the P3 term will calculate larger than allowed and for a 25mhz crystal it will have to be divided again by 4 and for a 27 mhz crystal by 5.? So for a 25mhz crystal and final output on 2 meters we get a P3 value of 25mhz / 6 / 4 which is 1,041,667 (rounded).? The 128 factor will need to be divided by 4.? 128/4 = 32.? The frequency resolution on 2 meters is 1/32 hz. To use this idea on 2 meters the method is to generate a solution for a base frequency using the P3 value above and save the P1,P2 and P3 terms in global variables.? You call a separate function to generate positive offsets from the base. The function will look something like: void freq_offset ( float offset ){ uint32_t p1,p2,p3; ??? p1 = P1, p2 = P2, p3 = P3;??????????? // get the base solution ??? p2 +=? (int32_t)(offset * 32.0);?????? // add desired factional offset. ? could add 0.5 to round the result instead of truncation shown ??? while( p2 >= p3 ) p2 -= p3, ++p1;? // p2 needs to be less than p3 ?now you would do the bit shifts and masking to find the values to load into the registers and write them to the si5351. Setting the base frequency will have a 4 hz accuracy.? The offsets from the base should be very accurate ( 1/32 hz ). ??? |
to navigate to use esc to dismiss