etherkit / Si5351Arduino

Library for the Si5351 clock generator IC in the Arduino environment
GNU General Public License v3.0
233 stars 95 forks source link

VCXO on Si5351B #34

Closed akadamson closed 7 years ago

akadamson commented 7 years ago

I just found an annoying bug, but I don't know what the fix it. If you build from a cold start the VCXO example, and run it, it will work the first time... but if you change anything that breaks it (e.g. because out 5351 is clocked from a TCXO, I set the capacitance to 0PF, then rebuilt, and nothing, no output, changed back to 8PF and nothing. Let the 5351 set unpowered until all the capacitors are fully drained and it will run again. I think there is some setup in the VCXO configuration that isn't being done that could clear and error from a problem. I'll spend some time, looking at it, but figured I'd let you know as well as I'm sure you have way more experience with the library/part than I do... Hoping you find the issue :)

NT7S commented 7 years ago

@akadamson Looking over your description, I just noticed that you mentioned that your reference is a TCXO. While I can't say this with absolute certainty, I'm fairly sure that won't work if you want to use the VCXO option. The datasheet indicates that you need to have a plain old crystal reference to pull. I'll still try to recreate your issue with my setup, but I wanted to pass that along immediately.

akadamson commented 7 years ago

It shouldn't matter, the 5351 just needs a clock, in this case it gets it from a TCXO, instead of an XO. And to make matters worse, the VCXO input works - occasionally, usually after the chip has been powered down, let set for a while, then powered back up, if you change anything on the 5351 and try it without a long duration power cycle, it won't output a frequency, until you power it down and let it set. It's really like something is getting set that shouldn't be, or something is being set out of sequence with the VC support. As further info, I'm using output 4, but as noted, it works once in a great while, but not consistently

NT7S commented 7 years ago

@akadamson When you said you changed the load capacitance to 0 pF, did you mean that you changed that value in the init() parameter or you changed it manually in code later? I changed it to 0 pF, 6 pF, and 8 pF and all worked as expected (with my board that has a crystal osc, not a TCXO).

As for the choice of reference, I'm not sure that I agree that it doesn't matter. The datasheet is not clear on the exact mode of operation of the VCXO, and whether it modulates the reference itself on XA or the VXCO stage internally. I'll do some more investigation.

NT7S commented 7 years ago

OK, I didn't have a TCXO handy, but I used a 2nd Si5351A breakout to supply an external 25 MHz reference to the Si5351B board. This does mostly work, but I do have some occasional failures when changing the capacitor load value in the init and re-upload the sketch. Hopefully this will be good enough for me to use for troubleshooting.

On a side note, I have also been feeding the ext clock through a 10 dB (50 ohm) pi attenuator pad to XA. (As has been pointed out to me, the datasheet specifies a max of 1 Vpp signal on this input, so I'll be making this change to the next rev of the breakout board). I'm not certain if this has any effect on this problem, but it's worth noting.

akadamson commented 7 years ago

So, yes, with a TCXO driving the part, it shouldn't need additional capacitance from the internal 0, 6, 8pf values. I've tried with with a standard 8pf and 0pf and both have the same behavior in that if you make any change while the 5351 is powered and re-try is will still most likely fail. If you power it down, leave it and then run the same code, it may work. Good catch on the input voltage from a TCXO, we are using a 1.8v TCXO, so it output voltage is .8v p2p Also our TCXO is a 26mhz one if you want to try that as the TXCO (5351A) frequency.

NT7S commented 7 years ago

Wanted to note something interesting I found. I changed my reference clock to 26 MHz as you stated that you use and I cannot get a proper amount of pull from VC at all. It barely responds to VC. I do wonder if perhaps that has some factor in this, as 26 MHz is not officially supported as a reference frequency on the XA input.

I'll keep experimenting.

NT7S commented 7 years ago

I noticed that the VCXO param registers retain their value when the power is on, so I was wondering if explicitly zeroing them out would do anything different. If you wouldn't mind, try inserting this code after your call to init() in your sketch and let me know if it changes the behavior at all:

si5351.si5351_write(SI5351_VXCO_PARAMETERS_LOW, 0);
si5351.si5351_write(SI5351_VXCO_PARAMETERS_MID, 0);
si5351.si5351_write(SI5351_VXCO_PARAMETERS_HIGH, 0);

Since adding that and changing the ref clock back to 25 MHz, I haven't had any issues yet, after many tries of changing the cap value in init(). Perhaps try this and try a 25 MHz ref if you can to see if it makes any difference in your case. As of now, I'm stuck because I can no longer get it to fail.

akadamson commented 7 years ago

Thanks so much, I'll indeed this this parameter to zero change. Kinda hard for me to change the 26mhz TCXO, but we'll go to a 25 the next time around.... I'll report vs. the 26mhz probably tomorrow. Thanks for spending the time!!!

akadamson commented 7 years ago

Well, no joy. It worked about 1 time in 8... here is my actual code

/*

  • si5351_vcxo.ino - Example for using the Si5351B VCXO functions
  • with Si5351Arduino library
  • Copyright (C) 2016 Jason Milldrum milldrum@gmail.com
  • This program is free software: you can redistribute it and/or modify
  • it under the terms of the GNU General Public License as published by
  • the Free Software Foundation, either version 3 of the License, or
  • (at your option) any later version.
  • This program is distributed in the hope that it will be useful,
  • but WITHOUT ANY WARRANTY; without even the implied warranty of
  • MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  • GNU General Public License for more details.
  • You should have received a copy of the GNU General Public License
  • along with this program. If not, see http://www.gnu.org/licenses/. */

include "si5351.h"

include "Wire.h"

define PLLB_FREQ 87600000000ULL

Si5351 si5351;

void setup() { // Start serial and initialize the Si5351 Serial.begin(57600);

analogWriteResolution(8);

pinMode(11,OUTPUT); digitalWrite(11, HIGH); delay(500); digitalWrite(11, LOW); delay(10000);

analogWrite(A0, 10);

si5351.init(SI5351_CRYSTAL_LOAD_0PF, 26000000UL, 0);

// add to see if the frequency will lock si5351.si5351_write(SI5351_VXCO_PARAMETERS_LOW, 0); si5351.si5351_write(SI5351_VXCO_PARAMETERS_MID, 0); si5351.si5351_write(SI5351_VXCO_PARAMETERS_HIGH, 0);

// Set VCXO osc to 866.340 MHz (144.390 MHz x 6), 40 ppm pull si5351.set_vcxo(PLLB_FREQ, 40);

// Set CLK0 to be locked to VCXO si5351.set_ms_source(SI5351_CLK4, SI5351_PLLB);

// Tune to 146 MHz center frequency si5351.set_freq_manual(14600000000ULL, PLLB_FREQ, SI5351_CLK4); //si5351.set_freq(14600000000ULL, SI5351_CLK4); //si5351.drive_strength(SI5351_CLK4, SI5351_DRIVE_8MA);

si5351.update_status(); delay(500); }

void loop() { static bool flip = false;

// Read the Status Register and print it every 10 seconds si5351.update_status(); Serial.print("corr: "); Serial.print(si5351.get_correction()); Serial.print(" SYS_INIT: "); Serial.print(si5351.dev_status.SYS_INIT); Serial.print(" LOL_A: "); Serial.print(si5351.dev_status.LOL_A); Serial.print(" LOL_B: "); Serial.print(si5351.dev_status.LOL_B); Serial.print(" LOS: "); Serial.print(si5351.dev_status.LOS); Serial.print(" REVID: "); Serial.println(si5351.dev_status.REVID);

if (flip = !flip) { analogWrite(A0, 10); } else { analogWrite(A0, 250); }

delay(5000); }

that section at the top around the pinMode for pin 11, is just for a FET that turns on the 1.8v supply that provides the power for the regulator and TCXO. You can comment it out. The rest is exactly as your test, but I diddle the analog output pin on the arduino to provide the voltage change on the VCXO. Between 10 and 250 which 0 would be 0v and 255 would be 3.3v

akadamson commented 7 years ago

Well, we proved the theory. There seems to be a problem in the library for the B variant with VC enabled. If I generate the registers with SiLabs Clock builder and load each linearly top to bottom, the VC input works correctly every time with a 26mhz TCXO. If however I use the library method for setting the registers it only works about 1 in 10 resets.

Also for a specified 40ppm configuration at 146mhz, the clockbuilder register values work correctly, that should equate to an approx 5.840khz and I see approx that movement from the carrier when I change the VC input from min to max of the voltage range. HOWEVER with the library setup, that same min max voltage change, when it's working, only equates to a very small freqency shift, probably on the order or < 1khz. So my guess is there is some math issues that are effecting this issue and I don't know if it's in the PLL calc or the register settings.

Here are the registers and configuration that I used clockbuilder to generate

/*
 * Design Report
 *
 * Overview
 * ========
 * Part:         Si5351B Rev B
 * Created By:   ClockBuilder Pro v2.13 [2017-03-03]
 * Timestamp:    2017-03-16 15:47:08 GMT-04:00
 * 
 * Design Rule Check
 * =================
 * Errors:
 * - No errors
 * 
 * Warnings:
 * - No warnings
 * 
 * Design
 * ======
 * Inputs:
 *     IN0: 26 MHz
 * 
 * Outputs:
 *    OUT0: Unused
 *    OUT1: Unused
 *    OUT2: Unused
 *    OUT3: Unused
 *    OUT4: 146 MHz
 *          Enabled LVCMOS 4 mA
 *          Offset 0.000 s 
 *    OUT5: Unused
 *    OUT6: Unused
 *    OUT7: Unused
 * 
 * Frequency Plan
 * ==============
 * PLL_B:
 *    Enabled Features = VCXO
 *    Fvco             = 876 MHz
 *    M                = 33.6923076923076923... [ 33 + 9/13 ]
 *    Input0:
 *       Source           = Crystal
 *       Source Frequency = 26 MHz
 *       Fpfd             = 26 MHz
 *       Load Capacitance = Not_Applicable
 *    Output4:
 *       Features       = VCXO
 *       Disabled State = StopLow
 *       R              = 1  (2^0)
 *       Fout           = 146 MHz
 *       N              = 6
 * 
 * Settings
 * ========
 * 
 * Location      Setting Name   Decimal Value  Hex Value
 * ------------  -------------  -------------  ---------
 * 0x0002[3]     XO_LOS_MASK    0              0x0      
 * 0x0002[4]     CLK_LOS_MASK   1              0x1      
 * 0x0002[5]     LOL_A_MASK     1              0x1      
 * 0x0002[6]     LOL_B_MASK     0              0x0      
 * 0x0002[7]     SYS_INIT_MASK  0              0x0      
 * 0x0007[7:4]   I2C_ADDR_CTRL  0              0x0      
 * 0x000F[2]     PLLA_SRC       0              0x0      
 * 0x000F[3]     PLLB_SRC       0              0x0      
 * 0x000F[4]     PLLA_INSELB    0              0x0      
 * 0x000F[5]     PLLB_INSELB    0              0x0      
 * 0x000F[7:6]   CLKIN_DIV      0              0x0      
 * 0x0010[1:0]   CLK0_IDRV      0              0x0      
 * 0x0010[3:2]   CLK0_SRC       3              0x3      
 * 0x0010[4]     CLK0_INV       0              0x0      
 * 0x0010[5]     MS0_SRC        0              0x0      
 * 0x0010[6]     MS0_INT        0              0x0      
 * 0x0010[7]     CLK0_PDN       1              0x1      
 * 0x0011[1:0]   CLK1_IDRV      0              0x0      
 * 0x0011[3:2]   CLK1_SRC       3              0x3      
 * 0x0011[4]     CLK1_INV       0              0x0      
 * 0x0011[5]     MS1_SRC        0              0x0      
 * 0x0011[6]     MS1_INT        0              0x0      
 * 0x0011[7]     CLK1_PDN       1              0x1      
 * 0x0012[1:0]   CLK2_IDRV      0              0x0      
 * 0x0012[3:2]   CLK2_SRC       3              0x3      
 * 0x0012[4]     CLK2_INV       0              0x0      
 * 0x0012[5]     MS2_SRC        0              0x0      
 * 0x0012[6]     MS2_INT        0              0x0      
 * 0x0012[7]     CLK2_PDN       1              0x1      
 * 0x0013[1:0]   CLK3_IDRV      0              0x0      
 * 0x0013[3:2]   CLK3_SRC       3              0x3      
 * 0x0013[4]     CLK3_INV       0              0x0      
 * 0x0013[5]     MS3_SRC        0              0x0      
 * 0x0013[6]     MS3_INT        0              0x0      
 * 0x0013[7]     CLK3_PDN       1              0x1      
 * 0x0014[1:0]   CLK4_IDRV      1              0x1      
 * 0x0014[3:2]   CLK4_SRC       3              0x3      
 * 0x0014[4]     CLK4_INV       0              0x0      
 * 0x0014[5]     MS4_SRC        1              0x1      
 * 0x0014[6]     MS4_INT        1              0x1      
 * 0x0014[7]     CLK4_PDN       0              0x0      
 * 0x0015[1:0]   CLK5_IDRV      0              0x0      
 * 0x0015[3:2]   CLK5_SRC       3              0x3      
 * 0x0015[4]     CLK5_INV       0              0x0      
 * 0x0015[5]     MS5_SRC        0              0x0      
 * 0x0015[6]     MS5_INT        0              0x0      
 * 0x0015[7]     CLK5_PDN       1              0x1      
 * 0x0016[1:0]   CLK6_IDRV      0              0x0      
 * 0x0016[3:2]   CLK6_SRC       3              0x3      
 * 0x0016[4]     CLK6_INV       0              0x0      
 * 0x0016[5]     MS6_SRC        0              0x0      
 * 0x0016[6]     FBA_INT        0              0x0      
 * 0x0016[7]     CLK6_PDN       1              0x1      
 * 0x0017[1:0]   CLK7_IDRV      0              0x0      
 * 0x0017[3:2]   CLK7_SRC       3              0x3      
 * 0x0017[4]     CLK7_INV       0              0x0      
 * 0x0017[5]     MS7_SRC        0              0x0      
 * 0x0017[6]     FBB_INT        0              0x0      
 * 0x0017[7]     CLK7_PDN       1              0x1      
 * 0x0024[17:0]  MSNB_P1        3800           0x00ED8  
 * 0x0027[19:0]  MSNB_P2        615392         0x963E0  
 * 0x0027[23:4]  MSNB_P3        1000012        0xF424C  
 * 0x004C[17:0]  MS4_P1         256            0x00100  
 * 0x004F[19:0]  MS4_P2         0              0x00000  
 * 0x004F[23:4]  MS4_P3         1              0x00001  
 * 0x005A[7:0]   MS6_P1         0              0x00     
 * 0x005B[7:0]   MS7_P1         0              0x00     
 * 0x0095[14:0]  SSDN_P2        0              0x0000   
 * 0x0095[7]     SSC_EN         0              0x0      
 * 0x0097[14:0]  SSDN_P3        0              0x0000   
 * 0x0097[7]     SSC_MODE       0              0x0      
 * 0x0099[11:0]  SSDN_P1        0              0x000    
 * 0x009A[15:4]  SSUDP          0              0x000    
 * 0x00A2[21:0]  VCXO_PARAM     174057         0x02A7E9 
 * 0x00B7[2:0]   SLAB_PLLA_CL   2              0x2      
 * 0x00B7[5:3]   SLAB_PLLB_CL   2              0x2      
 * 0x00B7[7:6]   XTAL_CL        0              0x0
 * 
 *
 */
akadamson commented 7 years ago

Forgot to include the easy register setup for above.. Just step through the array and set those registers top to bottom... note, I used output 4 because it was already wired into my design, but you could generate for any output with clockbuilder

si5351b_revb_register_t const si5351b_revb_registers[SI5351B_REVB_REG_CONFIG_NUM_REGS] =
{
  { 0x0002, 0x33 },
  { 0x0007, 0x01 },
  { 0x000F, 0x00 },
  { 0x0010, 0x8C },
  { 0x0011, 0x8C },
  { 0x0012, 0x8C },
  { 0x0013, 0x8C },
  { 0x0014, 0x6D },
  { 0x0015, 0x8C },
  { 0x0016, 0x8C },
  { 0x0017, 0x8C },
  { 0x0022, 0x42 },
  { 0x0023, 0x4C },
  { 0x0024, 0x00 },
  { 0x0025, 0x0E },
  { 0x0026, 0xD8 },
  { 0x0027, 0xF9 },
  { 0x0028, 0x63 },
  { 0x0029, 0xE0 },
  { 0x004A, 0x00 },
  { 0x004B, 0x01 },
  { 0x004C, 0x00 },
  { 0x004D, 0x01 },
  { 0x004E, 0x00 },
  { 0x004F, 0x00 },
  { 0x0050, 0x00 },
  { 0x0051, 0x00 },
  { 0x005A, 0x00 },
  { 0x005B, 0x00 },
  { 0x0095, 0x00 },
  { 0x0096, 0x00 },
  { 0x0097, 0x00 },
  { 0x0098, 0x00 },
  { 0x0099, 0x00 },
  { 0x009A, 0x00 },
  { 0x009B, 0x00 },
  { 0x00A2, 0xE9 },
  { 0x00A3, 0xA7 },
  { 0x00A4, 0x02 },
  { 0x00B7, 0x12 },
};
NT7S commented 7 years ago

Thank you for all of the data. I'll be away from my office for a few days but will start working with it when I'm back.

akadamson commented 7 years ago

Just wondering if you ever figure out the issue here?

NT7S commented 7 years ago

Haven't had time to look at it yet, but I hope to soon. I'm a one-man operation here and sometimes get pulled in different directions. I do want to get this working.

akadamson commented 7 years ago

:)... ya I hear ya.. you may have improved part of it. The PPS swing of your original implementation when it works and the register setting version above, is grossly different. Your is about 4 times smaller :)... So I'm wondering what other math is messed up and might be setting a VC register to a really small version and only occasionally will the VC work as a result. BTW, we verified with SiLabs that the 25/26/27 mhz doesn't matter, in fact in their latest software that generated the registers above, you can pick any clock you want, where the original version forced you to 25 or 27.

NT7S commented 7 years ago

@akadamson OK, I believe I found the source of the error. Please manually install the library from this branch and let me know if that fixes it for you: https://github.com/etherkit/si5351arduino/tree/v2.0.4

I set up one Si5351A board as a ref osc for my Si5351B board, and was able to test it with 25, 26, and 27 MHz reference clocks and now all seem to behave as expected, but I didn't do a super comprehensive test, so I'm counting on you to try to break it or not, thanks.