Le groupe DDS
Introduction
Le but de ce wiki est de donner les outils de bases pour démarrer un projet autour d'un DDS, de la programmation à l'implémentation sur circuits imprimés : réalisation de cartes "propriétaires" ou utilisation de kits de développement commerciaux.
Vous pouvez aussi participer à l'enrichissement de cette page avec vos sources ou partager vos projets.Contacter l'animateur du Groupe DDS par mail Fabrice.wiotte@univ-paris13.fr LPL Université Paris 13
http://jmfriedt.free.fr/network_analyzer.pdf : travaux pratiques de Master1 EEA Besançon pour réaliser un petit analyseur de réseau à base d'AD9834 (faible consommation, MCK=75 MHz) commandé par STM32F410.
Généralités sur les DDS
Les "Direct Digital Synthesizers" (DDS) sont des synthétiseurs qui peuvent générer des formes d'ondes arbitraires à diverses fréquences à partir d'une fréquence de référence fixe.
Un synthétiseur de fréquence est par extension un instrument qui permet de générer, dans une gamme de fréquences donnée, un signal dont on peut ajuster la fréquence et l’amplitude et auquel il peut être imposé une modulation de fréquence, de phase ou d’amplitude.
Une bonne note Analog device expliquant le fonctionnement des DDS se trouve ici : Média:Tuto_dds.pdf
La fréquence de sortie du DDS est exprimée par l'Équation ci dessous
1. fout : est la fréquence de sortie DDS
2. M : valeur du mot d'accord -> attention exprimé en Hexadécimal
3. fc : fréquence d'horloge système
4. N : la longueur de l'accumulateur de phase
Conception avec des circuits intégrés DDS commerciaux
Plusieurs aspects doivent être pris en compte lors de la sélection et de l'utilisation d'un DDS: la plage de fréquences requise, la plage d'amplitudes et de décalages, la forme d'onde, la résolution, la capacité de modulation.
La pureté du signal constitue généralement un facteur de sélection d’une source de signaux.
Pourquoi les DDS ?
Depuis quelques années pour les équipes de recherches du Laboratoire de Physique des Lasers (LPL), nous utilisons la technologie DDS pour développer des générateurs radiofréquences de quelques MHz à plusieurs centaines de MHz nécessaires au fonctionnement des expériences, ainsi qu'à l'étude et au développement des Condensats d'atomes froids (BEC). Cette technologie au travers de composants spécifiques, nous permet de réaliser des cartes électroniques adaptées aux expériences du laboratoire. Ces dernières sont entièrement pilotable numériquement, on peut ainsi programmer les paramètres principaux tel que la fréquence, la phase et l’amplitude. Les caractéristiques de ces composants font qu’ils disposent d'une grande pureté spectrale, d’une grande stabilité, d’un faible bruit de phase et d’une grande agilité en fréquence sans saut de phase. Les applications: Générateurs de fonctions, oscillateur local, PLL, driver AOM...
Ci-dessous schéma fonctionnel de l'AD9852
- 1.1 Description des principales fonctions d'entrées et de sorties.
REFERENCE CLOCK IN si l'horloge externe = 20MHz PLL activée x 15 = 300MHz (fréquence du system clock) ou si PLL off horloge externe max =300MHz. MASTER RESET bit actif sur front logic 1 initialise le DDS et met la sortie RF à zéro. ANALOG OUT est la sortie RF principale 0dBm en général. I/O UPDATE CLOCK est le bit de chargement des données dans le DDS (par défaut généré en interne et synchronisé sur system clock. FSK/BPSK/HOLD bit actif sur front logic 1 lance les rampes de fréquences en autres. OSK bit actif sur front logic 1 lance les rampes d'amplitudes. 8-BIT PARALLEL LOAD bus 8bits pour chargement des données actif si mode parallèle sélectionné. 6-BIT ADDRESS OR SERIAL PROGRAMMING bus 6bits pour chargement des adresses en mode parallèle sinon utiliser seulement bit A0 pour le mode SPI. SERIAL/PARALLEL SELECT bit de sélection des modes de programmation du DDS: = 1 si chargement parallèle, 0 si chargement série(pin 70 du DDS). DIFF/SINGLE SELECT bit de sélection single ended or differential clock input. pin 64 du DDS. WRITE OR WR/SCLK si mode Parallèle => bit de chargement I/O port buffers, actif sur front descendant ou SCLK en mode SPI.
Visualisation d'une sortie d'un DDS (AD9852)
Ci-dessus visualisation du changement de la fréquence de sortie d'un DDS sans saut de phase. Mode de programmation parallèle: en bas de l'écran bus de données(B1) et bus d'adresses(B2). Attention dans cet exemple je ne programme que l'octet de poids fort pour la fréquence et l'amplitude. En jaune signal d'actualisation des données et adresses, en rouge sortie RF sur 50ohms. En vert signal WR/SCLK bit de chargement dans I/O port buffers actif sur front descendant et durée minimale programmable = 50ns. En bleu I/O UPDATE données transmises au DDS actif sur front montant et durée minimale programmable = 50ns. Les courbes en vert et bleu sont volontairement décalées suivant la procédure de chargement des données fournie dans le datasheet du DDS(page 18 du datasheet AD9852).le mot de fréquence pour ce DDS est codé sur 48 bits et donc 6 Octets avec pour parallel address: 0x04;0x05;0x06;0x07;0x08;0x09 (0x04 Octet de poids fort)ou serial address= 0x02 en mode SPI. le mot d'amplitude pour ce DDS est codé sur 12 bits et donc 2 Octets avec pour parallel address:0x21;0x22;(0x21 Octet de poids fort) ou serial address= 0x07 en mode SPI.
Comment programmer un DDS Une des pages importantes dans un datasheet de DDS est la page register layout table. celle-ci définie tous les registres à utiliser pour programmer l'ensemble des fonctions de bases.
En rouge le mot de fréquence f1 programmable 48 bits soit sur 6 Octets. En bleu le mot d'amplitude programmable sur 12 bits soit sur 2 Octets. Ce sont les deux paramètres à programmer à minima pour générer un signal RF en sortie.
un DDS utilisé au LPL : l'AD9959
Comment programmer le DDS :La programmation sur ce DDS est uniquement en mode SPI Single-bit serial 2-wire mode (default mode) Single-bit serial 3-wire mode 2-bit serial mode 4-bit serial mode (SYNC_I/O not available)
Côté MSP430F169 : Les sorties SIMO1 P5.1, UCLK1 P5.3 et ACLK P5.6 sont utilisées pour programmer en mode SPI 2 fils (mode par défaut du DDS),Côté DDS AD9959: SCLK, SDIO_0 et CS/ sont à connecter au microcontrôleur. ci-dessous le mode par défaut.SDIO_1,2 et 3 sont connectés au microcontrôleur pour réaliser si on le souhaite, des profiles de rampes de fréquences ou de phases.
SCLK = serial clock pin 48 du DDS CS/ = Chip select pin 47 du DDS SDIO_0 = Serial data I/O pin 50 du DDS
Quel microcontrôleur pour piloter les DDS ?
Sur le schéma plus haut, le DDS a été programmé par l'intermédiaire d'un microcontrôleur 16 bits de chez TI, le MSP430F169 @8MHz d'horloge.
l'environnement de programmation du MSP430 est IAR Embedded Workbench téléchargeable gratuitement dans sa version de base avec un code limité @8Ko
Aujourd'hui je conseil d'utiliser un CPU ARM pour tous les développement uC (STM32, ARDUINO, TI TIVA séries...).
Un développement récent avec l'AD9959 à été réalisé avec un microcontrôleur ATMEL ARDUINO DUE, microcontrôleur 32 bits ARM @84MHz et un STM32F437 ARM @180MHz.
Les dernières cartes développées au LPL utilisent principalement des microcontrôleurs TEXAS INSTRUMENT TM4C123GH6PM ARM@80MHz Cortex®-M4F et TM4C1294 ARM@120MHz
Ci dessous Les différents registres du DDS l'AD9959 table 28 du datasheet de l'AD9959
registre CSR (channel select register) One byte is assigned to this register: le nombre d'octets du registre ici 1 octet. CSR serial address = 0x00; CSR defaut value = 0xF0;
Ce registre active les voies de sorties et les modes SPI: Par défaut toutes les voies sont activées et le mode SPI Single-bit serial 2-wire est sélectionné. Il est évidemment possible de redéfinir ce registre suivant son application.
Le second registre est le registre FR1: table 28 du datasheet registre FR1 (fonction register 1) three bytes is assigned to this register: nombre d'octets du registre FR1 serial address = 0x01; FR1 defaut value = 0x00;
Ce registre permet en autres de définir la PLL interne et le coefficient multiplicateur x4 à x20. Pour exemple la valeur à fournir pour activer la PLL x20 ⇒ FR1 = 0xD00000; Dans ce cas il suffit de fournir un quartz à 25MHz avec la PLL activée x20 on a 500MHz d'horloge PIN 22 et 23 du DDS.
Le troisième registre est le registre CFR table 29 du datasheet registre CFR (Channel Function Register) three bytes is assigned to this register: nombre d'octets du registre CFR serial address = 0x03; CFR defaut value =0x302;
Ce registre défini les différents mode de fonctionnement du DDS.Ce registre est important si vous utiliser certains modes de fonctionnement: balayage de fréquence, de phase, ou d'amplitude. Important par défaut les sortie sont en mode DAC full-scale current.
Le quatrième registre est le registre CFTW0: table 29 du datasheet registre CFTW0 (Channel Frequency Tuning Word 01) four bytes is assigned to this register: nombre d'octets du registre CFTW0 serial address = 0x04; CFTW0 defaut value =0x00;
Ce registre permet de rentrer la fréquence désirée suivant la relation ci-dessous:
FTW0 = frequency output x 2^32 /frequency clock en Hexadecimal
Le cinquième registre est le registre CPOW0 table 29 du datasheet registre CPOW0 (Channel Phase Offset Word 01) two bytes is assigned to this register: nombre d'octets du registre CPOW0 serial address = 0x05; CPOW0 defaut value =0x00;
Ce registre définie la phase du signal de sortie codé sur 14 bits avec la relation ci-dessous:
CPOW0 = Delta phi x 2^14 /360°
Le sixième registre est le registre ACR: table 29 du datasheet registre ACR (Amplitude Control Register) two bytes is assigned to this register: nombre d'octets du registre ACR serial address = 0x06; ACR defaut value =0x00;
Ce registre permet de définir l'amplitude. Par défaut l'amplitude est en mode full scale mais programmable si on modifie le registre CFR.
Les autres registres sont utiles pour programmer le DDS pour des balayages de fréquences, de phases et d'amplitudes en autres.
Registre FR2 (Function Register 2) Registre LSRR (Linear Sweep Ramp Rate1) Registre FDW (LSR Falling delta Word1) Registre RDW (LSR Risingdelta Word1) Registre CW1 (Channel Word 1) ...
Programme en C écrit dans un microcontrôleur, le MSP430F169 pour contrôler une DDS l'AD9959
initialisation et chargement des registres CSR et CFTW0:
int CSR_ADDRESS = 0x00; AD9959 CSR adresss Byte
int CSR_NUM_BYTE = 0x01; CSR nombre d'octet du registre
long CSR0 = 0x10; AD9959 du channel 0 MSB first SPI par défaut
int FTW_ADDRESS = 0x04; AD9959 FTW adresss Byte
int FTW_NUM_BYTE = 0x04; FTW nombre d'octet du registre
long FTW0 = 0x28F5C28F; frequence en hex = fout x2^32/fclock
dans le main
P4OUT = 0x40; AD9959 master reset bit de validation du MSP430
P4OUT = 0x00; AD9959 master set bit de validation du MSP430
write_serial_port(CSR_ADDRESS, CSR0, CSR_NUM_BYTE);
P5OUT = 0x40; I/O update du DDS bit de validation du MSP430
P5OUT = 0x00; I/O update du DDS bit de validation du MSP430
write_serial_port(FTW_ADDRESS, FTW0, FTW_NUM_BYTE);
P5OUT = 0x40; I/O update du DDS bit de validation du MSP430
P5OUT = 0x00; I/O update du DDS bit de validation du MSP430
Commentaires sur le programme: on fait un RESET du DDS (pin 3), on charge les données de chaque registre au travers du port SPI write_serial_port… Puis on réalise un I/O UPDATE pin 46 du DDS pour la validation et le transfert des données. Ce bout de programme permet de charger le channel 0 avec une fréquence de 80MHz et une amplitude par défaut FULL DAC. I/O_UPDATE is synchronous to the SYNC_CLK (Pin 54) = Master clock/4. Voir figure 40 du datasheet du DDS. Ci-dessous le sous programme d'initialisation des ports du microcontrôleur et du SPI pour le MSP430F169 : TI fourni de nombreux exemples de codes de bases pour configurer les modes SPI, I2C et utiliser la mémoire Flash: slac015p.zip
#include <msp430x16x.h>
void DDS_quartz_oscillator_init(void)
{
BCSCTL1 |= XTS; ACLK= LFXT1= HF XTAL
BCSCTL2 |= SELM_3; MCLK = LFXT1 (safe) pin 8,9 du MSP430
P1SEL = 0x00; P1 I/O select
P2SEL = 0x00; P2 I/O select
P3SEL = 0x00; P3 I/O select
P4SEL = 0x00; P4 I/O select
P5SEL = 0x0A; P5.1,3 SPI option select
P6SEL = 0x00; P6 I/O select
P1DIR = 0xFF; P1.output direction
P2DIR = 0xFF; P2 output direction
P3DIR = 0xFF; P3 output direction
P4DIR = 0xFF; P4 output direction
P5DIR = 0xFF; P5 output direction
P6DIR = 0xFF; P6 output direction
ME2 |= USPIE1; Enable USART1 SPI
UCTL1 |= CHAR + SYNC + MM; 8-bit SPI Master **SWRST**
UTCTL1 = CKPH + SSEL1 + STC; SMCLK delayed, 3-pin
UBR01 = 0x2; ACLK/2 for baud rate
UBR11 = 0x0; ACLK/2 for baud rate
UMCTL1 = 0x0; Clear modulation
UCTL1 &= ~SWRST; Initialize USART state machine
}
BCSCTL1 |= XTS; et BCSCTL2 |= SELM_3; permet d'être en mode HF XTAL le MSP430 fonctionnera à 8MHZ au lieu de 32KHz par défaut.
MSP430F169 ----------------- /|\| XIN|- | | | HF XTAL (455k - 8Mhz) --|RST XOUT|- | | | P5.4|-->MCLK = XTAL
D'après : M. Buccini Texas Instruments Inc. Feb 2005 Built with CCE Version: 3.2.0 and IAR Embedded Workbench Version: 3.21A
le sous programme pour le chargement des données en mode SPI du MSP430F169
void write_serial_port(int instruction, long data, int num_byte)
{
int i=0;
TXBUF1 = instruction;
do
{
TXBUF1 = data >>(num_byte-1-i)*8;
i++;
}
while (i < num_byte);
}
Un code complet pour charger le DDS avec le MSP430F169
#include <msp430x16x.h>
#include "DDS_quartz_oscillator.h"
void init_sys(void); MSP430 Initialisation routine
void tempo_loop(int loop_number); wait loop
void write_serial_port1(int instruction, long data, int num_byte);
/ main() variable declarations /
/ configuration Channel Select Register /
Channel Select Register
int CSR_ADRESS = 0x00; AD9959 CSR adresss Byte
long CSR = 0x10; AD9959 CH0 only MSB first
int CSR_NUM_BYTE = 0x01; AD9959 byte number by CSR
int FTW0_ADRESS = 0x04; AD9959 FTW0 adresss Byte
long FTW0 = 0x38C9138C; AD9959 Frequency Tuning Word0 122MHz
int FTW_NUM_BYTE = 0x04; AD9959 byte number by FTW
void main(void)
{
/ initialisation du msp430 /
init_sys(); Initialise the MSP430
tempo_loop(10000); wait loop
P5OUT = 0x00;
P4OUT = 0x40; Reset AD9959
tempo_loop(10000); wait loop
P4OUT = 0x00; Set AD9959
write_serial_port1(CSR_ADRESS, CSR, CSR_NUM_BYTE);
tempo_loop(100); wait loop
P5OUT = 0x40; AD9959 I/O update
P5OUT = 0x00;
write_serial_port1(FTW0_ADRESS, FTW0, FTW_NUM_BYTE);
tempo_loop(10); wait loop
P5OUT = 0x40; AD9959 I/O update
P5OUT = 0x00;
}
void init_sys(void)
{
WDTCTL = WDTPW + WDTHOLD; // stop Watch Dog Timer
DDS_quartz_oscillator_init(); // init usart1, spi mode, 2wire
}
void write_serial_port1(int instruction, long data, int num_byte)
{
int i=0;
TXBUF1 = instruction;
do
{
TXBUF1 = data >>(num_byte-1-i)*8;
i++;
}while (i < num_byte);
}
void tempo_loop(int loop_number)
{
int i;
int j;
for(i = 0; i < loop_number; ++i) wait loop
{
j=j+i;
}
}
Différentes cartes de développement : MSP430 - ARM TI - STM32 - Arduino
Environnement de programmation : IAR for MSP430 & ARM, code composer studio for MSP430 & ARM, IDE cube for STM32...
Code Composer Studio for ARM or MSP
Conception CAO électronique -> Tuto prise en main d'Altium Designer 20: support TP Ingénieur Instrumentation Galilée USPN
Les kits de développement c'est bien ! mais des cartes maisons c'est pas mal aussi !
Pour ceux qui veulent se lancer dans la CAO. Un tutoriel simple et une prise en main rapide du logiciel Altium designer 20
Fichier:CAO Electronique Fabrice Wiotte 2020.pdf
Conception CAO électronique avec projet moteur pas à pas sous Xilinx ISE et communication Python: Support TP ingénieurs instrumentation
Un tutoriel ISE XILINX pilotage d'un moteur pas à pas avec conception de cartes filles autour d'une carte Digilent Nexys 4 et Nexys A7 avec Artix7.
Fichier:TP 2021 FPGA2 moteur pas à pas Ingénieurs Instrumentation Galilée.pdf
Mise à jour des TP et correctifs: Fichier:TP 2022 Ingénieurs Instrumentation 2 Galilée mise a jour du 04 02 2022.pdf
Conception CAO électronique communication Python sur Raspberry pi 4 et programmation FPGA: J'ai adapté le TP FPGA 2 ci-dessus pour que le puisse piloter à distance sur le réseau le moteur pas à pas. Dans notre TP nous pouvions piloter le moteur grâce à une liaison USB-Série avec un PC à proximité. Pour un pilotage réseau j'ai donc connecté ma carte FPGA avec une Raspberry PI 4 et j'ai pu donc contrôler le moteur à distance via une liaison SSH. Le mieux est évidemment je pense de travailler en ligne de commande avec le terminal LX de la Raspberry Pi et il a de nombreux tuto pour installer et utiliser la Raspberry Pi.
Mise à jour du TP sous Vivado 2021.2 : environnement Vivado
TP VIVADO 2020 CmodA7 board digital clock
Ci-joint le lien pour le projet: https://github.com/fabzz60/Cmod-A7-Horloge-Demo-
TP réalisation de carte électronique, réalisation avec Altium Designer AD21: carte Spartan 6 LX4
Raspberry pi et cartes maisons connectées à la pi 4 projets 2021
Utilisation d'une Raspberry pi 4 pour contrôler les cartes maisons et des cartes DDS Procédure de communication avec une pi 4: Fichier:SSH Raspberry Pi.pdf Communication avec des cartes maisons et une liaison USB-série avec la pi 4 J'ai du tout de même installé ce paquet pylibftdi sous Raspbian qui est une interface Pythonic minimale pour les périphériques FTDI utilisant libftdi car je souhaite connecter plusieurs appareils disposant d'une puce FTDI serial-UART.
J'ai deux cartes électroniques connectées à ma Raspberry Pi 4:
--Une carte FPGA Artix 7 qui pilote le moteur pas à pas et communique via une puce FTDI double pont FT2232HQ pour l'UART et le JTAG.
--Une carte uC ARM TI puce TM4C1294 pour un projet générateur multi-voies à base de DDS (voir ce Wiki DDS), carte développée avec Altium au LPL qui est connectée avec une liaison USB-série, UART puce FTDI FT232.
J'ai donc un programme Python pour la carte DDS multivoie et un programme Python pour le moteur pas à pas que l'on a étudié. Sur ma Raspberry Pi 4 les programme Python sont modifiable à distance sous le terminal grâce à l'outil intégré à Raspbian nano -> éditeur de texte qui me permet de modifier et d'enregistrer mon code Python et de lancer les programmes.
Normalement je peux également charger la puce FPGA (bit file) avec la Raspberry Pi grâce à l'outil développé par Digilent (Adept2) qui est l'équivalent d'Impact sous ISE mais en version linux 32 bits pour Raspberry. La suite pour moi c'est d'utiliser les GPIO de la Raspberry Pi 4 notamment les ports SPI, I2C et Uart pour des projets d'électroniques embarqués...et d'intégrer des cartes filles maisons sur la Raspberry Pi.
Projet DDS's Strontium 2 Laser Superradiant 2022
Pour une nouvelle expérience du laboratoire utilisant de nombreux DDS synchronisés ou pas sur un signal d'horloge externe:
Rack multivoies DDS AD9852 & AD9858 : programmation uC ARM TM4C1294 and server TCP/IP Rack à droite de l'image:
Raspberry Pi 4 sur bus SPI DDS à gauche de l'image ci-dessous:
Carte DDS sur uC TI ARM TM4C1294 et serveur TCP-IP pour microcontrôleur développé par Texas Instruments.
Ci-dessous script Python pour la Raspberry Pi4 qui pilote le rack DDS: Script pour la liaison USB-serial (UART0 de la pi4)
Fichier:Code python liaison série UART0 pi4 .pdf
Ci-dessous script dans la Raspberry pi 4 : activation des broches GPIO, SPI, UART0 de la pi 4 qui contrôle les DDS
Fichier:Code Raspberry pi 4.pdf
Ci-dessous les cartes développées pour le projet Laser super radiant (Strontium 2) carte Format Europe 4 couches FR4 35um
Raspberry Pi4 sur carte Europe et fond de panier
Carte DDS AD9852 ou AD9858 sur fond de panier
Carte uC ARM TM4C1294, USB-sérial et Ethernet TCP-IP
General Note on the DDS card and on the BUS driver 2014 & update 2022
Présentation de l'architecture BUS DDS, communication parallèle pour le pilotage de 24 DDS sous Labview Fichier:NoteBusDDS LPL Strontium.pdf