• Aucun résultat trouvé

Maquette de traitement

N/A
N/A
Protected

Academic year: 2022

Partager "Maquette de traitement "

Copied!
20
0
0

Texte intégral

(1)

TP DSP

Maquette de traitement

La maquette utilisée dans le cadre de ces TP de traitement numérique du signal est constituée d’une carte Raspberry Pi avec la distribution Linux Raspbian et d’une carte fille "maison" offrant :

- 2 voies d’entrée analogiques numérisées utilisant des Convertisseurs Analogique-Numérique (CAN) 12 bits.

- 2 voies de sortie analogiques utilisant des Convertisseurs Numérique-Analogique (CNA) 8 bits.

Les plages des tensions d’entrée et de sortie sont d’environ [-1V ; +1V].

La fréquence d’échantillonnage est de 100kHz.

Les voies d’entrée et de sortie sont équipées respectivement de filtres anti-repliement et de reconstruction.

Ces filtres sont réalisés :

- pour une partie en numérique dans un FPGA à une fréquence d’échantillonnage de 1MHz et avec une fréquence de coupure d’environ 50KHz

- pour une partie par des filtres analogiques grossiers (du 2nd ordre) de fréquence de coupure d’environ 500kHz.

Au niveau des convertisseurs CAN et CNA, la fréquence d’échantillonnage est donc en réalité de 1MHz. Et ce n’est qu’après l’application des filtres anti-repliement en entrée que celle-ci est abaissée à 100kHz (sous- échantillonnage d’un facteur 10). En sortie, de manière réciproque, le rythme échantillon de 100kHz est accru d’un facteur 10 avant application des filtres de reconstruction numériques fonctionnant à 1Mhz.

L’ensemble Raspberry + carte d’entrée-sortie ambitionne d’offrir une plate-forme de traitement numérique du signal au même titre qu’une carte équipée d’interfaces Analogiques et d’un DSP (Digital Signal

Processor) ; c’est-à-dire un processeur spécialement conçu pour le traitement du signal. Citons les processeurs de la famille TMS320 de Texas Instrument ou ceux de la famille ADSP d’Analog Devices.

La caractéristique essentielle d’un DSP est la capacité à effectuer des traitement temps réel ; par exemple le calcul et la fourniture d’échantillons à une cadence bien déterminée (fréquence d’échantillonnage).

Pour parvenir à cela, les DSP utilisent des systèmes d’exploitation muni d’un noyau temps réel. A moins que ce soit le programme de traitement du signal qui gère entièrement le processeur.

Les DSPs ont aussi une architecture spécialement conçue pour le traitement du signal : plusieurs BUS de données, Arithmetic and Logic Unit (ALU) optimisée pour des opérations de multiplication-accumulations et pour des opérations sur les nombres complexes, des modes d’adressage particuliers (FFT), etc. Mais cette spécificité n’est pas déterminante. Les processeurs à usage général dont le marché est beaucoup plus important proposent en fait à prix égal une puissance de calcul souvent plus importante.

Le problème avec les processeurs à usage général réside dans les systèmes d’exploitation disponibles (Windows, Linux, etc.) qui ne sont généralement pas temps réel car les contraintes temps réel dégradent les performances dans le cas des tâches générales (non temps réel).

Dans le cas qui nous occupe - la mise en œuvre de techniques de traitement du signal numérique en temps réel – nous souhaitions si possible profiter et mettre en avant la solution populaire "Raspberry Pi – Linux"

plutôt que d’utiliser une solution propriétaire DSP ou µP+noyau temps réel.

Nous avons envisagé d’employer des noyaux temps réel Linux (Linux-rt et/ou Xenomai), mais nous sommes arrivés à la conclusion que cette solution ne permettrait pas d’atteindre des fréquences d’échantillonnage supérieures à quelques kHz.

Finalement, nous avons résolu le problème en interfaçant le mode temps réel des signaux numériques des convertisseurs Analogique-Numérique et Numérique-Analogique à celui non-temps réel du Raspberry Pi grâce à des buffers (FIFO) suffisamment longs.

Raspberry Pi

FPGA FIFO

FIFO CAN

CNA ( )

( )

(2)

Le principal inconvénient de cette solution est le retard important entre les signaux de sortie et les signaux d’entrée du fait des buffers. Et malheureusement, il faut des buffers de grandes longueurs pour amortir l’exécution "erratique" du traitement du signal au sein du Raspberry PI et fournir une alimentation correcte des convertisseurs. Ici, les buffers font plusieurs milliers d’échantillons – soit un retard de plusieurs dizaines de millisecondes.

L’avantage tient à l’emploi de l’environnement riche existant pour le Rasberry Pi : Linux et toutes ses

applications et en particulier dans le cadre qui nous occupe : SSH, VNC, CodeBlocks, Octave, Samba, FTP, etc …

Démarage

- Démarrer le PC et se connecter en tant que "dsp" (mode de passe "dsp").

- Relier la maquette au PC via le câble Ethernet RJ45.

- Brancher l’alimentation de la maquette.

- Lancer le logiciel "VNC Viewer" sur le PC et établir la connexion avec l’adresse IP 192.168.137.2 en tant que "dsp" (mode de passe "dsp") si demandé.

- L’invite de logging du Raspberry doit apparaître. Se connecter en tant que "dsp" (mode de passe

"dsp").

- Une invite de réinstallation du TP doit apparaître. Répondre affirmativement seulement si c’est la première connexion. Attention, les éventuels travaux antérieurs seront effacés.

- Le bureau Linux Raspbian du Raspberry apparaît ensuite dans la fenêtre "VNC Viewer". La suite du travail se passe ici.

Projet CodeBlocks

Le traitement numérique des signaux est réalisé dans le Raspberry par un programme écrit en C et/ou C++

exploitant au mieux les 4 cœurs du processeur. Un projet initial sous CodeBlocks est fourni sous forme d’un

"template". Pour créer un projet basé sur ce template : - Lancer Codeblocks (icone sur le bureau)

- Sélectionner menu "File" - "New» - «From template…"

- Sélectionner le template "pass"

- Une fenêtre de sélection de répertoire apparaît. Sélectionner le répertoire "dsp" puis demander la création d’un sous-répertoire pour le nouveau projet (choisir un nom en rapport) puis choisir "open "

- Codeblocks propose ensuite de nommer le projet. Par défaut, il propose le nom du template. Choisir plutôt le nom du répertoire choisi précédemment pour le projet.

La fenêtre de Codeblocks apparaît avec le nouveau projet ouvert.

(3)

Le projet initial est composé de 4 fichiers C ou C++ :

- Le fichier "main.cc " est le programme principal. La fonction main() réalise l’initialisation des entrées- sorties et initialise les différentes threads destinées à exploiter les différents cœurs du processeur.

Pour information :

o La thread "thread_io" avec la fonction f_io() assure le transfert des échantillons avec les FPGAs en charge des convertisseurs. Elle s’exécute dans le cœur 3.

o La thread "thread_process" avec la fonction f_process() réalise le traitement du signal ; c’est-à-dire le calcul des échantillons de sortie à partir (éventuellement) des échantillons d’entrée. Elle s’exécute dans le cœur 4.

o Enfin, une thread "thread_print" s’exécutant dans le cœur 2 réalise les taches d’affichage dans la fenêtre d’exécution.

o Le cœur 1 n’est pas utilisé par le programme mais il est utilisé par le système d’exploitation.

- Le fichier "fpga.c" contient les fonctions de bas niveau de communication avec le FPGA.

- Le fichier "log_printf.cc" contient les fonctions d’affichage de la thread "thread_print".

- Enfin, le fichier nommé ici "process.cc" - présenté dans la fenêtre CodeBlocks ci-dessus - contient les fonctions réalisant le traitement des échantillons. C’est ce seul fichier qui devra être modifié (et éventuellement renommé) pour mettre en œuvre les différents traitements abordés au cours des TPs.

- Et d’un fichier header "dspio.h" qui devra être inclus dans tous les fichiers sources mettant en œuvre les traitements et qui contient les prototypes des différentes fonctions utilisables dans le cadre des TPs :

void Init();

void Process(float io[2]);

int AdcFilter(int etat);

int DacFilter(int etat);

int log_printf(const char *format, ...);

int log_printl(const char *format, ...);

Les fonctions Init() et Process() sont les plus importantes.

La fonction Init() est appelée une seule fois au démarrage du programme. Elle est destinée à réaliser comme son nom l’indique des tâches d’initialisation ; par exemple la mise à zéro de tableaux globaux destinés à mémoriser les futurs échantillons de signal où l’initialisation de filtres à partir de fichiers crées avec Matlab (ou Octave).

La fonction Process() est appelée à chaque nouvel instant d’échantillonnage. Elle reçoit via le tableau

"float io[2]» les échantillons provenant des 2 voies d’entrée. Elle calcule les valeurs des échantillons destinés aux 2 voies de sortie et les place dans le tabeau io[2] (à la place des échantillons d’entrée) avant de terminer. Dans le fichier "process.cc" présenté dans la fenêtre CodeBlocks ci-dessus, les valeurs des échantillons d’entrée ne sont pas remplacées et c’est donc ces valeurs qui seront envoyées aux voies de sortie (d’où le nom du fichier).

Les 2 fonctions suivantes AdcFilter() et DacFilter() permettent d’activer ou de désactiver les filtres numériques respectivement d'anti-repliement et de reconstruction mise en œuvre dans le FPGA. Par défaut, les filtres sont activés.

Enfin, les fonctions log_printf() et log_printl() permettent de réaliser des affichages sans risque de ralentir le traitement temps réel des échantillons car elles s’exécutent dans une thread indépendante. Il est à noter qu’en cas de surcharge, certains affichages peuvent être omis. Quand c’est le cas, une séquence de 3 points : "…" est affichée pour l’indiquer.

Ces deux fonctions fonctionnent comme la fonction printf() du C. Cependant, la fonction log_printl()fait en sorte d’afficher le message sur une ligne numérotée (utile pour repérer des affichages manquants).

Compilation, exécution et débogage

Sélectionner le mode "Debug" ou "Release" (choisir le mode "Debug" dans un premier temps) puis utiliser la commande "Build" pour construire l’exécutable.

(4)

Comme indiqué ci-dessus, la construction ne doit faire apparaître aucune erreur ni warning.

Lancer l’exécution (commande "Run").

La fenêtre d’exécution apparaît avec le message "Init OK" ; signe que l’exécution du programme est correcte (si un message d’erreur apparaissait comme «FPGA not responding», arrêter puis relancer l’exécution) :

Le programme fonctionne. S’agissant du projet initial, les signaux d’entrée transitent par le Raspberry sans être modifiés. Les signaux de sortie doivent donc être identiques aux signaux d’entrée (au bruit de

quantification près et à condition qu’ils soient dans la bande passante du système).

Vérifier le bon fonctionnement du programme en appliquant par exemple un signal sinusoïdal de 10kHz d’amplitude 0.5V en entrée et en vérifiant au scope que le signal apparaît bien en sortie.

Aucun traitement n’étant réalisé, la charge du thread de traitement (indiquée dans la barre de titre de la fenêtre d’exécution) n’est que de 0.5%.

Pour les futurs traitements, il faudra veiller à ce que la charge n’atteigne pas 100%. Si c’était le cas, penser à passer en mode "Release" pour profiter d’un code plus optimisé et diminuer la charge.

Modification, débogage et version release

Pour illustrer l’affichage dans la fenêtre d’exécution, imaginons que nous voulions estimer et afficher la puissance du signal numérique de la voie 0 ; c’est-à-dire la moyenne estimée du signal mis au carré :

1 ( )

et également transmettre le signal de la voie d’entrée 0 sur la voie de sortie 1.

Nous allons modifier la fonction Process() de la manière suivante :

(5)

static float Px=0;

static int cnt=0;

Px+=io[0]*io[0];

cnt=(cnt+1)%N;

if(cnt==0) { Px/=N;

log_printf("Px = %f Veff = %f\n",Px,sqrt(Px));

Px=0;

}

io[1]=io[0]; // recopie de la voie 0 sur la voie 1 }

Remarque : on affiche à la fois la puissance et la racine carrée de la puissance qui est la valeur efficace du signal. On utilise donc la fonction sqrt() dont le prototype est contenu dans le fichier "math.h". Il ne faut donc pas oublier d’inclure ce fichier en tête de notre fichier source :

#include <math.h>

Reconstruire ensuite l’exécutable puis lancer son exécution :

On remarque que la charge est maintenant de 1.5% ; c’est-à-dire un peu plus élevée du fait des calculs effectués.

Vérifier la validité de la valeur efficace estimée en la comparant à celle estimée par l’oscilloscope.

Imaginons que le programme ne fonctionne pas comme on le voudrait. Nous pourrions rechercher le problème en recourant au débogueur.

Typiquement, nous placerions un point d’arrêt à un endroit d’intérêt du code source :

Puis nous lancerions la session de débogage (Menu "Debug" de Codeblocks puis "Start/Continue".

L’exécution commence et s’arrête au niveau du point d’arrêt :

(6)

On peut alors examiner les valeurs des différentes variables de manière à identifier la cause du mauvais fonctionnement.

Lorsque le fonctionnement du programme est satisfaisant, nous pouvons éventuellement reconstruire le projet en version "Release" (plutôt qu’en version "Debug") de manière à obtenir un code machine plus efficace. Dans le cas du programme considéré ci-dessus, la charge passe alors de 1.5% à 0.5%. A ne pas négliger lorsque la charge en mode "Debug" est excessive (proche ou supérieure à 100%).

Mode simulateur

Il est à noter que le projet CodeBlocks initial propose un mode "Simulateur" (en plus des modes "Release"

et "Debug") destiné à tester les traitements programmés en l'absence du matériel. Il suffit d'avoir

CodeBlocks installé sur une machine quelconque (PC Windows par exemple) pour l'utiliser. Dans ce mode, les entrées et sorties se font via des fichiers ascii.

(7)

- TP DSP - - Prise en main -

Le but de cette première manipulation est de se familiariser avec le matériel et de mesurer la fonction de transfert du système de traitement numérique en absence de tout traitement.

Préparation

Lire attentivement et entièrement le texte. Réfléchir à ce que signifie un traitement produisant une phase linéaire. Renommer et adapter le projet CodeBlocks initial en recourant au mode "Simulateur" de manière à répondre aux différentes questions. Préparer, dans la mesure du possible, les réponses aux questions auxquelles il faudra répondre dans le compte-rendu.

Compte-rendu

Le compte rendu comprendra les listings des différents programmes, les observations ainsi que leurs exploitations et les réponses aux différentes questions.

Prise en main

Utiliser le projet pass initial de manière à transmettre sans traitement les échantillons d’entrée en sortie.

Appliquer un signal en entrée et observer le signal produit en sortie.

Désactiver la partie numérique des filtres anti-repliement et/ou de reconstruction. Observer les phénomènes de repliement ainsi que l’allure du signal en sortie. Commenter.

Fonction de transfert globale

Il s'agit de déterminer la réponse en fréquence globale de la carte. Pour cela, appliquer un signal sinusoïdal en entrée du système (filtres numériques anti-repliement et de reconstruction activés) et observer le signal en sortie.

Dans un premier temps, se faire une idée de l’allure de la réponse en fréquence en module et en phase en parcourant le domaine fréquentiel.

Procéder ensuite aux seules mesures utiles et nécessaires puis aux tracés (en utilisant une échelle linéaire pour les abscisses).

Le module pourra être tracé à la fois en linéaire pour apprécier les ondulations éventuelles en bande passante et en décibel pour apprécier l’atténuation en bande affaiblie. Déterminer le ou les fréquences de coupures.

La phase quant à elle devra être exploitée de manière à mettre en évidence sa linéarité et donc son équivalence à un retard pur. Déterminer la valeur de ce retard et proposer une explication.

Proposer une méthode alternative pour mesurer ce retard. Vérifier la cohérence des résultats.

Fonction de transfert d'entrée

Le but est de mesurer la contribution à la fonction de transfert des filtres anti-repliement situés en entrée.

Pour cela, nous allons comparer le signal numérique obtenu à l'intérieur du processeur au signal analogique présent en entrée. Du fait de l’absence de référence temporelle commune aux deux domaines analogique et numérique, nous ne pourrons pas mesurer le déphasage entre les signaux. Nous ne nous intéresserons donc qu’au module de la réponse en fréquence.

Mesurer l'amplitude du signal analogique en entrée ne pose pas de problème. Par contre, la mesure de l'amplitude du signal numérique au niveau du processeur est plus délicate.

Différentes méthodes sont envisageables. Quelles sont-elles ?

Une des plus fiables consiste à estimer la puissance du signal numérique puis d’en déduire sa valeur efficace.

La puissance d’un signal numérique est la moyenne des échantillons au carrés.

Modifier le projet initial pour estimer la puissance du signal numérique en calculant la somme suivante :

1 2

0

1 ( )

N n

P x n

N

=

=

puis imprimer la valeur de

P

ainsi que la valeur efficace déduite grâce à la fonction log_printf(). On fera en sorte de réitérer infiniment le calcul et l’affichage.

(8)

Comparer dans un premier temps l'estimation obtenue pour différentes valeurs de

N

. Comment faut-il choisir cette valeur pour obtenir une estimation de qualité.

Après avoir réglé correctement cette valeur, relever et tracer le module de la réponse en fréquence du filtre anti-repliement. Comparer à la fonction de transfert globale.

Désactiver la partie numérique des filtres anti-repliement. Quels sont les changements ?

Fonction de transfert de sortie

Il s'agit de mesurer la réponse en fréquence des filtres de reconstruction présents en sortie de la carte.

Nous ne nous intéresserons encore une fois qu'au module de la réponse en fréquence. Pour mesurer cette grandeur, il faut maintenant générer un signal sinusoïdal d'amplitude déterminée à l'intérieur du processeur et relever l'amplitude du signal analogique obtenu en sortie de la carte. On pourra pour cela utiliser

l'instruction suivante :

io[0]=A*sin(2*pi*f*(n++)*Te);

Cependant, cette instruction peut poser problème du fait que la variable n grandit continuellement et peut arriver à saturation. Proposer si possible une modification pour résoudre ce problème.

Relever et tracer le module de la réponse en fréquence des filtres de reconstruction. Comparer à la fonction de transfert globale.

Les fonctions de transfert d'entrée et de sortie confirment-elles la fonction de transfert globale ? Que se passe-t-il si le signal sinusoïdal généré par le processeur est à une fréquence supérieure à

2 F e .

Essayer avec 3 4

Fepar exemple puis avec d'autres fréquences. Expliquer le phénomène observé.

Rapport Signal à Bruit

Le but est d'évaluer le rapport signal à bruit au niveau du signal de sortie. Pour cela, injecter un signal sinusoïdal en entrée de la carte et utiliser le module fft de l'oscilloscope pour caractériser le bruit au niveau du signal de sortie. Quelle est la nature de ce bruit (blanc, harmonique, etc.). Mesurer sa puissance et en déduire le rapport signal à bruit de sortie.

(9)

- TP DSP -

- Filtrage à Réponse Impulsionnelle Finie -

Préparation

Lire attentivement et entièrement le texte. Calculer les réponses en fréquences théoriques (module et phase) des filtres devant être mis en œuvre (lorsqu'elles ne sont pas fournies). Réfléchir au moyen de mettre en évidence la phase linéaire des différents filtres (en comprenant évidemment ce qu'est une phase linéaire ; point déjà abordé lors du premier TP). Préparer les réponses aux questions auxquelles il faudra répondre dans le compte-rendu.

Compte-rendu

Le compte-rendu comprendra la préparation, les listings des différents programmes, et les réponses aux différentes questions.

Introduction

Commencer très simplement en implantant les réponses impulsionnelles : { 1 ; 1 } et { 1 ; -1 }. Il s'agit simplement de délivrer en sortie la somme ou la différence de deux échantillons successifs d'entrée. Les programmes C relatifs à ces deux filtres s'appelleront rif1.c et rif2.c. Vérifier rapidement les réponses en fréquence (module) de ces filtres très simples en les comparant aux réponses théoriques (utiliser une échelle linéaire).

La convolution des réponses impulsionnelles précédentes (mise en série des filtres) donne : { 1 ; 0 ; -1 }.

Implanter ce nouveau filtre via le programme rif3.c. Vérifier la justesse de sa réponse en fréquence.

Ce filtre est-il à phase linéaire ? Si oui, quelle est cette phase et quel est le retard introduit par ce filtre (théoriques et mesurés (attention au retard introduit par la carte elle-même)) ? Pour mesurer plus justement le déphasage engendré par le traitement numérique uniquement, on pourra délivrer sur l'une des sorties de la carte le signal filtréy(n) et sur l'autre le signal d'entrée x(n) (ou encore x(nL)

L

est un retard judicieusement choisi pour mettre en évidence la phase linéaire du traitement).

Convolution

Ecrire un programme rif4.c destiné à mettre en œuvre des filtres R.I.F. de façon plus systématique, c’est- à-dire en effectuant l’opération de convolution :

=

= 1

0

) ( ) ( ) (

N

i

i n x i h n y

Pour cela, définir la dimension du filtre grâce à un define au début du programme :

#define N 10

Et déclarer les tableaux destinés à recevoir les coefficients de la réponse impulsionnelle ainsi que les échantillons du signal d’entrée devant être mémorisés :

float h[N], x[N];

Puis initialiser la réponse impulsionnelle : h[0]= ...;

h[1]= ...;

h[N-1]= ...;

Remarque : on pourra également initialiser la réponse impulsionnelle en la déclarant : float h[]={ 1 , 0, -1 };

Ces variables correctement déclarées et initialisées, programmer le traitement : y=0;

for(i=0; i<N; ++i){

y=y+ ...

}

ainsi que la mise à jour du tableau des échantillons d’entrée nécessaires au traitement.

Dans un premier temps, on pourra fixer N à 3 et chercher la réalisation du filtre précédent de réponse : { 1 ; 0 ; -1 } et vérifier le bon fonctionnement du programme.

(10)

Filtre passe bas

Le programme générique fonctionnant correctement, on pourra implanter facilement un filtre passe bas obtenu avec Matlab :

h=[ 0.0537 0 -0.0916 0 0.3131 0.5 0.3131 0 -0.0916 0 0.0537 ] de la façon suivante :

N = 11;

F = [ 0 2*0.2 2*0.3 2*0.5 ];

M = [ 1 1 0 0 ];

h=remez(N-1,F,M);

Les caractéristiques de ce filtre sont les suivantes :

Il suffira pour cela d'adapter N à la dimension du filtre et d'initialiser le tableau contenant les coefficients du filtre. Le fichier contenant le programme s'appellera rif5.c.

On relèvera la réponse en fréquence et on la comparera à celle attendue. On vérifiera également la phase linéaire du filtre en mesurant le retard introduit par le filtre (procéder comme auparavant).

Filtre passe haut

Transformer le filtre passe bas précédent en filtre passe haut en faisant en sorte que la réponse en fréquence soit décalée de

2

±Fe. Comment faut-il modifier les coefficients de la réponse impulsionnelle.

Mettre en œuvre le filtre (programme rif6.c)et vérifier la nouvelle réponse en fréquence. Peut-on

appliquer une méthode analogue pour passer d'un filtre passe bas à un filtre passe bande ? Si oui, expliquer comment.

Filtre de Hilbert

On implantera pour finir un filtre à coefficients complexes (rif7.c) obtenu avec Matlab :

h = [ 0 -0.0267j 0 -0.0584j 0 -0.1049j 0 -0.1991j 0 -0.6323j 1 0.6323j 0 0.1991j 0 0.1049j 0 0.0584j 0 0.0267j 0 0 ]

de la façon suivante :

N=21; h=hilbert([zeros(1,(N-1)/2) 1 zeros(1,(N+1)/2)]);

Les caractéristiques de la partie imaginaire de ce filtre sont les suivantes :

0 0.5 1

0 0.5 1 1.5

|H(f)|

0 0.5 1

-80 -60 -40 -20 0 20

|H(f)| (dB)

0 5 10 15

-0.2 0 0.2 0.4 0.6

h(n)

0 0.5 1

-200 -100 0 100 200

Phase (°)

(11)

Le programme appliquera le filtre à une des voies d'entrée et les parties réelle et imaginaire du signal produit seront délivrées sur les deux voies de sortie.

Comparer les signaux de sortie. Quelle est la particularité de ce genre de filtres ? A quoi peuvent-ils servir ? Calculer avec Matlab puis mettre en œuvre un filtre plus long et donc plus efficace (N=101 par exemple).

Quelle serait la réponse en fréquence idéale ? En déduire la réponse impulsionnelle associée.

0 0.5 1

0 0.5 1 1.5

|H(f)|

0 0.5 1

-100 -50 0 50

|H(f)| (dB)

0 10 20 30

-1 -0.5 0 0.5 1

h(n)

0 0.5 1

-200 -100 0 100 200

Phase (°)

(12)

- TP DSP -

- Filtrage à Réponse Impulsionnelle Infinie -

Préparation

Lire attentivement et entièrement le texte. Déterminer les coefficients des filtres devant être calculés ainsi que les facteurs d’échelle. Préparer les réponses aux questions auxquelles il faudra répondre dans le compte-rendu.

Compte-rendu

Le compte-rendu comprendra la préparation, les listings des différents programmes, et les réponses aux différentes questions.

Introduction

Les filtres à réponse impulsionnelle infinie sont plus délicats à implanter que les filtres à réponse

impulsionnelle finie car leur caractère récursif (contre réaction) les expose à la divergence. Ceci est d'autant plus vrai que leurs pôles sont proches du cercle unité. On dit alors qu'on a affaire à des filtres résonnants.

De tels filtres requièrent une grande précision au niveau de leurs coefficients, des échantillons et des calculs.

Cellule du second ordre purement récursive

Soit la fonction de transfert est la suivante :

2 2 1

1 1

) 1

(

+

= +

Z b Z b Z H

Calculer les coefficients du filtre pour que la résonnance ait lieu à la fréquence 4

Fe et que son amplitude soit de 10. Tracer la réponse en fréquence. Quel facteur d’échelle faut-il appliquer au signal pour qu’il n’y ait pas saturation en sortie ?

Programmer ce filtre (rii1.c) et comparer la réponse en fréquence obtenue à sa valeur théorique.

De quel type de filtres s’agit-il ? A quoi peuvent-ils servir ? Comment varie leur phase ?

Cellule du second ordre générale

Soit la fonction de transfert est la suivante :

2 2 1 1

2 2 1 1 0

1 )

(

+ +

+

= +

Z b Z b

Z a Z a Z a

H

Conserver les coefficients du dénominateur déterminés précédemment pour obtenir une fréquence de résonnance de

4

Fe. Calculer les coefficients du numérateur pour obtenir des zéros sur le cercle unité en 4 Fe . Evaluer la réponse en fréquence grâce à l’interprétation géométrique. Quel facteur d’échelle faut-il

appliquer au signal pour qu’il n’y ait pas saturation en sortie ?

Programmer ce filtre (rii2.c) et comparer la réponse en fréquence obtenue à sa valeur théorique.

De quel type de filtres s’agit-il ? A quoi peuvent-ils servir ? Comment varie la phase ?

Filtre elliptique passe-bas

Ordre 2

Il s’agit pour commencer d’un filtre d'ordre 2 obtenu avec la méthode elliptique sous Matlab de la façon suivante :

(13)

[B,A] = ellip(N, 0.9, 26, Wn);

 B = 0.1744 0.2419 0.1744

 A = 1.0000 -0.7400 0.3953

Les caractéristiques fréquentielles de ce filtre sont les suivantes :

Programmer ce filtre (rii3.c) et comparer la réponse en fréquence obtenue à sa valeur théorique.

Ordre élevé

Il s’agit d’un filtre elliptique d’ordre 6 obtenu de la façon suivante avec Matlab :

[N, Wn] = ellipord(0.4, 0.6, 0.09, 60);  N = 6 Wn = 0.4 [B,A] = ellip(N,0.09,60,Wn);

 B = 0.0207 0.0585 0.1060 0.1255 0.1060 0.0585 0.0207

 A = 1.0000 -1.9673 2.9074 -2.5353 1.5771 -0.5972 0.1163 Les caractéristiques fréquentielles de ce filtre sont les suivantes :

0 0.5 1

0 0.2 0.4 0.6 0.8 1

|H(f)|

0 0.5 1

-80 -60 -40 -20 0

|H(f)| (dB)

0 0.5 1

0 0.5 1 1.5 2 2.5

Groupe delay

0 0.5 1

-200 -150 -100 -50 0 50

Phase (°)

(14)

Programmer ce filtre (rii4.c) et comparer la réponse en fréquence obtenue à sa valeur théorique. Que peut-on dire de sa phase ?

Passe-haut

Expliquer comment il faudrait modifier les coefficients du filtre passe-bas d’ordre 6 pour obtenir un filtre passe-haut de même largeur de bande. Justifier votre réponse.

Programmer ce filtre (rii5.c) et vérifier la justesse de la transformation.

Existe-il une méthode analogue pour obtenir un filtre passe-bande ? Si oui, laquelle ? Peut-on l’appliquer au filtre passe-bas d’ordre 6 ? Si oui, quelle est la bande passante du filtre ?

Oscillateur

Reprendre le programme rii1.c (le recopier dans un programme oscil.c) et modifier les coefficients b1 et b2 pour que le pôle soit sur le cercle unité en

8

Fe et initialiser les échantillons y(−1) et y(−2) pour que le signal de sortie y(n) produit en absence de signal d'entrée (x(n)=0) soit une cosinusoïde

d'amplitude unité. Vérifier le bon fonctionnement de l'oscillateur ainsi produit.

L'amplitude dérive-t-elle ? Proposer une explication.

Discuter la précision fréquentielle.

0 0.5 1

0 0.5 1 1.5

|H(f)|

0 0.5 1

-100 -50 0 50

|H(f)| (dB)

0 0.5 1

0 5 10 15 20

Groupe delay

0 0.5 1

-200 -100 0 100 200

Phase (°)

(15)

- TP DSP - - Prédiction Linéaire -

Préparation

Lire attentivement et entièrement le texte. Préparer les réponses aux questions auxquelles il faudra répondre dans le compte-rendu.

Compte-rendu

Le compte-rendu comprendra la préparation, les listings des différents programmes, et les réponses aux différentes questions.

Introduction

Par opposition aux filtres analogiques dont les caractéristiques sont le plus souvent figées, les filtres numériques peuvent facilement évoluer au cours du temps. Il suffit pour cela de modifier leurs coefficients qui sont stockés dans la mémoire du processeur de traitement. Il est possible ainsi de passer d'un filtre passe bas à un filtre passe haut (ou quelconque) d'un instant à un autre en conservant le même programme de traitement. Il suffit pour cela de remplacer un jeu de coefficients par un autre (ou simplement de

commuter d'un jeu à un autre). Ce potentiel ouvre la voie à des traitements adaptés au cours du temps aux caractéristiques temporelles/fréquentielles ou statistiques du signal. Citons par exemple le cas d'une transmission radio d'un signal dans la gamme des fréquences HF.

La gamme HF s'étend de 2 à 30 MHz et permet l'établissement de communications à très longue distance (plusieurs milliers de kilomètres) grâce à la réflexion des ondes sur les couches ionosphériques de

l'atmosphère qui se situent à des altitudes allant de 100 à 300 km. De multiples réflexions faisant intervenir le sol peuvent apparaître et ainsi plusieurs trajets de propagation coexister en même temps avec des retards différentiels pouvant aller jusqu'à 5 ms. De plus, chaque trajet a des caractéristiques fluctuantes tant en amplitude qu'en phase du fait notamment du mouvement des couches ionisées ; la bande de fréquences de ces fluctuations est de l'ordre de quelques Hz.

Pour des débits supérieurs à 600 bit/s dans la bande 300-3000 Hz en modulations de phase, les taux d'erreurs en absence de traitement sont trop importants. L'amélioration de la qualité du signal reçu passe alors par l'emploi de filtres numériques adaptatifs dont le rôle est d'"égaliser" le canal de transmission non- stationnaire. Grossièrement, il s'agit de compléter le traitement variable que le signal a subi dans le canal de transmission par un traitement adaptatif de sorte que le traitement global (canal+égaliseur) apparaisse comme fixe et équivalent à un filtre à phase linéaire passe tout (retard pur).

Des principes équivalents peuvent être appliqués dès lors qu'un signal utile subit un traitement indésirable et variable (provoqué le plus souvent par un milieu naturel). Citons à titre d'exemple les applications médicales telles que l'échographie, l'écoute de phénomènes naturels (sismographie), l'annulation d'écho en téléphonie, etc.

Il est un autre domaine où les traitements adaptatifs sont beaucoup utilisés. C'est celui de la caractérisation et du codage des signaux. L'observation de base est que de nombreux signaux peuvent être vus comme des bruits blancs ayant traversés un filtre qui les a pourvus de caractéristiques fréquentielles particulières.

C'est le cas de nombreux sons émis par l'homme quand il parle. L'idée est alors de chercher à déterminer les caractéristiques du filtre qui aurait fourni un tel signal à partir d'un simple bruit blanc. A partir de là, s'il s'agit par exemple de transmettre à distance le signal, il suffit d'envoyer le filtre (le modèle), et

éventuellement le bruit blanc à l'origine du signal (l'excitation). De même s'il s'agit de reproduire le signal (synthétiseur par exemple), il est plus économique de mémoriser le filtre et éventuellement son excitation plutôt que le signal lui-même (souvent, l'excitation n'est pas nécessaire ; un simple bruit blanc synthétique peut suffire).

Dans la pratique, le modèle est obtenu indirectement en adaptant un filtre au signal étudié de façon à retrouver un bruit blanc :

b(n) : bruit blanc inconnu (excitation)

Modèle Filtre adaptatif

b(n) x(n) e(n)

(16)

x(n) : signal observé

e(n) : bruit blanc (b(n) estimé).

Plus précisément, le filtre est adapté en cherchant à "prédire" le signal observé s(n) à partir de ses échantillons passés { x(n-1) ; x(n-2) ; . . . . x(n-N) } (N : ordre du filtre). e(n) devient alors une erreur de prédiction :

) ( ) ( . ) (

1

n x i n x a n e

N

i

i − −

=

=

ou encore

1 )

