-
-
Notifications
You must be signed in to change notification settings - Fork 98
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Speed of switching frequencies? #22
Comments
There's no doubt that set_freq() was written with ease of tuning prioritized over tuning speed, and your tuning speed sounds similar to my experiences. This issue has been raised previously in a slightly different form ( #5 ), so I am aware that it's something which could be improved. I'm not sure when I can get to the implementation of #5, but it is fairly high on my list of features to add. In the mean time, which Arduino version are you using to drive the Si5351? If you are using a 8 or 16 MHz microcontroller, I wonder if you wouldn't see a fair bit of speed improvement in trying a Due or a Zero, which has much greater clock speed. I haven't profiled the code, but I suspect most of the time spent in the tuning routine is in doing math, so a faster micro would probably help. If you can't try it with a faster micro, let me know and I'll see if I can find some time to run an experiment here. |
I used an Arduino Uno, first. |
Yes, it may be feasible to set up either of the methods you described, as I have experimented with both techniques in trying to get the Si5351 to generate PSK. You could manually set up the two different PLLs, and then switch between them using the Alternately, you could use the CLK1 output as your main output, set CLK0 and CLK1 as your mark and space frequencies, and then switch the output mux between the CLK0 output and the CLK1 output to get your FSK, using
and
Hopefully that will give you a workaround until direct register set access can be better implemented. Good luck! |
There is some intrinsic switching time when using the 2nd method where there is no output at all during the switch, so it may not be suitable for your needs. It may also affect the first method, although my memory is failing me on that at the moment. If those don't work, you may be forced to manually calculate the registers to twiddle for FSK until #5 can be implemented. |
Cool, thanks for the input! I'll give those a try. (As I'm just now starting to dive into the RF mire, but this sounds useful.) |
Comment after the fact: The Si5351 PLLs may take up to 10ms thereabouts to lock onto a new frequency when changed, so (though I haven't gotten this far yet) to get switching times well below that, the change has to happen in the MultiSynth stage for any guarantees to be made. |
Additional comment which solved the problem: Kicking up the Wire library speed from 100kHz to 400kHz with |
@snout Excellent! Glad you could find a way to get the desired result! I recall that bulk transfer is available, but it just slipped my mind so I'm glad you reminded me of that. I'm going to reopen this issue just so I can look into the feasibility of adding those features to the main library code. |
My code (on the Mega2560):
Then in the loop, when sending: To make this a little more generic, if timing allows, I'm fairly sure that P1, P2 and P3 (the three synth components) can be shifted-and-logic-function done in the send stage, though I wanted to do as little as possible in there. When quick shifting is needed, I'm (again) fairly sure that the calculating of P1 and P2, involving multiplication, division, and several math functions, I'd suggest an array of a few P1P2P3 tuples that can be precalculated, then sent with just a reference to which tuple is to be the new MS-configuration. |
I'm working on a inexpensive VNA using the TI MSP432 and Energia, and trying to figure out how to make sweeps faster and more reliable. Here is my code: `void setup()
}` And the function that changes frequency by being called over and over again.
}` I would love to remove the delay(500), but if even cut it down very much it ends up picking daisies after a few iterations. Thanks, Rob |
@snout I'd love to see your actual Arduino code. I'm looking to retrofit an old crystal-based scanner with an Etherkit Si5351. The Arduino will set it's output based on what channel is being scanned, so I've got to tune it pretty quickly. I'd love to tune by your method, but am having trouble understanding how to go from say the settings given by Clock Builder Plus to what needs to go into the Arduino sketch... Thanks much and 73, |
The code is here on github. As I recall, we tuned it down to the minimum I could get away with, and it was much less than the 500 mS above. Here is the URL: |
@frohro Hi Rob - excellent, thanks much! I'll take a look at this shortly. :) thanks much and 73, |
Did the above replies help? What I ended up doing was to have the two PLLs in the chip, PLL_A and PLL_B set to different frequencies that were just 15kHz above and below the 'target' 27,145MHz "center" that the receiver expected. I used the Clock Builder to calculate the frequencies so that the divider was an integer, and had to do this because the receiver I was toying with was very picky, and the divider in the Si chip is - even mentioned in the datasheet - prone to give a little jitter when dividing by a float instead of 'doing it in integer mode'. So the end result became: Set the divider to a common integer that fits both frequencies, then set PLL_A and PLL_B to those, and when transmitting data, simply send a command to the chip 'switch to PLL so-and-so as input now!', in effect using the two PLLs to represent mark and space and never changing the PLL frequencies or the MultiSynth divider settings. Like NT7S said further up in the thread: "You could manually set up the two different PLLs, and then switch between them using the set_ms_source() method." Simply sending the 'change PLL' command is also a very quick operation, so that works out just fine for me. I noted above that I had to use a Mega2560 because the comparatively slow Arduino Uno at 8MHz wasn't fast enough to send the 'change PLL' commands in time for them to still be within the receiver's expected timeout-waiting-for-valid-bit. Well! I hope this gives some insight in what I did and for what convoluted reasons. The end result - a jitter free transmission that worked for my single intended purpose, but not suitable for quickly shifting to other frequencies because of its construction. (As in, shifting requires a lot more commands than just 'switch clock source'. As for your question about setting up the divider/multisynth, here's the few lines of code that does that for me (this all taken from either examples found in libraries, or in the library code itself, and the multiplier, number and denominator algorithms I think I got from the Si datasheet): For the multiSynth divider: ..and when transmitting: [transmitting bits in a loop using this code - note that I had to tweak the timing between bits aswell to get it just right. Not sure if that value will create 1ms on any board, or if it varies with, well, temperature or what have you other conditions.] void send_bit_with_multisynth(byte the_bit) { [and finish with] |
Thanks Ben, |
Good morning all, Thanks much for the multiple helpful replies! I'm still working my way thru them, the datasheet, and the AN619 application note. It's going pretty slowly, but I think I'm making progress. ;) I also came across code by Christophe, OE1CGS, where everything is done with a minimum of libraries - just the Wire.h library in fact. :) I'll post a link and the code below just for completeness: https://www.qrp-labs.com/synth/oe1cgs.html Please excuse the below for not being in a code box. I put in between the marks and it doesn't work? Strange, I must be doing something wrong. Anyways, thanks much the replies! Thanks and 73, ` void setup() { void loop() { void TX_ON () { // Enables output on CLK0 and disables Park Mode on CLK1 void TX_OFF () { // Disables output on CLK0 and enters Park Mode on CLK1 void SetFrequency (unsigned long frequency) { // Frequency in Hz; must be within [7810 Hz to 200 Mhz] outdivider = 900000000 / frequency; // With 900 MHz beeing the maximum internal PLL-Frequency while (outdivider > 900){ // If output divider out of range (>900) use additional Output divider fvco = outdivider * R * frequency; // Calculate the PLL-Frequency (given the even divider) switch (R){ // Convert the Output Divider to the bit-setting required in register 44 a = fvco / F_XTAL; // Multiplier to get from Quartz-Oscillator Freq. to PLL-Freq. MS0_P1 = 128 * outdivider - 512; // Calculation of Output Divider registers MS0_P1 to MS0_P3 f = 128 * b / c; // Calculation of Feedback Multisynth registers MSNA_P1 to MSNA_P3 Si5351a_Write_Reg (16, 128); // Disable output during the following register settings void SetParkMode () { // Sets CLK1 to the Park Mode frequency of 150 MHz to keep the Si5351a warm during key-up void SetPower (byte power){ // Sets the output power level void Si5351a_Write_Reg (byte regist, byte value){ // Writes "byte" into "regist" of Si5351a via I2C |
I'm trying to build a naive FSK transmitter, by sending 1ms long 'zero' (27.145.900MHz) or 'one' (27.143.000MHz) "bits", and am using the test case:
si5351.set_freq(2714590000ULL, SI5351_PLL_FIXED, SI5351_CLK0); // zero bit
delayMicroseconds(5000);
si5351.set_freq(2714300000ULL, SI5351_PLL_FIXED, SI5351_CLK0); // one bit
delayMicroseconds(1000);
But it seems like the minimum time in my pulses is 4ms output. When checking with 3MHz and 7MHz (to take two random, far-apart frequencies that my 16Msps scope can handle) I see that the minimum time for one pulse (or burst of the same frequency) is a little over 3ms, regardless of how low I drop the delayMicroseconds.
Is there a clever way to switch frequencies, considering that I only have one output that I will be using, and only two fixed frequencies (or one base frequency with +/- of some kHz) that will be sent?
Is set_freq itself a slow routine and not meant to be used for this purpose, but some other trickery to change the output faster, once the PLL frequency has been set?
The text was updated successfully, but these errors were encountered: