Si5351 : Ne pas tirer de conclusion trop hâtive

Après avoir testé différents codes et regardé des vidéos type Youtube que l’on trouve un peu partout sur internet concernant le générateur programmable de fréquences  Si5351, je suis resté un peu sur ma fin. J’envisageais tout bonnement d’utiliser un autre circuit intégré. Mais, voilà il y a un mais. Et je vais donc profiter de cet article pour vous exposer ce « mais ».

A la fin de l’article, vous trouverez la liste du matériel utilisé et les liens afférents.

Voici un des multiples exemples de ce que l’on peut trouver couramment dans les tutos sur ce circuit intégré:

Logiciel de base adafruit

#include <Wire.h>
#include <Adafruit_SI5351.h>

Adafruit_SI5351 clockgen = Adafruit_SI5351();

/**************************************************************************/
/*
Arduino setup function (automatically called at startup)
*/
/**************************************************************************/
void setup(void)
{
Serial.begin(9600);
Serial.println(« Si5351 Clockgen Test »); Serial.println(«  »);

/* Initialise the sensor */
if (clockgen.begin() != ERROR_NONE)
{
/* There was a problem detecting the IC … check your connections */
Serial.print(« Ooops, no Si5351 detected … Check your wiring or I2C ADDR! »);
while(1);
}
Serial.println(« OK! »);

/* INTEGER ONLY MODE –> most accurate output */
/* Setup PLLA to integer only mode @ 900MHz (must be 600..900MHz) */
/* Set Multisynth 0 to 112.5MHz using integer only mode (div by 4/6/8) */
/* 25MHz * 36 = 900 MHz, then 900 MHz / 8 = 112.5 MHz */
Serial.println(« Set PLLA to 900MHz »);
clockgen.setupPLLInt(SI5351_PLL_A, 36);
Serial.println(« Set Output #0 to 112.5MHz »);
clockgen.setupMultisynthInt(0, SI5351_PLL_A, SI5351_MULTISYNTH_DIV_8);

/* FRACTIONAL MODE –> More flexible but introduce clock jitter */
/* Setup PLLB to fractional mode @616.66667MHz (XTAL * 24 + 2/3) */
/* Setup Multisynth 1 to 13.55311MHz (PLLB/45.5) */
clockgen.setupPLL(SI5351_PLL_B, 24, 2, 3);
Serial.println(« Set Output #1 to 13.553115MHz »);
clockgen.setupMultisynth(1, SI5351_PLL_B, 45, 1, 2);

/* Multisynth 2 is not yet used and won’t be enabled, but can be */
/* Use PLLB @ 616.66667MHz, then divide by 900 -> 685.185 KHz */
/* then divide by 64 for 10.706 KHz */
/* configured using either PLL in either integer or fractional mode */

Serial.println(« Set Output #2 to 10.706 KHz »);
clockgen.setupMultisynth(2, SI5351_PLL_B, 900, 0, 1);
clockgen.setupRdiv(2, SI5351_R_DIV_64);

/* Enable the clocks */
clockgen.enableOutputs(true);
}

/**************************************************************************/
/*
Arduino loop function, called once ‘setup’ is complete (your own code
should go here)
*/
/**************************************************************************/
void loop(void)
{
}

Et voici le spectre obtenu sur une charge résistive de 50 Ohms et un atténuateur de 30dB entre l’analyseur de spectre et la sortie Clock0 du SI 5351.

spectre Logiciel de base

Et à vide avec simplement un atténuateur de 30dB entre l’analyseur de spectre et la sortie Clock0 du SI 5351.

spectre non chargé Logiciel de base

Alors oui, ca ne me donne pas du tout envie de poursuivre avec un composant qui produit autant de raies (fréquences) pour un seul signal à 112.5 MHz.

Pour ce test, j’utilise les produits suivants :img_3217

  • Charge fictive 50 Ohms
  • Atténuateur 30 dB
  • Splitter à 2 sorties 50 Ohms
  • Analyseur scalaire D6
  • Oscilloscope Siglent 1202X-E (Sonde positionnée en X10)
  • Arduino MEGA Wemos

Pourquoi l’analyseur de spectre et non un oscilloscope pour réaliser ce test ?

Parmi les nombreuses raisons possibles voici 3 points en réponse à cela :

  • Le but est d’afficher la pureté du spectre en sortie et pas forcément la forme de l’onde qui de toute façon est carré selon la documentation du circuit intégré.
  • L’oscilloscope dont je dispose à mon domicile est un Siglent 1202X-E donc avec une bande passante de 200MHz Ce qui le rend incapable de représenter correctement la fréquence du signal que j’ai choisi dans cet exemple. Soit 112,5 MHz. En effet, il ne faut pas oublier qu’un oscilloscope standard numérique est capable de reproduire relativement fidèlement un signal 5 fois inférieur à la valeur de sa bande passante. Ici la bande passante étant de 200 MHz donc pas grand-chose à espérer en terme de fidélité pour un signal supérieur à 40 MHz. Ce problème n’existe pas sur un oscilloscope analogique.
  • La fonction FFT de mon oscilloscope est très loin d’être en capacité de réaliser ce que peut réaliser mon analyseur de spectre.

Voici, le signal carré à 112,5 MHz sur l’oscilloscope numérique à la bande passante trop étroite et pourtant de 200MHz. Le constat est dramatique :

SDS00040

Ormi la valeur de la fréquence du signal en haut à droite, cette mesure ne va pas nous apporter grand-chose comme information sur la “propreté » du signal au regard du besoin attendu. On est très loin du signal carré attendu. Et là, c’est l’oscilloscope qui n’est pas en capacité de par sa largeur de bande passante de reproduire avec fidélité ce qu’il mesure.

En conclusion sur le choix de l’appareil de mesure pour mon besoin en cours : Oscilloscope 0, Analyseur de spectre 1

Revenons à nos moutons:

L’analyseur de spectre utilisé ici est plus précisément l’analyseur scalaire D6. Vous trouverez plusieurs articles et liens à son sujet dans mon blog à partir d’ici. C’est l’occasion de mettre aussi en avant le logiciel VMA Simple Spectrum Analyser de Vitor Martins Augusto qui est un radioamateur portugais (à découvrir ici)

Comme nous l’avons vu plus haut que ce soit chargé ou non chargé le signal fourni en sortie du SI5351 est plutôt décevant. Le nombre de raies et leurs grandeurs présentes dans le spectre est bien trop importante à mon gout.

Déçu sur le fait de ne pas pouvoir agir sur l’ensemble des possibilités de ce circuit intégré à l’aide des exemples de programmes fournis çà et là. Quelques questions sont rapidement apparues, parmi lesquels :

  • Ce circuit intégré est-il à la hauteur de ses promesses ?
  • Ai-je fais le bon choix au regard de mon besoin ?
  • Faut-il des composants extérieurs pour obtenir un signal propre ?

Dans ce cas-là, rien de tel de laisser les programmes miraculeux qui fleurissent ça et là sur le net et autant se plonger dans la documentation du constructeur du composant.

Je me rends sur le site du constructeur Silicon Labs, ici puis je télécharge la DataSheet au format pdf du circuit intégré (ici).

Soulagement, une piste semble apparaître. Pour autant ça ne reste qu’un début dans ma quête. On le trouve au chapitre 7 « Register Map Summary » et aussi au chapitre 8 « Register Description », cela laisse supposer l’existence d’un document qui fournit des informations pour programmer les registres de ce circuit intégré.

Retour dans la documentation de chez Silicon Labs et direction ici dans la section « Resources ». De là, je débusque la note d’application AN619, ici.

Et là au miracle, il semble y avoir un nombre important d’informations qui devraient me permettre d’utiliser plus convenablement ce circuit intégré et donc d’en retirer son nectar. Finalement un coup de « stress » pour rien.

Cette note explique entre autre comment programmer manuellement les registres du Si5351 afin de produire son signal « aux petits oignons » dans le respect des possibilités de celui-ci. Le principe est d’envoyer via le bus I2C, directement dans les registres, les valeurs binaires pour les positionner à mon bon vouloir et donc me débarrasser des différentes librairies proposées par les uns et les autres qui ne sont pas nécessairement en phase avec mon besoin.

Etant partisan du moindre effort 😉 ou plus précisément du « Pourquoi réinventer l’eau froide ? ». Je suis donc retourné dans ce formidable outil qu’est internet et j’ai trouvé un site radioamateur qui aborde l’utilisation des registres de ce circuit intégré. Yeees !

Le site en question QRP Labs (à retrouver ici) et tout particulièrement ici aborde dans la langue deShakespeare différent points très judicieux pour utiliser convenablement ce circuit intégré.

Je vous invite à utiliser Google Traduction si vous avez des difficultés avec la langue anglaise. Ça fonctionne plutôt bien ici malgré les termes techniques relatifs à notre loisir.

En lisant la notice d’application AN619, j’ai noté la possibilité de paramétrer le courant disponible en sortie du SI5351. Ceci affecte directement le driver de « puissance » de chacune des sorties de ce circuit intégré. Et je ne serais pas surpris que toutes ces raies qui fleurissent dans le spectre soient maîtrisables en fonction du courant autorisé sur dans les différents driver de la sortie du CI.

Et miracle après avoir injecté dans l’Arduino MEGA de chez WEMOS (voir ici) qui me sert à piloter le SI5351 j’obtiens un tout autre spectre bien plus propre. Je dispose enfin d’une fréquence à 112.5 MHz dans un environnement « intimiste » c’est à dire sans la présence de d’autres fréquences qui n’y ont rien à faire :

Signal avec registre et charge 50
La version du spectre avec une charge de 50 Ohms sur la sortie du SI5351
Signal avec registre et non chargé
La version du spectre avec la sortie à vide du SI5351

Le code du programme que j’utilise, est donné ci-dessous, à l’origine il n’est pas de moi, j’ai juste apporté les modifications nécessaires à mon besoin. Il repose sur du code disponible sur QRP Labs. J’ai aussi placé des commentaires en français là où il me semble que cela peut aider ceux qui rencontrent des difficultés avec l’anglais.

#include <Wire.h>
void setup() {
Wire.begin(); // Initialise I2C-communication en « master »
// SDA sur pin ADC04
// SCL sur pin ADC05
SetFrequency (112500000); // Réglage de la fréquence de l’horloge CLK0
}

// Création de la fonction qui permet d’écrire dans le registre du Si5351
void Registre (byte reg, byte val){ // Défini l’état « val » du registre « reg » via l’I2C
// L’information qui sera saisie le sera en décimal, donc faire la conversion binaire/décimal pour « val »
Wire.beginTransmission(96); // Débute la transmission avec l’adresse 96 qui correspond à celle du Si5351 (Voir datasheet)
Wire.write(reg); // Defini le numéro du registre
Wire.write(val); // Défini l’état que doit avoir le registre
Wire.endTransmission(); // Clôture la transmission
}
// Activation uniquement de la sortie CLK0
void CLK0_ON () {
Registre (18, 128); // Désactive la sortie de la clock 2
Registre (17, 128); // Désative la sortie de la clock 1
Registre (16, 79); // Active la sortie CLK0, le XTAL est défini comme source, active la PLL A
}

// Génération du signal sur la sortie CLK0
void loop() {
CLK0_ON(); // Sortie Clock0 active
SetPower(1); // Réglage du courant disponible sur le driver de sortie
delay(10000);
}
// Construction du signal d’horloge
void SetFrequency (unsigned long frequency) { // Fréquence en Hz; Comprise entre 7810 Hz et 200 MHz
#define F_XTAL 25000000; // Fréquence de l’oscillateur
#define c 1048574; // « c » part of Feedback-Multiplier from XTAL to PLL
unsigned long fvco; // Fréquence du VCO de la PLL (600-900 MHz)
unsigned long outdivider; // Output divider in range [4,6,8-900], even numbers preferred
byte R = 1; // Additional Output Divider in range [1,2,4,…128]
byte a; // « a » part of Feedback-Multiplier from XTAL to PLL in range [15,90]
unsigned long b; // « b » part of Feedback-Multiplier from XTAL to PLL
float f; // floating variable, needed in calculation
unsigned long MS0_P1; // Si5351a Output Divider register MS0_P1, P2 and P3 are hardcoded below
unsigned long MSNA_P1; // Si5351a Feedback Multisynth register MSNA_P1
unsigned long MSNA_P2; // Si5351a Feedback Multisynth register MSNA_P2
unsigned long MSNA_P3; // Si5351a Feedback Multisynth register MSNA_P3

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
R = R * 2;
outdivider = outdivider / 2;
}
if (outdivider % 2) outdivider–; // finds the even divider which delivers the intended Frequency

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
case 1: R = 0; break; // Bits [6:4] = 000
case 2: R = 16; break; // Bits [6:4] = 001
case 4: R = 32; break; // Bits [6:4] = 010
case 8: R = 48; break; // Bits [6:4] = 011
case 16: R = 64; break; // Bits [6:4] = 100
case 32: R = 80; break; // Bits [6:4] = 101
case 64: R = 96; break; // Bits [6:4] = 110
case 128: R = 112; break; // Bits [6:4] = 111
}

a = fvco / F_XTAL; // Multiplier to get from Quartz-Oscillator Freq. to PLL-Freq.
f = fvco – a * F_XTAL; // Multiplier = a+b/c
f = f * c; // this is just « int » and « float » mathematics
f = f / F_XTAL;
b = f;

MS0_P1 = 128 * outdivider – 512; // Calculation of Output Divider registers MS0_P1 to MS0_P3
// MS0_P2 = 0 and MS0_P3 = 1; these values are hardcoded, see below

f = 128 * b / c; // Calculation of Feedback Multisynth registers MSNA_P1 to MSNA_P3
MSNA_P1 = 128 * a + f – 512;
MSNA_P2 = f;
MSNA_P2 = 128 * b – MSNA_P2 * c;
MSNA_P3 = c;
// Programmation des registres du Si5351
Registre (16, 128); // Désactivation des sorties durant la programmation des resistres
Registre (26, (MSNA_P3 & 65280) >> 8); // Bits [15:8] of MSNA_P3 in register 26
Registre (27, MSNA_P3 & 255); // Bits [7:0] of MSNA_P3 in register 27
Registre (28, (MSNA_P1 & 196608) >> 16); // Bits [17:16] of MSNA_P1 in bits [1:0] of register 28
Registre (29, (MSNA_P1 & 65280) >> 8); // Bits [15:8] of MSNA_P1 in register 29
Registre (30, MSNA_P1 & 255); // Bits [7:0] of MSNA_P1 in register 30
Registre (31, ((MSNA_P3 & 983040) >> 12) | ((MSNA_P2 & 983040) >> 16)); // Parts of MSNA_P3 und MSNA_P1
Registre (32, (MSNA_P2 & 65280) >> 8); // Bits [15:8] of MSNA_P2 in register 32
Registre (33, MSNA_P2 & 255); // Bits [7:0] of MSNA_P2 in register 33
Registre (42, 0); // Bits [15:8] of MS0_P3 (always 0) in register 42
Registre (43, 1); // Bits [7:0] of MS0_P3 (always 1) in register 43
Registre (44, ((MS0_P1 & 196608) >> 16) | R); // Bits [17:16] of MS0_P1 in bits [1:0] and R in [7:4]
Registre (45, (MS0_P1 & 65280) >> 8); // Bits [15:8] of MS0_P1 in register 45
Registre (46, MS0_P1 & 255); // Bits [7:0] of MS0_P1 in register 46
Registre (47, 0); // Bits [19:16] of MS0_P2 and MS0_P3 are always 0
Registre (48, 0); // Bits [15:8] of MS0_P2 are always 0
Registre (49, 0); // Bits [7:0] of MS0_P2 are always 0
if (outdivider == 4){
Registre (44, 12 | R); // Special settings for R = 4 (see datasheet)
Registre (45, 0); // Bits [15:8] of MS0_P1 must be 0
Registre (46, 0); // Bits [7:0] of MS0_P1 must be 0
}
Registre (177, 32); // This resets PLL A
}

// Réglage courant de sortie, voir page 19 de l’AN619 de chez Silicon Labs
void SetPower (byte power){
if (power == 0 || power > 4){power = 0;}
switch (power){
case 1:
Registre (16, 76); // CLK0  Contrôle du courant de sortie -> 2mA
break;
case 2:
Registre (16, 77); // CLK0  Contrôle du courant de sortie -> 4mA
break;
case 3:
Registre (16, 78); // CLK0  Contrôle du courant de sortie -> 6mA
break;
case 4:
Registre (16, 79); // CLK0  Contrôle du courant de sortie -> 8mA
break;
}
}

Voici donc où modifier dans le programme ce courant de sortie disponible pour piloter le SI5351. Il suffit d’attribuer une valeur 1, 2, 3, ou 4 au paramètre SetPower(x). Et tout naturellement vous pourrez maîtriser la pureté du signal de sortie.

Exemple ici pour la sortie d’horloge 0

2020-01-26_205649

Nous venons de le voir ce synthétiseur de fréquences le SI5351 est finalement loin d’être inintéressant. Il nécessite de lui consacrer un peu de temps pour en tirer tout son bénéfice. Donc surtout de pas tirer trop hâtivement une conclusion sur ses possibilités.

Je vais poursuivre mes activités autour de ce circuit, il n’est pas impossible que par la suite je vous fasse part d’autres constats à son sujet. Je vous invite à approfondir la lecture de la notice d’application AN619 qui est en quelque sorte la mine d’or de ce circuit intégré. Le site QRPLabs est aussi très riche à son sujet.

Câblage entre les cartes et le matériel de mesures:

Drawing2

Côté accessoires et matériel, voici quelques compléments d’informations:

  • La carte d’évaluation SI5351 est la suivante
  • La plaque sur laquelle est fixé la breadboard est disponible ici par exemple. Elle me permet de laisser à poste la carte MEGA et Raspberry 3. Elle est aussi prévue pour y fixer à la place de la MEGA une UNO.
  • Le splitter que j’utilise est le suivant
  • L’atténuateur qui couvre les valeurs 30, 20 et 10 dB est le suivant
  • L’analyseur scalaire D6 (regarder ici à son sujet) est disponible ici
  • Les câbles SMA courts et longs sont disponibles ici
  • La charge fictive est celle-ci
  • J’utilise aussi différents adapteurs SMA comme ceux-ci
  • Les connecteurs SMA à souder sur la carte d’évaluation SI5351 sont les suivants
  • La carte MEGA WEMOS est la suivante

3 réflexions sur “Si5351 : Ne pas tirer de conclusion trop hâtive

  1. Bonjour,
    super travail d’étude et de rédaction.
    Je n’hésite plus pour opter pour ce produit, grâce aux petits oignons ;o)
    Encore merci pour ce partage.
    Paul F5HPQ

Votre commentaire

Choisissez une méthode de connexion pour poster votre commentaire:

Logo WordPress.com

Vous commentez à l’aide de votre compte WordPress.com. Déconnexion /  Changer )

Photo Google

Vous commentez à l’aide de votre compte Google. Déconnexion /  Changer )

Image Twitter

Vous commentez à l’aide de votre compte Twitter. Déconnexion /  Changer )

Photo Facebook

Vous commentez à l’aide de votre compte Facebook. Déconnexion /  Changer )

Connexion à %s