( . )

( 0

0

=

=

=

a avec i n x a n e

N

i i

La prédiction est correcte lorsque la puissance de l'erreur est minimale. Sous certaines conditions, cette dernière est alors également blanche. Le filtre constitué par les coefficients ai représente alors une estimation de l'inverse du modèle et donc indirectement une caractérisation de ce dernier.

L'adaptation des coefficients du filtre passe par l'emploi d'algorithmes plus ou moins compliqués. Le plus simple est celui dit du "gradient stochastique" qui, appliqué à la minimisation de l'erreur quadratique moyenne (Least Mean Squares ou LMS) conduit à l'équation d'adaptation suivante :

) ( ).

( . ) ( ) 1

(n a n xn i e n ai + = i −µ −

La quantité x(ni).e(n) est la dérivée partielle du carré de l'erreur de prédiction à l'instant n par rapport au coefficient ai . L'ensemble de ces quantités pour i allant de 1 à N forme le gradient de l'erreur. L'algorithme du gradient stochastique consiste à rechercher la minimisation de l'erreur en faisant évoluer les coefficients du filtre dans la direction opposée au gradient.

µ

est une grandeur appelée "pas d'adaptation" qui doit être choisie très petite : 0.01 ou 0.001. C'est cette grandeur qui règle le compromis entre la vitesse de convergence du filtre et sa qualité.

Manipulation

Créer ou reprendre un programme réalisant un filtre à réponse impulsionnelle finie.

Compléter ce programme de façon à réaliser un filtre de prédiction adaptatif. Pour cela :

- Initialiser l'ensemble des coefficients à zéro à l'exception du premier qui doit être initialisé à -1.

- Programmer l'équation d'adaptation des coefficients (à l'exception du premier qui doit demeurer à -1).

Le filtre devra s'adapter au signal présent sur la première entrée de la carte constituée d'une ou plusieurs fréquences pures (signal carré par exemple). La première sortie devra délivrer l'erreur de prédiction.

Si elles sont présentes, les deuxièmes entrée et sortie de la carte pourront être utilisées pour observer les caractéristiques fréquentielles du filtre adaptatif grâce à l'analyseur de spectre. Pour que cela soit possible, il faudra évidement que le programme effectue également le filtrage de la deuxième entrée et délivre le résultat sur la deuxième sortie.

Si la carte de dispose pas d'une seconde sortie, on pourra arrêter l'adaptation au bout d'un certain temps (tout en maintenant le filtrage) de façon à analyser les caractéristiques du filtre après adaptation (générateur BF et oscilloscope en mode FFT). Une seconde manière plus élégante pour analyser les caractéristiques fréquentielles du filtre consiste à créer en interne un signal évoluant linéairement en fréquence depuis 0 jusque

2

Fe et de délivrer en sortie de la carte ce signal après filtrage.

A titre indicatif, voici comment peut être généré le signal évoluant en fréquence :

(17)

#include <math.h>

void Process(float io[2]) {

static float f=0,ft=0,df=2.0/48000;

if((f+=df)>=0.5) f=0.0;

if((ft+=f)>=1.0) ft-=1.0;

*io=sinf(2*3.1416*ft);

}

Observations

Observer le comportement du filtre adaptatif en fonction du signal d'entrée (sinusoïdal, carré, …), du pas d'adaptation et de la dimension du filtre. Commenter.

Comparer aux résultats obtenus avec un algorithme plus sophistiqué des moindres carrés récursif dont le programme est contenu dans le fichier mcr.c. Commenter.

(18)

- TP DSP -

- Egalisation Aveugle -

Préparation

Lire attentivement et entièrement le texte. Préparer les codes des différentes fonctions C nécessaires à la réalisation du TP. Préparer les réponses aux questions auxquelles il faudra répondre dans le compte-rendu.

Compte-rendu

Le compte-rendu comprendra la préparation, les listings des différents programmes, et les réponses aux différentes questions.

Introduction

Le but du TP est de simuler en temps réel une chaîne de transmission de données :

Pour cela, le kit de développement Texas est muni d’une carte fille munie de deux entrées et de deux sorties. L’échantillonnage est effectué à 22 kHz.

Dans le cadre du TP : L’entrée 1 est utilisée éventuellement pour recevoir les symboles à transmettre (données). La sortie 1 est utilisée pour délivrer le signal dégradé en sortie du canal après ajout du bruit.

L’entrée 2 est utilisée pour recevoir le signal dégradé (sortie 1 sur entrée 2). Enfin la sortie 2 est utilisée pour sortir le signal égalisé.

Génération des données

Il s’agit d’un train binaire (0 et 1 aléatoires) codé en NRZ (Non Retour à Zéro) : Les 0 et les 1 sont transmis respectivement sous forme d’une tension –V et +V.

Si le générateur de tension disponible dans le cadre du TP est capable de délivrer un tel signal, on pourra l’utiliser. Il faudra le régler de façon que le rythme des symboles (0 et 1) soit acceptable (Fe/8 par exemple) et que la tension délivrée soit adaptée à la carte de traitement (

± 1 V

par exemple).

Si le générateur de tension n’est pas capable de délivrer un tel signal, il faudra programmer la carte de traitement pour générer le signal en interne. Pour obtenir une grandeur aléatoire, utiliser la fonction rand() qui délivre une valeur entière aléatoire comprise entre 0 et RAND_MAX (fonction et constante définies dans stdlib.h). Attention, il ne faut pas modifier la valeur du signal généré à chaque nouvel instant

d’échantillonnage car le rythme symbole doit être inférieur à la fréquence d’échantillonnage (Fe/8 par exemple). Par souci de clarté, on isolera le code responsable de la génération des symboles dans une fonction :

int GetSymbole() { … }

Le bon fonctionnement de la génération des données sera vérifié en transmettant provisoirement les symboles sur la première voie en sortie de la carte de traitement. Observer alors le signal obtenu (il s’agit d’un signal aléatoire qu’il convient d’observer en réglant correctement l’oscilloscope). Faire varier le rythme symbole. Justifier l’allure du signal (après avoir établi sa densité spectrale de puissance). Remarquer sa dissymétrie et proposer une explication.

Canal

Il s’agit de simuler l’action du canal de transmission (ligne, propagation, etc.) par un filtre. Ici, le signal est transmis en bande de base comme dans le cas d’une transmission sur ligne (il n’y a pas de fréquence porteuse comme en radio). On adoptera donc comme modèle de canal celui généralement retenu pour une

Données estimées

Canal Egaliseur

Données

Bruit

(19)

1 1

) 1

( = −

Z Z

C α

α est une valeur proche de 1.

Comment doit être choisi α pour que ce modèle fonctionne ? Donner l’allure de la réponse en fréquence pour

α = 0 . 9

. Calculer alors la puissance du signal en sortie du canal. Et proposer une estimation grossière de sa densité de probabilité. En déduire le facteur d’échelle qu’il convient d’appliquer au signal pour le délivrer en sortie de la carte de traitement sans saturation.

Programmer la fonction de filtrage : x=Canal(s);

où s et x sont respectivement le symbole courant et le signal en sortie du canal.

Observer le signal en sortie du canal en le transmettant en sortie de la carte. Justifier son allure.

Bruit

Il s’agit de simuler une dégradation du signal par un bruit additif gaussien. La seule fonction disponible dans le DSP pour obtenir une valeur aléatoire est la fonction rand(). Celle-ci fournit une valeur aléatoire entière uniformément répartie entre 0 et RAND_MAX. Proposer une méthode utilisant cette fonction et produisant une valeur aléatoire gaussienne centrée de puissance unité. Programmer cette fonction. Vérifier son bon fonctionnement en délivrant le bruit produit en sortie de la carte. Enfin, utiliser la fonction pour bruiter le signal en sortie du canal de façon à obtenir un rapport signal à bruit de 20 dB :

x=x+gamma*randn() ; Où gamma est l’amplitude du bruit.

Délivrer le signal dégradé sur la première sortie de la carte. Vérifier le résultat en observant le signal.

Egalisation

Il s’agit de traiter le signal dégradé obtenu sur la première sortie de la carte et rebouclé sur la deuxième entrée avec un filtre adaptatif de façon à obtenir un signal exploitable ; c’est-à-dire, un signal qui puisse être seuillé pour déterminer les données initialement transmises.

Le filtre adaptatif est un filtre à réponse impulsionnelle finie :

=

= 1

0

) ( ).

( )

(

N i

i n x i w n

y

Son adaptation est réalisée avec l’algorithme du gradient stochastique (LMS : Least Means Squares) grâce à une séquence d’apprentissage.

Normalement, la séquence d’apprentissage est constituée d’une certaine quantité de symboles aléatoires.

La séquence est émise en début de transmission (juste avant d’émettre les symboles constituant le message utile). La séquence est distordue et bruitée dans le canal physique. Lorsque la séquence est reçue, l’égaliseur qui connaît la séquence émise s’adapte en réglant les coefficients du filtre de façon à obtenir un signal le plus proche possible du signal émis : la séquence. Lorsque la séquence prend fin, l’égaliseur est normalement adapté : le filtre obtenu est satisfaisant. Ce dernier est alors utilisé pour traiter les symboles inconnus dégradés par le canal. Lorsque les caractéristiques du canal varient dans le temps, l’égaliseur doit être recalculé périodiquement ; ce qui nécessite à chaque fois l’émission d’une séquence d’apprentissage. L’émission de séquences d’apprentissage diminue le débit utile de la transmission. D’autre part, l’utilisation de séquences d’apprentissage n’est pas aisée du fait de la synchronisation nécessaire entre l’adaptation de l’égaliseur et la réception des séquences (l’égaliseur doit s’adapter lorsque le signal d’apprentissage est reçu). Cette synchronisation est obtenue généralement en observant l’intercorrélation entre la séquence et le signal reçu. Le calcul de cette intercorrélation représente un coût non négligeable.

Ces différents inconvénients ont conduit au développement de nouvelles techniques dites "aveugles" en ce sens qu’elles opèrent l’égalisation du signal en absence de séquences d’apprentissage.

C’est une de ces techniques que nous allons utiliser dans le cadre de ce TP.

CMA (Constant Modulus Algorithm)

L’idée est extrêmement simple : le signal émis est constitué de valeurs

± 1

(à un facteur d’échelle près). Il convient donc d’adapter le filtre égaliseur de façon à obtenir un signal analogue en sortie. Est-ce une condition suffisante pour obtenir un signal de sortie correspondant au signal émis. La réponse est oui car s’il subsistait de l’interférence inter-symboles, alors en vertu du caractère aléatoire des symboles

) (n e

) (n d )

(n y

(20)

(indépendance), le signal résultant (combinaison linéaire des symboles émis du fait d’une mauvaise adaptation de l’égaliseur) serait plus dispersé (théorème centrale limite).

Cette propriété est exploité en utilisant le schéma d’adaptation suivant :

Le signal désiré d(n) est obtenu en "décidant" le signal en sortie de l’égaliseur.

Lorsque l’égaliseur est adapté, à un instant donné, le signal de sortie y(n) est proche d’un symbole unique (l’interférence inter-symboles est faible). La fonction non-linéaire de décision a de grandes chances de déterminer la valeur initiale du symbole (la probabilité d’erreur est faible). Le signal d(n) constitue alors un très bon signal désiré (au même titre qu’un signal d’apprentissage). Bien sûr, à certains instants, du fait du bruit, la décision sera incorrecte. L’utilisation du signal d(n) conduira alors à une mauvaise correction de l’égaliseur. Mais si l’égaliseur est déjà correctement adapté (transmission établie), ces instants de

mauvaises décisions sont en très faible nombre (moins de 1 pour 1000 typiquement si la transmission est exploitable) et donc sans conséquence. Cette façon de procéder offre l’avantage non négligeable d’assurer une adaptation continuelle au canal de transmission (et non plus pendant les seules séquences

d’apprentissage).

La seule question qui subsiste concerne "l’amorçage" du système. Il n’est pas facile de répondre à cette question. Le plus simple, dans le cadre de ce TP, est de programmer la technique et de déterminer dans quelle mesure elle fonctionne. Nous verrons en particulier qu’elle est très sensible à la façon d’initialiser les coefficients du filtre égaliseur.

Programmer la technique dans une fonction :

y=Cma(x2); /* x2 : signal provenant de la seconde entrée */

Le code est analogue à celui mis au point pour la prédiction linéaire. Seul le signal désiré est différent. Dans le cas de la prédiction linéaire, c’était le signal présent en entrée du filtre prédicteur. Désormais, il s’agit du signal de sortie du filtre décidé :

if(y>0) d=1; else d=-1;

Initialisation : on initialisera l’ensemble des coefficients du filtre à 0 à l’exception du coefficient central qu’on initialisera à 1. Le pas d’adaptation sera choisi très petit : 0.001 ou 0.0001.

A l’issue de la programmation de cette dernière fonction, la fonction Process devrait présenter l’allure suivante :

void Process(float io[2]) { float s;

s=GetSymbole();

io[0]=Canal(s)+0.0*randn();

io[1]=Cma(io[1]);

}

Délivrer le signal égalisé sur la seconde sortie de la carte. Comparer ce signal au signal en sortie du canal délivré par la première sortie. Régler l’oscilloscope de façon à obtenir le diagramme de l’œil. Le représenter et indiquer à quel instant et avec quel seuil le signal doit être décidé pour identifier les valeurs des symboles émis.

Observer l’ouverture de l’œil en fonction du bruit, du pas d’adaptation et de la façon d’initialiser les coefficients du filtre. Commenter.

+1

) (n e

) (n d )

(n y

-1

Références

Documents relatifs

Fiches pratiques Analyse &amp; traitement du signal #Sinust. Le signal sinusoïdal

SLIT à temps discret – Réponse impulsionnelle - Convolution discrète – Réponse en fréquence – Fonction filtrage Filtre à Réponse Impulsionnelle Finie (RIF) - Filtre à

• Valeur du gain de ce filtre à la fréquence de coupure : –3dB (quel que soit l’ordre N).. Rm : le temps de propagation

Une variable simple (ce qu’on appelle &#34;un scalaire&#34;) est vue comme un tableau à une ligne et une colonne ; un vecteur de N éléments est vu comme une matrice à une colonne et

La même TFD que ci-dessus peut être appliquée en boucle, au signal entier, en découpant ce dernier en parties de tailles égales, appelées trames. Le résultat est alors un ensemble de

où ω 0 est la pulsation de coupure. 1.1) En définissant un vecteur de valeurs de fréquences variant de 0 à 10000 Hertz par pas de 1, réaliser un affichage graphique du module

1.1) Générer quelques périodes d’un signal constitué par la somme de 2 signaux sinusoïdaux de mêmes amplitudes et de fréquences respectives f 1 =10Hz et f 2 =100Hz. 1.2)

Pour que cette somme puisse être non-nulle, il faut que le nombre de valeurs que prennent l’indice de h[k] (i) et celui de e[k] (j-i) soient égaux au nombre d’éléments de h[k] et