<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
		<id>http://wikigeii.iut-troyes.univ-reims.fr//api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Fredmn</id>
		<title>troyesGEII - Contributions de l’utilisateur [fr]</title>
		<link rel="self" type="application/atom+xml" href="http://wikigeii.iut-troyes.univ-reims.fr//api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Fredmn"/>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Sp%C3%A9cial:Contributions/Fredmn"/>
		<updated>2026-06-21T10:49:31Z</updated>
		<subtitle>Contributions de l’utilisateur</subtitle>
		<generator>MediaWiki 1.30.1</generator>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_eval1&amp;diff=21092</id>
		<title>Cours:Elen4 TNS TP eval1</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_eval1&amp;diff=21092"/>
				<updated>2026-06-02T14:04:15Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;accesscontrol&amp;gt;Acces:Prof&amp;lt;/accesscontrol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
* Sauf spécification, les traitements pourront se faire indifférement dans Gnuradio, dans Python/Jupyter ou dans les deux.&lt;br /&gt;
&lt;br /&gt;
* Faire valider les solutions de chaque question auprès de l'enseignant.&lt;br /&gt;
&lt;br /&gt;
* La note finale sera ramenée sur 20 points.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{{q| (3 points) 1)}} Construire un signal ''x(n)'' comme une sinuisoïde de fréquence 500Hz et d'amplitude 3, la fréquence d'échantillonnage étant de 32kHz. Tracer son graphe temporel dans Gnuradio.&lt;br /&gt;
&lt;br /&gt;
{{q| (3 points) 2)}} Tracer son graphe temporel dans Python/Jupyter.&lt;br /&gt;
&lt;br /&gt;
{{q| (3 points) 3)}} Ajouter à ''x(n)'' un bruit gaussien d'amplitude 1 puis tracer le graphe temporel de ''x(n)'' et son graphe fréquentiel (module).&lt;br /&gt;
&lt;br /&gt;
{{q| (3 points) 4)}} Proposer un filtre qui permettrait de réduire ce bruit. L'implémenter dans Python/Jupyter ou dans Gnuradio.&lt;br /&gt;
&lt;br /&gt;
{{q| (3 points) 5)}} Construire un signal ''x&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;(n) = s&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;(n) + s&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;(n) + s&amp;lt;sub&amp;gt;3&amp;lt;/sub&amp;gt;(n) + b(n)'', avec&lt;br /&gt;
* ''s&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;(n)'' : sinusoïde de fréquence 500Hz d'amplitude 3&lt;br /&gt;
* ''s&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;(n)'' : sinusoïde de fréquence 3000Hz d'amplitude 3&lt;br /&gt;
* ''s&amp;lt;sub&amp;gt;3&amp;lt;/sub&amp;gt;(n)'' : sinusoïde de fréquence 5000Hz, d'amplitude 2&lt;br /&gt;
* ''b(n)'' : bruit gaussien d'amplitude 1&lt;br /&gt;
{{Todos| Tracer les graphes temporel et fréquentiel de ''x&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;(n)''.}}&lt;br /&gt;
&lt;br /&gt;
{{q| (3 points) 6)}} On propose d'appliquer un filtre dont voici la fonction de transfert :&lt;br /&gt;
{{FxT | H(z) |&lt;br /&gt;
0.0032 + 0.0163 z&amp;lt;sup&amp;gt;-1&amp;lt;/sup&amp;gt; + 0.0327 z&amp;lt;sup&amp;gt;-2&amp;lt;/sup&amp;gt; + 0.0327 z&amp;lt;sup&amp;gt;-3&amp;lt;/sup&amp;gt; + 0.0163 z&amp;lt;sup&amp;gt;-4&amp;lt;/sup&amp;gt; + 0.0032 z&amp;lt;sup&amp;gt;-5&amp;lt;/sup&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
1 - 2.4744 z&amp;lt;sup&amp;gt;-1&amp;lt;/sup&amp;gt; + 2.8110 z&amp;lt;sup&amp;gt;-2&amp;lt;/sup&amp;gt; - 1.7037 z&amp;lt;sup&amp;gt;-3&amp;lt;/sup&amp;gt; + 0.5444 z&amp;lt;sup&amp;gt;-4&amp;lt;/sup&amp;gt; - 0.07231 z&amp;lt;sup&amp;gt;-5&amp;lt;/sup&amp;gt;}}&lt;br /&gt;
À toutes fins utiles, voici les coefficients du numérateur et du dénominateur, avec plus de précision et sous forme de liste :&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| Numérateur || : [0.0032792, 0.016396, 0.032792, 0.032792, 0.016396, 0.0032792]&lt;br /&gt;
|-&lt;br /&gt;
| Dénominateur || : [1, -2.4744, 2.811, -1.7038, 0.54443, -0.072316]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Montrer expérimentalement que ce filtre est stable.}}&lt;br /&gt;
&lt;br /&gt;
{{q| (3 points) 7)}} Tracer la réponse fréquentielle du filtre et indiquer sa nature et le caractériser.&lt;br /&gt;
&lt;br /&gt;
{{q| (3 points) 8)}} Implémenter ce filtre, en l'appliquant au signal ''x&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;(n)''. Vérifier le bon comportement du filtre.&lt;br /&gt;
&lt;br /&gt;
{{q| (3 points) 9)}} On souhaite ne conserver que la composante à 3kHz du signal ''x&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;(n)'', proposer une chaine complète de traitements.&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21091</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21091"/>
				<updated>2026-06-01T13:03:33Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* PID numérique avec un filtre numérique linéaire */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
Dans les deux cas, un système temps réel sera considéré :&lt;br /&gt;
* à intervalles de temps (réguliers ou non), une valeur ''x(n)'' rentre dans le système&lt;br /&gt;
* le travail consiste à calculer ''y(n)'' avec l'équation au différences du filtre, à partir de la valeur ''x(n)'' et de ses versions précédentes ''x(n-1)'' et ''x(n-2)'' (et aussi ''y(n-1)'', ''y(n-2)'') qu'il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de ''temps réel'' implique que ''y(n)'' doit être calculer avant qu'une nouvelle valeurs de ''x(n)'' ne rentre dans le système.&lt;br /&gt;
&lt;br /&gt;
=== Bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
Nous allons implémenter un filtre IIR dans gnuradio, en écrivant le traitement dans un bloc Python.&lt;br /&gt;
&lt;br /&gt;
==== Filtre moyenneur====&lt;br /&gt;
&lt;br /&gt;
{{q| a)}} Dans un premier temps, prendre connaissance du tutoriel suivant : [https://wiki.gnuradio.org/index.php?title=Creating_Your_First_Block wiki Gnuradio - ''Creating Your First Block'']&lt;br /&gt;
&lt;br /&gt;
{{q| b)}} Nous allons écrire un filtre simple, qui implémente un simple moyenneur :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;Python&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
from gnuradio import gr&lt;br /&gt;
&lt;br /&gt;
class blk(gr.sync_block):  &lt;br /&gt;
    def __init__(self):  # Pas de paramètres&lt;br /&gt;
        gr.sync_block.__init__(&lt;br /&gt;
            self,&lt;br /&gt;
            name=&amp;quot;Filtre moyenneur&amp;quot;,  &lt;br /&gt;
            in_sig=[np.float32],&lt;br /&gt;
            out_sig=[np.float32]&lt;br /&gt;
        )&lt;br /&gt;
        self.xn1 = 0 # initialisation d'un attribut pour stocker x(n-1)&lt;br /&gt;
&lt;br /&gt;
    def work(self, input_items, output_items):&lt;br /&gt;
        xn = input_items[0][0] # On ne &amp;quot;consomme&amp;quot; qu'un seul échantillon en entrée&lt;br /&gt;
        yn = (xn + self.xn1) / 2&lt;br /&gt;
        self.xn1 = xn&lt;br /&gt;
        output_items[0][0] = yn # On ne produit donc également qu'un seul échantillon en sortie&lt;br /&gt;
        return 1 # On retourne le nombre de valeurs consomées&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Filtre IIR : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc Python dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;np.float32&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;np.float32&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in[0][0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
&lt;br /&gt;
{{q| a)}}  Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au [[Cours:Elen4_TNS_TP_TraitAudioEtDemodulation|TP 5]].&lt;br /&gt;
&lt;br /&gt;
{{q| b)}}  Modifier votre code pour implémenter le filtre complet de démodulation.&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
Cette partie sera travaillée dans un notebook Jupyter.&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique, la sortie du controleur PID ''u(t)'' est donnée par:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
On considère que le temps est discrétisé : ''t = n.''d''t'' où d''t'' est l'intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée &amp;lt;br/&amp;gt;[[Fichier:PIDderivative.png|400px]] [[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
** La dérivée est calculée par ''D = (e(n)-e(n-1))/''d''t''&lt;br /&gt;
** L'intégrale est approximée en cumulant progressivement : ''I = I + e(n).''d''t''&lt;br /&gt;
C'est ainsi que vous avez implémenté vos PID jusqu'ici.&lt;br /&gt;
&lt;br /&gt;
Voici un notebook exemple à explorer sur deux modélisations : asservissement de 1) température et de 2) position ''z'' d'un drone : [[Media:TNS TP6 starter.ipynb.zip|TNS_TP6_starter.ipynb.zip]]&lt;br /&gt;
&lt;br /&gt;
{{q | a)}} ''Ki = Kd = 0'' =&amp;gt; chercher le meilleur ''Kp'' =&amp;gt; erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | b)}} ''Kd = 0'' =&amp;gt; l'introduction du terme integral permet de corriger cette erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | c)}} Le terme dérivatif n'est pas nécessaire pour la température&lt;br /&gt;
&lt;br /&gt;
{{q | d)}} Mais l'est pour asservir la position ''z'' du drone.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique avec un filtre numérique linéaire ====&lt;br /&gt;
&lt;br /&gt;
Nous allons reprendre le PID, par sa fonction de transfert qui exprime un filtre linéaire continu, et construire un filtre linéaire numérique qui l'approxime.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{q | a)}} Cherchons la fonction de transfert du filtre continu d'un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l'équation différentielle&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:EqPID.png|500px]]&lt;br /&gt;
&amp;lt;br/&amp;gt;On applique la transformée de Laplace (dérivée =&amp;gt; multiplication par ''s'' ; intégrale =&amp;gt; division par ''s'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPID.png|130]]&lt;br /&gt;
&amp;lt;br/&amp;gt;Le terme dérivatif étant très sensible au bruit, on lui applique généralement un filtre passe bas (''w0/(w0+s)'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
&lt;br /&gt;
{{q | b)}} Il s'agit maintenant de transformer la variable ''s'' en une variable ''z'' :&lt;br /&gt;
* par transformée bilinéaire : &amp;lt;br/&amp;gt; ''s = (2/Ts)*(z-1)/(z+1)'' (voir le cours)&lt;br /&gt;
* ou par ''backward euler'' (version un peu plus simple) : &amp;lt;br/&amp;gt;''s = (z-1)/(Ts*z)''.&lt;br /&gt;
&lt;br /&gt;
En injectant le changement de variable dans la fonction de transfert ''H(s)'', obtenir la fonction de transfert ''H(z)'' du filtre linéaire numérique correspondant (dans un premier temps avec ''backward Euler'') :&lt;br /&gt;
* soit &amp;quot;à la main&amp;quot;&lt;br /&gt;
* ou en exploitant [https://www.sympy.org/en/index.html Sympy] (calcul symbolique). Un début :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;Python&amp;quot;&amp;gt;&lt;br /&gt;
import sympy&lt;br /&gt;
from sympy import symbols, Poly, Eq&lt;br /&gt;
Ki, Kd, Kp, N, Ts, z, s = symbols('K_i K_d K_p N T_s z s')&lt;br /&gt;
&lt;br /&gt;
Hs = Kp + (Ki/s)  + Kd*s * (N/(N+s))&lt;br /&gt;
&lt;br /&gt;
Hz = Hs.subs(s, (z-1)/(Ts*z))&lt;br /&gt;
&lt;br /&gt;
# ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans les deux cas, il sera nécessaire d'obtenir ''H(z)'' sous la forme d'une fraction rationnelle.&lt;br /&gt;
&lt;br /&gt;
{{q | c)}} Implémentation du filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt; dont voici le squelette&lt;br /&gt;
&amp;lt;source lang=&amp;quot;Python&amp;quot;&amp;gt;&lt;br /&gt;
class FilterController:&lt;br /&gt;
&lt;br /&gt;
    def mfilter(self, e):&lt;br /&gt;
        xn = e&lt;br /&gt;
        # TODO&lt;br /&gt;
        return yn    &lt;br /&gt;
    &lt;br /&gt;
    def __init__(self, K_p, K_i, K_d, N, T_s, set_point):&lt;br /&gt;
        self.set_point = set_point&lt;br /&gt;
        # A COMPLÉTER&lt;br /&gt;
    &lt;br /&gt;
    def get_control(self, measurement, dt):&lt;br /&gt;
        e = self.set_point - measurement&lt;br /&gt;
        u = self.mfilter(e)&lt;br /&gt;
        return u&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{q | d)}} Appliquer ce contrôleur à la simulation d'asservissement de drone et vérifier qu'un comportement proche de celui de la partie précédente (PID numérique &amp;quot;classique&amp;quot;) est obtenu.&lt;br /&gt;
&lt;br /&gt;
{{q | e)}} Implémenter le filtre obtenu à l'aide de la transformée bilinéaire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Archive : codage de bloc Gnuradio en C++ ===&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;br /&gt;
--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21090</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21090"/>
				<updated>2026-06-01T13:00:58Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* PID numérique avec un filtre numérique linéaire */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
Dans les deux cas, un système temps réel sera considéré :&lt;br /&gt;
* à intervalles de temps (réguliers ou non), une valeur ''x(n)'' rentre dans le système&lt;br /&gt;
* le travail consiste à calculer ''y(n)'' avec l'équation au différences du filtre, à partir de la valeur ''x(n)'' et de ses versions précédentes ''x(n-1)'' et ''x(n-2)'' (et aussi ''y(n-1)'', ''y(n-2)'') qu'il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de ''temps réel'' implique que ''y(n)'' doit être calculer avant qu'une nouvelle valeurs de ''x(n)'' ne rentre dans le système.&lt;br /&gt;
&lt;br /&gt;
=== Bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
Nous allons implémenter un filtre IIR dans gnuradio, en écrivant le traitement dans un bloc Python.&lt;br /&gt;
&lt;br /&gt;
==== Filtre moyenneur====&lt;br /&gt;
&lt;br /&gt;
{{q| a)}} Dans un premier temps, prendre connaissance du tutoriel suivant : [https://wiki.gnuradio.org/index.php?title=Creating_Your_First_Block wiki Gnuradio - ''Creating Your First Block'']&lt;br /&gt;
&lt;br /&gt;
{{q| b)}} Nous allons écrire un filtre simple, qui implémente un simple moyenneur :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;Python&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
from gnuradio import gr&lt;br /&gt;
&lt;br /&gt;
class blk(gr.sync_block):  &lt;br /&gt;
    def __init__(self):  # Pas de paramètres&lt;br /&gt;
        gr.sync_block.__init__(&lt;br /&gt;
            self,&lt;br /&gt;
            name=&amp;quot;Filtre moyenneur&amp;quot;,  &lt;br /&gt;
            in_sig=[np.float32],&lt;br /&gt;
            out_sig=[np.float32]&lt;br /&gt;
        )&lt;br /&gt;
        self.xn1 = 0 # initialisation d'un attribut pour stocker x(n-1)&lt;br /&gt;
&lt;br /&gt;
    def work(self, input_items, output_items):&lt;br /&gt;
        xn = input_items[0][0] # On ne &amp;quot;consomme&amp;quot; qu'un seul échantillon en entrée&lt;br /&gt;
        yn = (xn + self.xn1) / 2&lt;br /&gt;
        self.xn1 = xn&lt;br /&gt;
        output_items[0][0] = yn # On ne produit donc également qu'un seul échantillon en sortie&lt;br /&gt;
        return 1 # On retourne le nombre de valeurs consomées&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Filtre IIR : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc Python dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;np.float32&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;np.float32&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in[0][0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
&lt;br /&gt;
{{q| a)}}  Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au [[Cours:Elen4_TNS_TP_TraitAudioEtDemodulation|TP 5]].&lt;br /&gt;
&lt;br /&gt;
{{q| b)}}  Modifier votre code pour implémenter le filtre complet de démodulation.&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
Cette partie sera travaillée dans un notebook Jupyter.&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique, la sortie du controleur PID ''u(t)'' est donnée par:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
On considère que le temps est discrétisé : ''t = n.''d''t'' où d''t'' est l'intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée &amp;lt;br/&amp;gt;[[Fichier:PIDderivative.png|400px]] [[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
** La dérivée est calculée par ''D = (e(n)-e(n-1))/''d''t''&lt;br /&gt;
** L'intégrale est approximée en cumulant progressivement : ''I = I + e(n).''d''t''&lt;br /&gt;
C'est ainsi que vous avez implémenté vos PID jusqu'ici.&lt;br /&gt;
&lt;br /&gt;
Voici un notebook exemple à explorer sur deux modélisations : asservissement de 1) température et de 2) position ''z'' d'un drone : [[Media:TNS TP6 starter.ipynb.zip|TNS_TP6_starter.ipynb.zip]]&lt;br /&gt;
&lt;br /&gt;
{{q | a)}} ''Ki = Kd = 0'' =&amp;gt; chercher le meilleur ''Kp'' =&amp;gt; erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | b)}} ''Kd = 0'' =&amp;gt; l'introduction du terme integral permet de corriger cette erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | c)}} Le terme dérivatif n'est pas nécessaire pour la température&lt;br /&gt;
&lt;br /&gt;
{{q | d)}} Mais l'est pour asservir la position ''z'' du drone.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique avec un filtre numérique linéaire ====&lt;br /&gt;
&lt;br /&gt;
Nous allons reprendre le PID, par sa fonction de transfert qui exprime un filtre linéaire continu, et construire un filtre linéaire numérique qui l'approxime.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{q | a)}} Cherchons la fonction de transfert du filtre continu d'un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l'équation différentielle&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:EqPID.png|500px]]&lt;br /&gt;
&amp;lt;br/&amp;gt;On applique la transformée de Laplace (dérivée =&amp;gt; multiplication par ''s'' ; intégrale =&amp;gt; division par ''s'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPID.png|130]]&lt;br /&gt;
&amp;lt;br/&amp;gt;Le terme dérivatif étant très sensible au bruit, on lui applique généralement un filtre passe bas (''w0/(w0+s)'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
&lt;br /&gt;
{{q | b)}} Il s'agit maintenant de transformer la variable ''s'' en une variable ''z'' :&lt;br /&gt;
* par transformée bilinéaire : &amp;lt;br/&amp;gt; ''s = (2/Ts)*(z-1)/(z+1)'' (voir le cours)&lt;br /&gt;
* ou par ''backward euler'' (version un peu plus simple) : &amp;lt;br/&amp;gt;''s = (z-1)/(Ts*z)''.&lt;br /&gt;
&lt;br /&gt;
En injectant le changement de variable dans la fonction de transfert ''H(s)'', obtenir la fonction de transfert ''H(z)'' du filtre linéaire numérique correspondant (dans un premier temps avec ''backward Euler'') :&lt;br /&gt;
* soit &amp;quot;à la main&amp;quot;&lt;br /&gt;
* ou en exploitant [https://www.sympy.org/en/index.html Sympy] (calcul symbolique). Un début :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;Python&amp;quot;&amp;gt;&lt;br /&gt;
import sympy&lt;br /&gt;
from sympy import symbols, Poly, Eq&lt;br /&gt;
Ki, Kd, Kp, N, Ts, z, s = symbols('K_i K_d K_p N T_s z s')&lt;br /&gt;
&lt;br /&gt;
Hs = Kp + (Ki/s)  + Kd*s * (N/(N+s))&lt;br /&gt;
&lt;br /&gt;
Hz = Hs.subs(s, (z-1)/(Ts*z))&lt;br /&gt;
&lt;br /&gt;
# ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans les deux cas, il sera nécessaire d'obtenir ''H(z)'' sous la forme d'une fraction rationnelle.&lt;br /&gt;
&lt;br /&gt;
{{q | c)}} Implémentation du filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt; dont voici le squelette&lt;br /&gt;
&amp;lt;source lang=&amp;quot;Python&amp;quot;&amp;gt;&lt;br /&gt;
class FilterController:&lt;br /&gt;
&lt;br /&gt;
    def mfilter(self, e):&lt;br /&gt;
        xn = e&lt;br /&gt;
        # TODO&lt;br /&gt;
        return yn    &lt;br /&gt;
    &lt;br /&gt;
    def __init__(self, K_p, K_i, K_d, N, T_s, set_point):&lt;br /&gt;
        self.set_point = set_point&lt;br /&gt;
        # A COMPLÉTER&lt;br /&gt;
    &lt;br /&gt;
    def get_control(self, measurement, dt):&lt;br /&gt;
        e = self.set_point - measurement&lt;br /&gt;
        u = self.mfilter(e)&lt;br /&gt;
        return u&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{q | d)}} Appliquer ce contrôleur à la simulation d'asservissement de drone et vérifier qu'un comportement proche de celui de la partie précédente (PID numérique &amp;quot;classique&amp;quot;) est obtenu.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Archive : codage de bloc Gnuradio en C++ ===&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;br /&gt;
--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21089</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21089"/>
				<updated>2026-06-01T13:00:35Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* PID numérique avec un filtre numérique linéaire */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
Dans les deux cas, un système temps réel sera considéré :&lt;br /&gt;
* à intervalles de temps (réguliers ou non), une valeur ''x(n)'' rentre dans le système&lt;br /&gt;
* le travail consiste à calculer ''y(n)'' avec l'équation au différences du filtre, à partir de la valeur ''x(n)'' et de ses versions précédentes ''x(n-1)'' et ''x(n-2)'' (et aussi ''y(n-1)'', ''y(n-2)'') qu'il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de ''temps réel'' implique que ''y(n)'' doit être calculer avant qu'une nouvelle valeurs de ''x(n)'' ne rentre dans le système.&lt;br /&gt;
&lt;br /&gt;
=== Bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
Nous allons implémenter un filtre IIR dans gnuradio, en écrivant le traitement dans un bloc Python.&lt;br /&gt;
&lt;br /&gt;
==== Filtre moyenneur====&lt;br /&gt;
&lt;br /&gt;
{{q| a)}} Dans un premier temps, prendre connaissance du tutoriel suivant : [https://wiki.gnuradio.org/index.php?title=Creating_Your_First_Block wiki Gnuradio - ''Creating Your First Block'']&lt;br /&gt;
&lt;br /&gt;
{{q| b)}} Nous allons écrire un filtre simple, qui implémente un simple moyenneur :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;Python&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
from gnuradio import gr&lt;br /&gt;
&lt;br /&gt;
class blk(gr.sync_block):  &lt;br /&gt;
    def __init__(self):  # Pas de paramètres&lt;br /&gt;
        gr.sync_block.__init__(&lt;br /&gt;
            self,&lt;br /&gt;
            name=&amp;quot;Filtre moyenneur&amp;quot;,  &lt;br /&gt;
            in_sig=[np.float32],&lt;br /&gt;
            out_sig=[np.float32]&lt;br /&gt;
        )&lt;br /&gt;
        self.xn1 = 0 # initialisation d'un attribut pour stocker x(n-1)&lt;br /&gt;
&lt;br /&gt;
    def work(self, input_items, output_items):&lt;br /&gt;
        xn = input_items[0][0] # On ne &amp;quot;consomme&amp;quot; qu'un seul échantillon en entrée&lt;br /&gt;
        yn = (xn + self.xn1) / 2&lt;br /&gt;
        self.xn1 = xn&lt;br /&gt;
        output_items[0][0] = yn # On ne produit donc également qu'un seul échantillon en sortie&lt;br /&gt;
        return 1 # On retourne le nombre de valeurs consomées&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Filtre IIR : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc Python dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;np.float32&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;np.float32&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in[0][0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
&lt;br /&gt;
{{q| a)}}  Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au [[Cours:Elen4_TNS_TP_TraitAudioEtDemodulation|TP 5]].&lt;br /&gt;
&lt;br /&gt;
{{q| b)}}  Modifier votre code pour implémenter le filtre complet de démodulation.&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
Cette partie sera travaillée dans un notebook Jupyter.&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique, la sortie du controleur PID ''u(t)'' est donnée par:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
On considère que le temps est discrétisé : ''t = n.''d''t'' où d''t'' est l'intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée &amp;lt;br/&amp;gt;[[Fichier:PIDderivative.png|400px]] [[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
** La dérivée est calculée par ''D = (e(n)-e(n-1))/''d''t''&lt;br /&gt;
** L'intégrale est approximée en cumulant progressivement : ''I = I + e(n).''d''t''&lt;br /&gt;
C'est ainsi que vous avez implémenté vos PID jusqu'ici.&lt;br /&gt;
&lt;br /&gt;
Voici un notebook exemple à explorer sur deux modélisations : asservissement de 1) température et de 2) position ''z'' d'un drone : [[Media:TNS TP6 starter.ipynb.zip|TNS_TP6_starter.ipynb.zip]]&lt;br /&gt;
&lt;br /&gt;
{{q | a)}} ''Ki = Kd = 0'' =&amp;gt; chercher le meilleur ''Kp'' =&amp;gt; erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | b)}} ''Kd = 0'' =&amp;gt; l'introduction du terme integral permet de corriger cette erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | c)}} Le terme dérivatif n'est pas nécessaire pour la température&lt;br /&gt;
&lt;br /&gt;
{{q | d)}} Mais l'est pour asservir la position ''z'' du drone.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique avec un filtre numérique linéaire ====&lt;br /&gt;
&lt;br /&gt;
Nous allons reprendre le PID, par sa fonction de transfert qui exprime un filtre linéaire continu, et construire un filtre linéaire numérique qui l'approxime.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{q | a)}} Cherchons la fonction de transfert du filtre continu d'un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l'équation différentielle&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:EqPID.png|500px]]&lt;br /&gt;
&amp;lt;br/&amp;gt;On applique la transformée de Laplace (dérivée =&amp;gt; multiplication par ''s'' ; intégrale =&amp;gt; division par ''s'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPID.png|130]]&lt;br /&gt;
&amp;lt;br/&amp;gt;Le terme dérivatif étant très sensible au bruit, on lui applique généralement un filtre passe bas (''w0/(w0+s)'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
&lt;br /&gt;
{{q | b)}} Il s'agit maintenant de transformer la variable ''s'' en une variable ''z'' :&lt;br /&gt;
* par transformée bilinéaire : &amp;lt;br/&amp;gt; ''s = (2/Ts)*(z-1)/(z+1)'' (voir le cours)&lt;br /&gt;
* ou par ''backward euler'' (version un peu plus simple) : &amp;lt;br/&amp;gt;''s = (z-1)/(Ts*z)''.&lt;br /&gt;
&lt;br /&gt;
En injectant le changement de variable dans la fonction de transfert ''H(s)'', obtenir la fonction de transfert ''H(z)'' du filtre linéaire numérique correspondant (dans un premier temps avec ''backward Euler'') :&lt;br /&gt;
* soit &amp;quot;à la main&amp;quot;&lt;br /&gt;
* ou en exploitant [https://www.sympy.org/en/index.html Sympy] (calcul symbolique). Un début :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;Python&amp;quot;&amp;gt;&lt;br /&gt;
import sympy&lt;br /&gt;
from sympy import symbols, Poly, Eq&lt;br /&gt;
Ki, Kd, Kp, N, Ts, z, s = symbols('K_i K_d K_p N T_s z s')&lt;br /&gt;
&lt;br /&gt;
Hs = Kp + (Ki/s)  + Kd*s * (N/(N+s))&lt;br /&gt;
&lt;br /&gt;
Hz = Hs.subs(s, (z-1)/(Ts*z))&lt;br /&gt;
&lt;br /&gt;
# ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans les deux cas, il sera nécessaire d'obtenir ''H(z)'' sous la forme d'une fraction rationnelle.&lt;br /&gt;
&lt;br /&gt;
{{q | c)}} Implémentation du filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt; dont voici le squelette&lt;br /&gt;
&amp;lt;source lang=&amp;quot;Python&amp;quot;&amp;gt;&lt;br /&gt;
class FilterController:&lt;br /&gt;
&lt;br /&gt;
    def mfilter(self, e):&lt;br /&gt;
        xn = e&lt;br /&gt;
        # TODO&lt;br /&gt;
        return yn    &lt;br /&gt;
    &lt;br /&gt;
    def __init__(self, K_p, K_i, K_d, N, T_s, set_point):&lt;br /&gt;
        self.set_point = set_point&lt;br /&gt;
        # A COMPLÉTER&lt;br /&gt;
    &lt;br /&gt;
    def get_control(self, measurement, dt):&lt;br /&gt;
        e = self.set_point - measurement&lt;br /&gt;
        u = self.mfilter(e)&lt;br /&gt;
        return u&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{q | d)}} Appliquer ce contrôleur à la simulation d'asservissement de drone et vérifier qu'un comportement proche de celui de la partie précédente est obtenu.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Archive : codage de bloc Gnuradio en C++ ===&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;br /&gt;
--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21088</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21088"/>
				<updated>2026-06-01T13:00:17Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* PID numérique avec un filtre numérique linéaire */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
Dans les deux cas, un système temps réel sera considéré :&lt;br /&gt;
* à intervalles de temps (réguliers ou non), une valeur ''x(n)'' rentre dans le système&lt;br /&gt;
* le travail consiste à calculer ''y(n)'' avec l'équation au différences du filtre, à partir de la valeur ''x(n)'' et de ses versions précédentes ''x(n-1)'' et ''x(n-2)'' (et aussi ''y(n-1)'', ''y(n-2)'') qu'il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de ''temps réel'' implique que ''y(n)'' doit être calculer avant qu'une nouvelle valeurs de ''x(n)'' ne rentre dans le système.&lt;br /&gt;
&lt;br /&gt;
=== Bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
Nous allons implémenter un filtre IIR dans gnuradio, en écrivant le traitement dans un bloc Python.&lt;br /&gt;
&lt;br /&gt;
==== Filtre moyenneur====&lt;br /&gt;
&lt;br /&gt;
{{q| a)}} Dans un premier temps, prendre connaissance du tutoriel suivant : [https://wiki.gnuradio.org/index.php?title=Creating_Your_First_Block wiki Gnuradio - ''Creating Your First Block'']&lt;br /&gt;
&lt;br /&gt;
{{q| b)}} Nous allons écrire un filtre simple, qui implémente un simple moyenneur :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;Python&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
from gnuradio import gr&lt;br /&gt;
&lt;br /&gt;
class blk(gr.sync_block):  &lt;br /&gt;
    def __init__(self):  # Pas de paramètres&lt;br /&gt;
        gr.sync_block.__init__(&lt;br /&gt;
            self,&lt;br /&gt;
            name=&amp;quot;Filtre moyenneur&amp;quot;,  &lt;br /&gt;
            in_sig=[np.float32],&lt;br /&gt;
            out_sig=[np.float32]&lt;br /&gt;
        )&lt;br /&gt;
        self.xn1 = 0 # initialisation d'un attribut pour stocker x(n-1)&lt;br /&gt;
&lt;br /&gt;
    def work(self, input_items, output_items):&lt;br /&gt;
        xn = input_items[0][0] # On ne &amp;quot;consomme&amp;quot; qu'un seul échantillon en entrée&lt;br /&gt;
        yn = (xn + self.xn1) / 2&lt;br /&gt;
        self.xn1 = xn&lt;br /&gt;
        output_items[0][0] = yn # On ne produit donc également qu'un seul échantillon en sortie&lt;br /&gt;
        return 1 # On retourne le nombre de valeurs consomées&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Filtre IIR : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc Python dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;np.float32&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;np.float32&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in[0][0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
&lt;br /&gt;
{{q| a)}}  Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au [[Cours:Elen4_TNS_TP_TraitAudioEtDemodulation|TP 5]].&lt;br /&gt;
&lt;br /&gt;
{{q| b)}}  Modifier votre code pour implémenter le filtre complet de démodulation.&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
Cette partie sera travaillée dans un notebook Jupyter.&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique, la sortie du controleur PID ''u(t)'' est donnée par:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
On considère que le temps est discrétisé : ''t = n.''d''t'' où d''t'' est l'intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée &amp;lt;br/&amp;gt;[[Fichier:PIDderivative.png|400px]] [[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
** La dérivée est calculée par ''D = (e(n)-e(n-1))/''d''t''&lt;br /&gt;
** L'intégrale est approximée en cumulant progressivement : ''I = I + e(n).''d''t''&lt;br /&gt;
C'est ainsi que vous avez implémenté vos PID jusqu'ici.&lt;br /&gt;
&lt;br /&gt;
Voici un notebook exemple à explorer sur deux modélisations : asservissement de 1) température et de 2) position ''z'' d'un drone : [[Media:TNS TP6 starter.ipynb.zip|TNS_TP6_starter.ipynb.zip]]&lt;br /&gt;
&lt;br /&gt;
{{q | a)}} ''Ki = Kd = 0'' =&amp;gt; chercher le meilleur ''Kp'' =&amp;gt; erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | b)}} ''Kd = 0'' =&amp;gt; l'introduction du terme integral permet de corriger cette erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | c)}} Le terme dérivatif n'est pas nécessaire pour la température&lt;br /&gt;
&lt;br /&gt;
{{q | d)}} Mais l'est pour asservir la position ''z'' du drone.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique avec un filtre numérique linéaire ====&lt;br /&gt;
&lt;br /&gt;
Nous allons reprendre le PID, par sa fonction de transfert qui exprime un filtre linéaire continu, et construire un filtre linéaire numérique qui l'approxime.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{q | a)}} Cherchons la fonction de transfert du filtre continu d'un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l'équation différentielle&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:EqPID.png|500px]]&lt;br /&gt;
&amp;lt;br/&amp;gt;On applique la transformée de Laplace (dérivée =&amp;gt; multiplication par ''s'' ; intégrale =&amp;gt; division par ''s'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPID.png|130]]&lt;br /&gt;
&amp;lt;br/&amp;gt;Le terme dérivatif étant très sensible au bruit, on lui applique généralement un filtre passe bas (''w0/(w0+s)'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
&lt;br /&gt;
{{q | b)}} Il s'agit maintenant de transformer la variable ''s'' en une variable ''z'' :&lt;br /&gt;
* par transformée bilinéaire : &amp;lt;br/&amp;gt; ''s = (2/Ts)*(z-1)/(z+1)'' (voir le cours)&lt;br /&gt;
* ou par ''backward euler'' (version un peu plus simple) : &amp;lt;br/&amp;gt;''s = (z-1)/(Ts*z)''.&lt;br /&gt;
&lt;br /&gt;
En injectant le changement de variable dans la fonction de transfert ''H(s)'', obtenir la fonction de transfert ''H(z)'' du filtre linéaire numérique correspondant (dans un premier temps avec ''backward Euler'') :&lt;br /&gt;
* soit &amp;quot;à la main&amp;quot;&lt;br /&gt;
* ou en exploitant [https://www.sympy.org/en/index.html Sympy] (calcul symbolique). Un début :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;Python&amp;quot;&amp;gt;&lt;br /&gt;
import sympy&lt;br /&gt;
from sympy import symbols, Poly, Eq&lt;br /&gt;
Ki, Kd, Kp, N, Ts, z, s = symbols('K_i K_d K_p N T_s z s')&lt;br /&gt;
&lt;br /&gt;
Hs = Kp + (Ki/s)  + Kd*s * (N/(N+s))&lt;br /&gt;
&lt;br /&gt;
Hz = Hs.subs(s, (z-1)/(Ts*z))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans les deux cas, il sera nécessaire d'obtenir ''H(z)'' sous la forme d'une fraction rationnelle.&lt;br /&gt;
&lt;br /&gt;
{{q | c)}} Implémentation du filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt; dont voici le squelette&lt;br /&gt;
&amp;lt;source lang=&amp;quot;Python&amp;quot;&amp;gt;&lt;br /&gt;
class FilterController:&lt;br /&gt;
&lt;br /&gt;
    def mfilter(self, e):&lt;br /&gt;
        xn = e&lt;br /&gt;
        # TODO&lt;br /&gt;
        return yn    &lt;br /&gt;
    &lt;br /&gt;
    def __init__(self, K_p, K_i, K_d, N, T_s, set_point):&lt;br /&gt;
        self.set_point = set_point&lt;br /&gt;
        # A COMPLÉTER&lt;br /&gt;
    &lt;br /&gt;
    def get_control(self, measurement, dt):&lt;br /&gt;
        e = self.set_point - measurement&lt;br /&gt;
        u = self.mfilter(e)&lt;br /&gt;
        return u&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{q | d)}} Appliquer ce contrôleur à la simulation d'asservissement de drone et vérifier qu'un comportement proche de celui de la partie précédente est obtenu.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Archive : codage de bloc Gnuradio en C++ ===&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;br /&gt;
--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21087</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21087"/>
				<updated>2026-06-01T10:18:16Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
Dans les deux cas, un système temps réel sera considéré :&lt;br /&gt;
* à intervalles de temps (réguliers ou non), une valeur ''x(n)'' rentre dans le système&lt;br /&gt;
* le travail consiste à calculer ''y(n)'' avec l'équation au différences du filtre, à partir de la valeur ''x(n)'' et de ses versions précédentes ''x(n-1)'' et ''x(n-2)'' (et aussi ''y(n-1)'', ''y(n-2)'') qu'il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de ''temps réel'' implique que ''y(n)'' doit être calculer avant qu'une nouvelle valeurs de ''x(n)'' ne rentre dans le système.&lt;br /&gt;
&lt;br /&gt;
=== Bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
Nous allons implémenter un filtre IIR dans gnuradio, en écrivant le traitement dans un bloc Python.&lt;br /&gt;
&lt;br /&gt;
==== Filtre moyenneur====&lt;br /&gt;
&lt;br /&gt;
{{q| a)}} Dans un premier temps, prendre connaissance du tutoriel suivant : [https://wiki.gnuradio.org/index.php?title=Creating_Your_First_Block wiki Gnuradio - ''Creating Your First Block'']&lt;br /&gt;
&lt;br /&gt;
{{q| b)}} Nous allons écrire un filtre simple, qui implémente un simple moyenneur :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;Python&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
from gnuradio import gr&lt;br /&gt;
&lt;br /&gt;
class blk(gr.sync_block):  &lt;br /&gt;
    def __init__(self):  # Pas de paramètres&lt;br /&gt;
        gr.sync_block.__init__(&lt;br /&gt;
            self,&lt;br /&gt;
            name=&amp;quot;Filtre moyenneur&amp;quot;,  &lt;br /&gt;
            in_sig=[np.float32],&lt;br /&gt;
            out_sig=[np.float32]&lt;br /&gt;
        )&lt;br /&gt;
        self.xn1 = 0 # initialisation d'un attribut pour stocker x(n-1)&lt;br /&gt;
&lt;br /&gt;
    def work(self, input_items, output_items):&lt;br /&gt;
        xn = input_items[0][0] # On ne &amp;quot;consomme&amp;quot; qu'un seul échantillon en entrée&lt;br /&gt;
        yn = (xn + self.xn1) / 2&lt;br /&gt;
        self.xn1 = xn&lt;br /&gt;
        output_items[0][0] = yn # On ne produit donc également qu'un seul échantillon en sortie&lt;br /&gt;
        return 1 # On retourne le nombre de valeurs consomées&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Filtre IIR : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc Python dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;np.float32&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;np.float32&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in[0][0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
&lt;br /&gt;
{{q| a)}}  Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au [[Cours:Elen4_TNS_TP_TraitAudioEtDemodulation|TP 5]].&lt;br /&gt;
&lt;br /&gt;
{{q| b)}}  Modifier votre code pour implémenter le filtre complet de démodulation.&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
Cette partie sera travaillée dans un notebook Jupyter.&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique, la sortie du controleur PID ''u(t)'' est donnée par:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
On considère que le temps est discrétisé : ''t = n.''d''t'' où d''t'' est l'intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée &amp;lt;br/&amp;gt;[[Fichier:PIDderivative.png|400px]] [[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
** La dérivée est calculée par ''D = (e(n)-e(n-1))/''d''t''&lt;br /&gt;
** L'intégrale est approximée en cumulant progressivement : ''I = I + e(n).''d''t''&lt;br /&gt;
C'est ainsi que vous avez implémenté vos PID jusqu'ici.&lt;br /&gt;
&lt;br /&gt;
Voici un notebook exemple à explorer sur deux modélisations : asservissement de 1) température et de 2) position ''z'' d'un drone : [[Media:TNS TP6 starter.ipynb.zip|TNS_TP6_starter.ipynb.zip]]&lt;br /&gt;
&lt;br /&gt;
{{q | a)}} ''Ki = Kd = 0'' =&amp;gt; chercher le meilleur ''Kp'' =&amp;gt; erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | b)}} ''Kd = 0'' =&amp;gt; l'introduction du terme integral permet de corriger cette erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | c)}} Le terme dérivatif n'est pas nécessaire pour la température&lt;br /&gt;
&lt;br /&gt;
{{q | d)}} Mais l'est pour asservir la position ''z'' du drone.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique avec un filtre numérique linéaire ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d'un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l'équation différentielle&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:EqPID.png|500px]]&lt;br /&gt;
&amp;lt;br/&amp;gt;On applique la transformée de Laplace (dérivée =&amp;gt; multiplication par ''s'' ; intégrale =&amp;gt; division par ''s'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPID.png|130]]&lt;br /&gt;
&amp;lt;br/&amp;gt;Le terme dérivatif étant très sensible au bruit, on lui applique généralement un filtre passe bas (''w0/(w0+s)'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Archive : codage de bloc Gnuradio en C++ ===&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;br /&gt;
--&amp;gt;&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21086</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21086"/>
				<updated>2026-06-01T10:16:51Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* PID numérique &amp;quot;classique&amp;quot; */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
Dans les deux cas, un système temps réel sera considéré :&lt;br /&gt;
* à intervalles de temps (réguliers ou non), une valeur ''x(n)'' rentre dans le système&lt;br /&gt;
* le travail consiste à calculer ''y(n)'' avec l'équation au différences du filtre, à partir de la valeur ''x(n)'' et de ses versions précédentes ''x(n-1)'' et ''x(n-2)'' (et aussi ''y(n-1)'', ''y(n-2)'') qu'il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de ''temps réel'' implique que ''y(n)'' doit être calculer avant qu'une nouvelle valeurs de ''x(n)'' ne rentre dans le système.&lt;br /&gt;
&lt;br /&gt;
=== Bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
Nous allons implémenter un filtre IIR dans gnuradio, en écrivant le traitement dans un bloc Python.&lt;br /&gt;
&lt;br /&gt;
==== Filtre moyenneur====&lt;br /&gt;
&lt;br /&gt;
{{q| a)}} Dans un premier temps, prendre connaissance du tutoriel suivant : [https://wiki.gnuradio.org/index.php?title=Creating_Your_First_Block wiki Gnuradio - ''Creating Your First Block'']&lt;br /&gt;
&lt;br /&gt;
{{q| b)}} Nous allons écrire un filtre simple, qui implémente un simple moyenneur :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;Python&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
from gnuradio import gr&lt;br /&gt;
&lt;br /&gt;
class blk(gr.sync_block):  &lt;br /&gt;
    def __init__(self):  # Pas de paramètres&lt;br /&gt;
        gr.sync_block.__init__(&lt;br /&gt;
            self,&lt;br /&gt;
            name=&amp;quot;Filtre moyenneur&amp;quot;,  &lt;br /&gt;
            in_sig=[np.float32],&lt;br /&gt;
            out_sig=[np.float32]&lt;br /&gt;
        )&lt;br /&gt;
        self.xn1 = 0 # initialisation d'un attribut pour stocker x(n-1)&lt;br /&gt;
&lt;br /&gt;
    def work(self, input_items, output_items):&lt;br /&gt;
        xn = input_items[0][0] # On ne &amp;quot;consomme&amp;quot; qu'un seul échantillon en entrée&lt;br /&gt;
        yn = (xn + self.xn1) / 2&lt;br /&gt;
        self.xn1 = xn&lt;br /&gt;
        output_items[0][0] = yn # On ne produit donc également qu'un seul échantillon en sortie&lt;br /&gt;
        return 1 # On retourne le nombre de valeurs consomées&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Filtre IIR : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc Python dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;np.float32&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;np.float32&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in[0][0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
&lt;br /&gt;
{{q| a)}}  Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au [[Cours:Elen4_TNS_TP_TraitAudioEtDemodulation|TP 5]].&lt;br /&gt;
&lt;br /&gt;
{{q| b)}}  Modifier votre code pour implémenter le filtre complet de démodulation.&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
Cette partie sera travaillée dans un notebook Jupyter.&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique, la sortie du controleur PID ''u(t)'' est donnée par:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
On considère que le temps est discrétisé : ''t = n.''d''t'' où d''t'' est l'intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée &amp;lt;br/&amp;gt;[[Fichier:PIDderivative.png|400px]] [[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
** La dérivée est calculée par ''D = (e(n)-e(n-1))/''d''t''&lt;br /&gt;
** L'intégrale est approximée en cumulant progressivement : ''I = I + e(n).''d''t''&lt;br /&gt;
C'est ainsi que vous avez implémenté vos PID jusqu'ici.&lt;br /&gt;
&lt;br /&gt;
Voici un notebook exemple à explorer sur deux modélisations : asservissement de 1) température et de 2) position ''z'' d'un drone : [[Media:TNS TP6 starter.ipynb.zip|TNS_TP6_starter.ipynb.zip]]&lt;br /&gt;
&lt;br /&gt;
{{q | a)}} ''Ki = Kd = 0'' =&amp;gt; chercher le meilleur ''Kp'' =&amp;gt; erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | b)}} ''Kd = 0'' =&amp;gt; l'introduction du terme integral permet de corriger cette erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | c)}} Le terme dérivatif n'est pas nécessaire pour la température&lt;br /&gt;
&lt;br /&gt;
{{q | d)}} Mais l'est pour asservir la position ''z'' du drone.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique avec un filtre numérique linéaire ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d'un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l'équation différentielle&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:EqPID.png|500px]]&lt;br /&gt;
&amp;lt;br/&amp;gt;On applique la transformée de Laplace (dérivée =&amp;gt; multiplication par ''s'' ; intégrale =&amp;gt; division par ''s'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPID.png|130]]&lt;br /&gt;
&amp;lt;br/&amp;gt;Le terme dérivatif étant très sensible au bruit, on lui applique généralement un filtre passe bas (''w0/(w0+s)'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;br /&gt;
&lt;br /&gt;
=== Archive : codage de bloc Gnuradio en C++ ===&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21085</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21085"/>
				<updated>2026-06-01T10:15:41Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
Dans les deux cas, un système temps réel sera considéré :&lt;br /&gt;
* à intervalles de temps (réguliers ou non), une valeur ''x(n)'' rentre dans le système&lt;br /&gt;
* le travail consiste à calculer ''y(n)'' avec l'équation au différences du filtre, à partir de la valeur ''x(n)'' et de ses versions précédentes ''x(n-1)'' et ''x(n-2)'' (et aussi ''y(n-1)'', ''y(n-2)'') qu'il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de ''temps réel'' implique que ''y(n)'' doit être calculer avant qu'une nouvelle valeurs de ''x(n)'' ne rentre dans le système.&lt;br /&gt;
&lt;br /&gt;
=== Bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
Nous allons implémenter un filtre IIR dans gnuradio, en écrivant le traitement dans un bloc Python.&lt;br /&gt;
&lt;br /&gt;
==== Filtre moyenneur====&lt;br /&gt;
&lt;br /&gt;
{{q| a)}} Dans un premier temps, prendre connaissance du tutoriel suivant : [https://wiki.gnuradio.org/index.php?title=Creating_Your_First_Block wiki Gnuradio - ''Creating Your First Block'']&lt;br /&gt;
&lt;br /&gt;
{{q| b)}} Nous allons écrire un filtre simple, qui implémente un simple moyenneur :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;Python&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
from gnuradio import gr&lt;br /&gt;
&lt;br /&gt;
class blk(gr.sync_block):  &lt;br /&gt;
    def __init__(self):  # Pas de paramètres&lt;br /&gt;
        gr.sync_block.__init__(&lt;br /&gt;
            self,&lt;br /&gt;
            name=&amp;quot;Filtre moyenneur&amp;quot;,  &lt;br /&gt;
            in_sig=[np.float32],&lt;br /&gt;
            out_sig=[np.float32]&lt;br /&gt;
        )&lt;br /&gt;
        self.xn1 = 0 # initialisation d'un attribut pour stocker x(n-1)&lt;br /&gt;
&lt;br /&gt;
    def work(self, input_items, output_items):&lt;br /&gt;
        xn = input_items[0][0] # On ne &amp;quot;consomme&amp;quot; qu'un seul échantillon en entrée&lt;br /&gt;
        yn = (xn + self.xn1) / 2&lt;br /&gt;
        self.xn1 = xn&lt;br /&gt;
        output_items[0][0] = yn # On ne produit donc également qu'un seul échantillon en sortie&lt;br /&gt;
        return 1 # On retourne le nombre de valeurs consomées&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Filtre IIR : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc Python dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;np.float32&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;np.float32&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in[0][0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
&lt;br /&gt;
{{q| a)}}  Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au [[Cours:Elen4_TNS_TP_TraitAudioEtDemodulation|TP 5]].&lt;br /&gt;
&lt;br /&gt;
{{q| b)}}  Modifier votre code pour implémenter le filtre complet de démodulation.&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
Cette partie sera travaillée dans un notebook Jupyter.&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique, la sortie du controleur PID ''u(t)'' est donnée par:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
On considère que le temps est discrétisé : ''t = n.''d''t'' où d''t'' est l'intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée &amp;lt;br/&amp;gt;[[Fichier:PIDderivative.png|400px]] [[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
** La dérivée est calculée par ''D = (e(n)-e(n-1))/''d''t''&lt;br /&gt;
** L'intégrale est approximée en cumulant progressivement : ''I = I + e(n).''d''t''&lt;br /&gt;
C'est ainsi que vous avez implémenté vos PID jusqu'ici.&lt;br /&gt;
&lt;br /&gt;
Voici un notebook exemple à explorer sur deux modélisations : asservissement de 1) température et de 2) position ''z'' d'un drone : [[Media:TNS TP6 starter.ipynb.zip]]&lt;br /&gt;
&lt;br /&gt;
{{q | a)}} ''Ki = Kd = 0'' =&amp;gt; chercher le meilleur ''Kp'' =&amp;gt; erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | b)}} ''Kd = 0'' =&amp;gt; l'introduction du terme integral permet de corriger cette erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | c)}} Le terme dérivatif n'est pas nécessaire pour la température&lt;br /&gt;
&lt;br /&gt;
{{q | d)}} Mais l'est pour asservir la position ''z'' du drone.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique avec un filtre numérique linéaire ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d'un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l'équation différentielle&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:EqPID.png|500px]]&lt;br /&gt;
&amp;lt;br/&amp;gt;On applique la transformée de Laplace (dérivée =&amp;gt; multiplication par ''s'' ; intégrale =&amp;gt; division par ''s'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPID.png|130]]&lt;br /&gt;
&amp;lt;br/&amp;gt;Le terme dérivatif étant très sensible au bruit, on lui applique généralement un filtre passe bas (''w0/(w0+s)'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;br /&gt;
&lt;br /&gt;
=== Archive : codage de bloc Gnuradio en C++ ===&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Fichier:TNS_TP6_starter.ipynb.zip&amp;diff=21084</id>
		<title>Fichier:TNS TP6 starter.ipynb.zip</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Fichier:TNS_TP6_starter.ipynb.zip&amp;diff=21084"/>
				<updated>2026-06-01T10:14:06Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21083</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21083"/>
				<updated>2026-06-01T10:11:27Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* PID numérique &amp;quot;classique&amp;quot; */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
Dans les deux cas, un système temps réel sera considéré :&lt;br /&gt;
* à intervalles de temps (réguliers ou non), une valeur ''x(n)'' rentre dans le système&lt;br /&gt;
* le travail consiste à calculer ''y(n)'' avec l'équation au différences du filtre, à partir de la valeur ''x(n)'' et de ses versions précédentes ''x(n-1)'' et ''x(n-2)'' (et aussi ''y(n-1)'', ''y(n-2)'') qu'il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de ''temps réel'' implique que ''y(n)'' doit être calculer avant qu'une nouvelle valeurs de ''x(n)'' ne rentre dans le système.&lt;br /&gt;
&lt;br /&gt;
=== Bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
Nous allons implémenter un filtre IIR dans gnuradio, en écrivant le traitement dans un bloc Python.&lt;br /&gt;
&lt;br /&gt;
==== Filtre moyenneur====&lt;br /&gt;
&lt;br /&gt;
{{q| a)}} Dans un premier temps, prendre connaissance du tutoriel suivant : [https://wiki.gnuradio.org/index.php?title=Creating_Your_First_Block wiki Gnuradio - ''Creating Your First Block'']&lt;br /&gt;
&lt;br /&gt;
{{q| b)}} Nous allons écrire un filtre simple, qui implémente un simple moyenneur :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;Python&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
from gnuradio import gr&lt;br /&gt;
&lt;br /&gt;
class blk(gr.sync_block):  &lt;br /&gt;
    def __init__(self):  # Pas de paramètres&lt;br /&gt;
        gr.sync_block.__init__(&lt;br /&gt;
            self,&lt;br /&gt;
            name=&amp;quot;Filtre moyenneur&amp;quot;,  &lt;br /&gt;
            in_sig=[np.float32],&lt;br /&gt;
            out_sig=[np.float32]&lt;br /&gt;
        )&lt;br /&gt;
        self.xn1 = 0 # initialisation d'un attribut pour stocker x(n-1)&lt;br /&gt;
&lt;br /&gt;
    def work(self, input_items, output_items):&lt;br /&gt;
        xn = input_items[0][0] # On ne &amp;quot;consomme&amp;quot; qu'un seul échantillon en entrée&lt;br /&gt;
        yn = (xn + self.xn1) / 2&lt;br /&gt;
        self.xn1 = xn&lt;br /&gt;
        output_items[0][0] = yn # On ne produit donc également qu'un seul échantillon en sortie&lt;br /&gt;
        return 1 # On retourne le nombre de valeurs consomées&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Filtre IIR : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc Python dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;np.float32&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;np.float32&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in[0][0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
&lt;br /&gt;
{{q| a)}}  Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au [[Cours:Elen4_TNS_TP_TraitAudioEtDemodulation|TP 5]].&lt;br /&gt;
&lt;br /&gt;
{{q| b)}}  Modifier votre code pour implémenter le filtre complet de démodulation.&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
Cette partie sera travaillée dans un notebook Jupyter.&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique, la sortie du controleur PID ''u(t)'' est donnée par:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
On considère que le temps est discrétisé : ''t = n.''d''t'' où d''t'' est l'intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée &amp;lt;br/&amp;gt;[[Fichier:PIDderivative.png|400px]] [[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
** La dérivée est calculée par ''D = (e(n)-e(n-1))/''d''t''&lt;br /&gt;
** L'intégrale est approximée en cumulant progressivement : ''I = I + e(n).''d''t''&lt;br /&gt;
C'est ainsi que vous avez implémenté vos PID jusqu'ici.&lt;br /&gt;
&lt;br /&gt;
Voici un notebook exemple à explorer sur deux modélisations : asservissement de 1) température et de 2) position ''z'' d'un drone.&lt;br /&gt;
&lt;br /&gt;
{{q | a)}} ''Ki = Kd = 0'' =&amp;gt; chercher le meilleur ''Kp'' =&amp;gt; erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | b)}} ''Kd = 0'' =&amp;gt; l'introduction du terme integral permet de corriger cette erreur statique.&lt;br /&gt;
&lt;br /&gt;
{{q | c)}} Le terme dérivatif n'est pas nécessaire pour la température&lt;br /&gt;
&lt;br /&gt;
{{q | d)}} Mais l'est pour asservir la position ''z'' du drone.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique avec un filtre numérique linéaire ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d'un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l'équation différentielle&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:EqPID.png|500px]]&lt;br /&gt;
&amp;lt;br/&amp;gt;On applique la transformée de Laplace (dérivée =&amp;gt; multiplication par ''s'' ; intégrale =&amp;gt; division par ''s'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPID.png|130]]&lt;br /&gt;
&amp;lt;br/&amp;gt;Le terme dérivatif étant très sensible au bruit, on lui applique généralement un filtre passe bas (''w0/(w0+s)'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;br /&gt;
&lt;br /&gt;
=== Archive : codage de bloc Gnuradio en C++ ===&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21082</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21082"/>
				<updated>2026-06-01T10:10:21Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* PID numérique par approximation d'un filtre continu */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
Dans les deux cas, un système temps réel sera considéré :&lt;br /&gt;
* à intervalles de temps (réguliers ou non), une valeur ''x(n)'' rentre dans le système&lt;br /&gt;
* le travail consiste à calculer ''y(n)'' avec l'équation au différences du filtre, à partir de la valeur ''x(n)'' et de ses versions précédentes ''x(n-1)'' et ''x(n-2)'' (et aussi ''y(n-1)'', ''y(n-2)'') qu'il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de ''temps réel'' implique que ''y(n)'' doit être calculer avant qu'une nouvelle valeurs de ''x(n)'' ne rentre dans le système.&lt;br /&gt;
&lt;br /&gt;
=== Bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
Nous allons implémenter un filtre IIR dans gnuradio, en écrivant le traitement dans un bloc Python.&lt;br /&gt;
&lt;br /&gt;
==== Filtre moyenneur====&lt;br /&gt;
&lt;br /&gt;
{{q| a)}} Dans un premier temps, prendre connaissance du tutoriel suivant : [https://wiki.gnuradio.org/index.php?title=Creating_Your_First_Block wiki Gnuradio - ''Creating Your First Block'']&lt;br /&gt;
&lt;br /&gt;
{{q| b)}} Nous allons écrire un filtre simple, qui implémente un simple moyenneur :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;Python&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
from gnuradio import gr&lt;br /&gt;
&lt;br /&gt;
class blk(gr.sync_block):  &lt;br /&gt;
    def __init__(self):  # Pas de paramètres&lt;br /&gt;
        gr.sync_block.__init__(&lt;br /&gt;
            self,&lt;br /&gt;
            name=&amp;quot;Filtre moyenneur&amp;quot;,  &lt;br /&gt;
            in_sig=[np.float32],&lt;br /&gt;
            out_sig=[np.float32]&lt;br /&gt;
        )&lt;br /&gt;
        self.xn1 = 0 # initialisation d'un attribut pour stocker x(n-1)&lt;br /&gt;
&lt;br /&gt;
    def work(self, input_items, output_items):&lt;br /&gt;
        xn = input_items[0][0] # On ne &amp;quot;consomme&amp;quot; qu'un seul échantillon en entrée&lt;br /&gt;
        yn = (xn + self.xn1) / 2&lt;br /&gt;
        self.xn1 = xn&lt;br /&gt;
        output_items[0][0] = yn # On ne produit donc également qu'un seul échantillon en sortie&lt;br /&gt;
        return 1 # On retourne le nombre de valeurs consomées&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Filtre IIR : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc Python dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;np.float32&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;np.float32&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in[0][0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
&lt;br /&gt;
{{q| a)}}  Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au [[Cours:Elen4_TNS_TP_TraitAudioEtDemodulation|TP 5]].&lt;br /&gt;
&lt;br /&gt;
{{q| b)}}  Modifier votre code pour implémenter le filtre complet de démodulation.&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
Cette partie sera travaillée dans un notebook Jupyter.&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique, la sortie du controleur PID ''u(t)'' est donnée par:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
On considère que le temps est discrétisé : ''t = n.''d''t'' où d''t'' est l'intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée &amp;lt;br/&amp;gt;[[Fichier:PIDderivative.png|400px]] [[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
** La dérivée est calculée par ''D = (e(n)-e(n-1))/''d''t''&lt;br /&gt;
** L'intégrale est approximée en cumulant progressivement : ''I = I + e(n).''d''t''&lt;br /&gt;
C'est ainsi que vous avez implémenté vos PID jusqu'ici.&lt;br /&gt;
&lt;br /&gt;
Voici un notebook exemple à explorer sur deux modélisations : asservissement de 1) température et de 2) position ''z'' d'un drone.&lt;br /&gt;
&lt;br /&gt;
{{q | a}} ''Ki = Kd = 0'' =&amp;gt; chercher le meilleur ''Kp'' =&amp;gt; erreur statique.&lt;br /&gt;
{{q | b}} ''Kd = 0'' =&amp;gt; l'introduction du terme integral permet de corriger cette erreur statique.&lt;br /&gt;
{{q | c}} Le terme dérivatif n'est pas nécessaire pour la température&lt;br /&gt;
{{q | d}} Mais l'est pour asservir la position ''z'' du drone.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique avec un filtre numérique linéaire ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d'un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l'équation différentielle&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:EqPID.png|500px]]&lt;br /&gt;
&amp;lt;br/&amp;gt;On applique la transformée de Laplace (dérivée =&amp;gt; multiplication par ''s'' ; intégrale =&amp;gt; division par ''s'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPID.png|130]]&lt;br /&gt;
&amp;lt;br/&amp;gt;Le terme dérivatif étant très sensible au bruit, on lui applique généralement un filtre passe bas (''w0/(w0+s)'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;br /&gt;
&lt;br /&gt;
=== Archive : codage de bloc Gnuradio en C++ ===&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21081</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21081"/>
				<updated>2026-06-01T10:09:46Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* PID numérique &amp;quot;classique&amp;quot; */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
Dans les deux cas, un système temps réel sera considéré :&lt;br /&gt;
* à intervalles de temps (réguliers ou non), une valeur ''x(n)'' rentre dans le système&lt;br /&gt;
* le travail consiste à calculer ''y(n)'' avec l'équation au différences du filtre, à partir de la valeur ''x(n)'' et de ses versions précédentes ''x(n-1)'' et ''x(n-2)'' (et aussi ''y(n-1)'', ''y(n-2)'') qu'il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de ''temps réel'' implique que ''y(n)'' doit être calculer avant qu'une nouvelle valeurs de ''x(n)'' ne rentre dans le système.&lt;br /&gt;
&lt;br /&gt;
=== Bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
Nous allons implémenter un filtre IIR dans gnuradio, en écrivant le traitement dans un bloc Python.&lt;br /&gt;
&lt;br /&gt;
==== Filtre moyenneur====&lt;br /&gt;
&lt;br /&gt;
{{q| a)}} Dans un premier temps, prendre connaissance du tutoriel suivant : [https://wiki.gnuradio.org/index.php?title=Creating_Your_First_Block wiki Gnuradio - ''Creating Your First Block'']&lt;br /&gt;
&lt;br /&gt;
{{q| b)}} Nous allons écrire un filtre simple, qui implémente un simple moyenneur :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;Python&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
from gnuradio import gr&lt;br /&gt;
&lt;br /&gt;
class blk(gr.sync_block):  &lt;br /&gt;
    def __init__(self):  # Pas de paramètres&lt;br /&gt;
        gr.sync_block.__init__(&lt;br /&gt;
            self,&lt;br /&gt;
            name=&amp;quot;Filtre moyenneur&amp;quot;,  &lt;br /&gt;
            in_sig=[np.float32],&lt;br /&gt;
            out_sig=[np.float32]&lt;br /&gt;
        )&lt;br /&gt;
        self.xn1 = 0 # initialisation d'un attribut pour stocker x(n-1)&lt;br /&gt;
&lt;br /&gt;
    def work(self, input_items, output_items):&lt;br /&gt;
        xn = input_items[0][0] # On ne &amp;quot;consomme&amp;quot; qu'un seul échantillon en entrée&lt;br /&gt;
        yn = (xn + self.xn1) / 2&lt;br /&gt;
        self.xn1 = xn&lt;br /&gt;
        output_items[0][0] = yn # On ne produit donc également qu'un seul échantillon en sortie&lt;br /&gt;
        return 1 # On retourne le nombre de valeurs consomées&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Filtre IIR : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc Python dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;np.float32&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;np.float32&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in[0][0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
&lt;br /&gt;
{{q| a)}}  Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au [[Cours:Elen4_TNS_TP_TraitAudioEtDemodulation|TP 5]].&lt;br /&gt;
&lt;br /&gt;
{{q| b)}}  Modifier votre code pour implémenter le filtre complet de démodulation.&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
Cette partie sera travaillée dans un notebook Jupyter.&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique, la sortie du controleur PID ''u(t)'' est donnée par:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
On considère que le temps est discrétisé : ''t = n.''d''t'' où d''t'' est l'intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée &amp;lt;br/&amp;gt;[[Fichier:PIDderivative.png|400px]] [[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
** La dérivée est calculée par ''D = (e(n)-e(n-1))/''d''t''&lt;br /&gt;
** L'intégrale est approximée en cumulant progressivement : ''I = I + e(n).''d''t''&lt;br /&gt;
C'est ainsi que vous avez implémenté vos PID jusqu'ici.&lt;br /&gt;
&lt;br /&gt;
Voici un notebook exemple à explorer sur deux modélisations : asservissement de 1) température et de 2) position ''z'' d'un drone.&lt;br /&gt;
&lt;br /&gt;
{{q | a}} ''Ki = Kd = 0'' =&amp;gt; chercher le meilleur ''Kp'' =&amp;gt; erreur statique.&lt;br /&gt;
{{q | b}} ''Kd = 0'' =&amp;gt; l'introduction du terme integral permet de corriger cette erreur statique.&lt;br /&gt;
{{q | c}} Le terme dérivatif n'est pas nécessaire pour la température&lt;br /&gt;
{{q | d}} Mais l'est pour asservir la position ''z'' du drone.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d'un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d'un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l'équation différentielle&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:EqPID.png|500px]]&lt;br /&gt;
&amp;lt;br/&amp;gt;On applique la transformée de Laplace (dérivée =&amp;gt; multiplication par ''s'' ; intégrale =&amp;gt; division par ''s'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPID.png|130]]&lt;br /&gt;
&amp;lt;br/&amp;gt;Le terme dérivatif étant très sensible au bruit, on lui applique généralement un filtre passe bas (''w0/(w0+s)'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;br /&gt;
&lt;br /&gt;
=== Archive : codage de bloc Gnuradio en C++ ===&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21078</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21078"/>
				<updated>2026-06-01T09:17:41Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* Approximation de PID par filtre numérique linéaire */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
Dans les deux cas, un système temps réel sera considéré :&lt;br /&gt;
* à intervalles de temps (réguliers ou non), une valeur ''x(n)'' rentre dans le système&lt;br /&gt;
* le travail consiste à calculer ''y(n)'' avec l'équation au différences du filtre, à partir de la valeur ''x(n)'' et de ses versions précédentes ''x(n-1)'' et ''x(n-2)'' (et aussi ''y(n-1)'', ''y(n-2)'') qu'il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de ''temps réel'' implique que ''y(n)'' doit être calculer avant qu'une nouvelle valeurs de ''x(n)'' ne rentre dans le système.&lt;br /&gt;
&lt;br /&gt;
=== Bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
Nous allons implémenter un filtre IIR dans gnuradio, en écrivant le traitement dans un bloc Python.&lt;br /&gt;
&lt;br /&gt;
==== Filtre moyenneur====&lt;br /&gt;
&lt;br /&gt;
{{q| a)}} Dans un premier temps, prendre connaissance du tutoriel suivant : [https://wiki.gnuradio.org/index.php?title=Creating_Your_First_Block wiki Gnuradio - ''Creating Your First Block'']&lt;br /&gt;
&lt;br /&gt;
{{q| b)}} Nous allons écrire un filtre simple, qui implémente un simple moyenneur :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;Python&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
from gnuradio import gr&lt;br /&gt;
&lt;br /&gt;
class blk(gr.sync_block):  &lt;br /&gt;
    def __init__(self):  # Pas de paramètres&lt;br /&gt;
        gr.sync_block.__init__(&lt;br /&gt;
            self,&lt;br /&gt;
            name=&amp;quot;Filtre moyenneur&amp;quot;,  &lt;br /&gt;
            in_sig=[np.float32],&lt;br /&gt;
            out_sig=[np.float32]&lt;br /&gt;
        )&lt;br /&gt;
        self.xn1 = 0 # initialisation d'un attribut pour stocker x(n-1)&lt;br /&gt;
&lt;br /&gt;
    def work(self, input_items, output_items):&lt;br /&gt;
        xn = input_items[0][0] # On ne &amp;quot;consomme&amp;quot; qu'un seul échantillon en entrée&lt;br /&gt;
        yn = (xn + self.xn1) / 2&lt;br /&gt;
        self.xn1 = xn&lt;br /&gt;
        output_items[0][0] = yn # On ne produit donc également qu'un seul échantillon en sortie&lt;br /&gt;
        return 1 # On retourne le nombre de valeurs consomées&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Filtre IIR : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc Python dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;np.float32&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;np.float32&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in[0][0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
&lt;br /&gt;
{{q| a)}}  Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au [[Cours:Elen4_TNS_TP_TraitAudioEtDemodulation|TP 5]].&lt;br /&gt;
&lt;br /&gt;
{{q| b)}}  Modifier votre code pour implémenter le filtre complet de démodulation.&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
Cette partie sera travaillée dans un notebook Jupyter.&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique, la sortie du controleur PID ''u(t)'' est donnée par:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
On considère que le temps est discrétisé : ''t = n.dt'' où ''dt'' est l'intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée &amp;lt;br/&amp;gt;[[Fichier:PIDderivative.png|400px]] [[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
** La dérivée est calculée par ''D = (e(n)-e(n-1))/dt''&lt;br /&gt;
** L'intégrale est approximée en cumulant progressivement : ''I = I + e(n).dt''&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** ''Ki = Kd = 0'' =&amp;gt; chercher le meilleur ''Kp'' =&amp;gt; erreur de régime permanent&lt;br /&gt;
** ''Kd = 0'' =&amp;gt; l'introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n'est pas nécessaire dans cet exemple car la température ne dépend que de la commande ''u(t)''.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d'un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d'un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l'équation différentielle&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:EqPID.png|500px]]&lt;br /&gt;
&amp;lt;br/&amp;gt;On applique la transformée de Laplace (dérivée =&amp;gt; multiplication par ''s'' ; intégrale =&amp;gt; division par ''s'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPID.png|130]]&lt;br /&gt;
&amp;lt;br/&amp;gt;Le terme dérivatif étant très sensible au bruit, on lui applique généralement un filtre passe bas (''w0/(w0+s)'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;br /&gt;
&lt;br /&gt;
=== Archive : codage de bloc Gnuradio en C++ ===&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21077</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21077"/>
				<updated>2026-06-01T09:17:00Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* Filtre IIR : démodulation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
Dans les deux cas, un système temps réel sera considéré :&lt;br /&gt;
* à intervalles de temps (réguliers ou non), une valeur ''x(n)'' rentre dans le système&lt;br /&gt;
* le travail consiste à calculer ''y(n)'' avec l'équation au différences du filtre, à partir de la valeur ''x(n)'' et de ses versions précédentes ''x(n-1)'' et ''x(n-2)'' (et aussi ''y(n-1)'', ''y(n-2)'') qu'il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de ''temps réel'' implique que ''y(n)'' doit être calculer avant qu'une nouvelle valeurs de ''x(n)'' ne rentre dans le système.&lt;br /&gt;
&lt;br /&gt;
=== Bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
Nous allons implémenter un filtre IIR dans gnuradio, en écrivant le traitement dans un bloc Python.&lt;br /&gt;
&lt;br /&gt;
==== Filtre moyenneur====&lt;br /&gt;
&lt;br /&gt;
{{q| a)}} Dans un premier temps, prendre connaissance du tutoriel suivant : [https://wiki.gnuradio.org/index.php?title=Creating_Your_First_Block wiki Gnuradio - ''Creating Your First Block'']&lt;br /&gt;
&lt;br /&gt;
{{q| b)}} Nous allons écrire un filtre simple, qui implémente un simple moyenneur :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;Python&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
from gnuradio import gr&lt;br /&gt;
&lt;br /&gt;
class blk(gr.sync_block):  &lt;br /&gt;
    def __init__(self):  # Pas de paramètres&lt;br /&gt;
        gr.sync_block.__init__(&lt;br /&gt;
            self,&lt;br /&gt;
            name=&amp;quot;Filtre moyenneur&amp;quot;,  &lt;br /&gt;
            in_sig=[np.float32],&lt;br /&gt;
            out_sig=[np.float32]&lt;br /&gt;
        )&lt;br /&gt;
        self.xn1 = 0 # initialisation d'un attribut pour stocker x(n-1)&lt;br /&gt;
&lt;br /&gt;
    def work(self, input_items, output_items):&lt;br /&gt;
        xn = input_items[0][0] # On ne &amp;quot;consomme&amp;quot; qu'un seul échantillon en entrée&lt;br /&gt;
        yn = (xn + self.xn1) / 2&lt;br /&gt;
        self.xn1 = xn&lt;br /&gt;
        output_items[0][0] = yn # On ne produit donc également qu'un seul échantillon en sortie&lt;br /&gt;
        return 1 # On retourne le nombre de valeurs consomées&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Filtre IIR : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc Python dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;np.float32&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;np.float32&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in[0][0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
&lt;br /&gt;
{{q| a)}}  Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au [[Cours:Elen4_TNS_TP_TraitAudioEtDemodulation|TP 5]].&lt;br /&gt;
&lt;br /&gt;
{{q| b)}}  Modifier votre code pour implémenter le filtre complet de démodulation.&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique, la sortie du controleur PID ''u(t)'' est donnée par:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
On considère que le temps est discrétisé : ''t = n.dt'' où ''dt'' est l'intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée &amp;lt;br/&amp;gt;[[Fichier:PIDderivative.png|400px]] [[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
** La dérivée est calculée par ''D = (e(n)-e(n-1))/dt''&lt;br /&gt;
** L'intégrale est approximée en cumulant progressivement : ''I = I + e(n).dt''&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** ''Ki = Kd = 0'' =&amp;gt; chercher le meilleur ''Kp'' =&amp;gt; erreur de régime permanent&lt;br /&gt;
** ''Kd = 0'' =&amp;gt; l'introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n'est pas nécessaire dans cet exemple car la température ne dépend que de la commande ''u(t)''.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d'un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d'un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l'équation différentielle&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:EqPID.png|500px]]&lt;br /&gt;
&amp;lt;br/&amp;gt;On applique la transformée de Laplace (dérivée =&amp;gt; multiplication par ''s'' ; intégrale =&amp;gt; division par ''s'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPID.png|130]]&lt;br /&gt;
&amp;lt;br/&amp;gt;Le terme dérivatif étant très sensible au bruit, on lui applique généralement un filtre passe bas (''w0/(w0+s)'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Archive : codage de bloc Gnuradio en C++ ===&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21076</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21076"/>
				<updated>2026-06-01T09:16:32Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* Filtre moyenneur */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
Dans les deux cas, un système temps réel sera considéré :&lt;br /&gt;
* à intervalles de temps (réguliers ou non), une valeur ''x(n)'' rentre dans le système&lt;br /&gt;
* le travail consiste à calculer ''y(n)'' avec l'équation au différences du filtre, à partir de la valeur ''x(n)'' et de ses versions précédentes ''x(n-1)'' et ''x(n-2)'' (et aussi ''y(n-1)'', ''y(n-2)'') qu'il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de ''temps réel'' implique que ''y(n)'' doit être calculer avant qu'une nouvelle valeurs de ''x(n)'' ne rentre dans le système.&lt;br /&gt;
&lt;br /&gt;
=== Bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
Nous allons implémenter un filtre IIR dans gnuradio, en écrivant le traitement dans un bloc Python.&lt;br /&gt;
&lt;br /&gt;
==== Filtre moyenneur====&lt;br /&gt;
&lt;br /&gt;
{{q| a)}} Dans un premier temps, prendre connaissance du tutoriel suivant : [https://wiki.gnuradio.org/index.php?title=Creating_Your_First_Block wiki Gnuradio - ''Creating Your First Block'']&lt;br /&gt;
&lt;br /&gt;
{{q| b)}} Nous allons écrire un filtre simple, qui implémente un simple moyenneur :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;Python&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
from gnuradio import gr&lt;br /&gt;
&lt;br /&gt;
class blk(gr.sync_block):  &lt;br /&gt;
    def __init__(self):  # Pas de paramètres&lt;br /&gt;
        gr.sync_block.__init__(&lt;br /&gt;
            self,&lt;br /&gt;
            name=&amp;quot;Filtre moyenneur&amp;quot;,  &lt;br /&gt;
            in_sig=[np.float32],&lt;br /&gt;
            out_sig=[np.float32]&lt;br /&gt;
        )&lt;br /&gt;
        self.xn1 = 0 # initialisation d'un attribut pour stocker x(n-1)&lt;br /&gt;
&lt;br /&gt;
    def work(self, input_items, output_items):&lt;br /&gt;
        xn = input_items[0][0] # On ne &amp;quot;consomme&amp;quot; qu'un seul échantillon en entrée&lt;br /&gt;
        yn = (xn + self.xn1) / 2&lt;br /&gt;
        self.xn1 = xn&lt;br /&gt;
        output_items[0][0] = yn # On ne produit donc également qu'un seul échantillon en sortie&lt;br /&gt;
        return 1 # On retourne le nombre de valeurs consomées&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Filtre IIR : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc Python dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;np.float32&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;np.float32&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
&lt;br /&gt;
{{q| a)}}  Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au [[Cours:Elen4_TNS_TP_TraitAudioEtDemodulation|TP 5]].&lt;br /&gt;
&lt;br /&gt;
{{q| b)}}  Modifier votre code pour implémenter le filtre complet de démodulation.&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique, la sortie du controleur PID ''u(t)'' est donnée par:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
On considère que le temps est discrétisé : ''t = n.dt'' où ''dt'' est l'intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée &amp;lt;br/&amp;gt;[[Fichier:PIDderivative.png|400px]] [[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
** La dérivée est calculée par ''D = (e(n)-e(n-1))/dt''&lt;br /&gt;
** L'intégrale est approximée en cumulant progressivement : ''I = I + e(n).dt''&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** ''Ki = Kd = 0'' =&amp;gt; chercher le meilleur ''Kp'' =&amp;gt; erreur de régime permanent&lt;br /&gt;
** ''Kd = 0'' =&amp;gt; l'introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n'est pas nécessaire dans cet exemple car la température ne dépend que de la commande ''u(t)''.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d'un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d'un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l'équation différentielle&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:EqPID.png|500px]]&lt;br /&gt;
&amp;lt;br/&amp;gt;On applique la transformée de Laplace (dérivée =&amp;gt; multiplication par ''s'' ; intégrale =&amp;gt; division par ''s'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPID.png|130]]&lt;br /&gt;
&amp;lt;br/&amp;gt;Le terme dérivatif étant très sensible au bruit, on lui applique généralement un filtre passe bas (''w0/(w0+s)'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Archive : codage de bloc Gnuradio en C++ ===&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21075</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21075"/>
				<updated>2026-06-01T09:15:12Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
Dans les deux cas, un système temps réel sera considéré :&lt;br /&gt;
* à intervalles de temps (réguliers ou non), une valeur ''x(n)'' rentre dans le système&lt;br /&gt;
* le travail consiste à calculer ''y(n)'' avec l'équation au différences du filtre, à partir de la valeur ''x(n)'' et de ses versions précédentes ''x(n-1)'' et ''x(n-2)'' (et aussi ''y(n-1)'', ''y(n-2)'') qu'il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de ''temps réel'' implique que ''y(n)'' doit être calculer avant qu'une nouvelle valeurs de ''x(n)'' ne rentre dans le système.&lt;br /&gt;
&lt;br /&gt;
=== Bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
Nous allons implémenter un filtre IIR dans gnuradio, en écrivant le traitement dans un bloc Python.&lt;br /&gt;
&lt;br /&gt;
==== Filtre moyenneur====&lt;br /&gt;
&lt;br /&gt;
{{q| a)}} Dans un premier temps, prendre connaissance du tutoriel suivant : [https://wiki.gnuradio.org/index.php?title=Creating_Your_First_Block wiki Gnuradio - ''Creating Your First Block'']&lt;br /&gt;
&lt;br /&gt;
{{q| b)}} Nous allons écrire un filtre simple, qui implémente un simple moyenneur :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;Python&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
from gnuradio import gr&lt;br /&gt;
&lt;br /&gt;
class blk(gr.sync_block):  &lt;br /&gt;
    def __init__(self):  # Pas de paramètres&lt;br /&gt;
        gr.sync_block.__init__(&lt;br /&gt;
            self,&lt;br /&gt;
            name=&amp;quot;Filtre moyenneur&amp;quot;,  &lt;br /&gt;
            in_sig=[np.float32],&lt;br /&gt;
            out_sig=[np.float32],&lt;br /&gt;
        )&lt;br /&gt;
        self.xn1 = 0 # initialisation d'un attribut pour stocker x(n-1)&lt;br /&gt;
&lt;br /&gt;
    def work(self, input_items, output_items):&lt;br /&gt;
        xn = input_items[0][0] # On ne &amp;quot;consomme&amp;quot; qu'un seul échantillon en entrée&lt;br /&gt;
        yn = (xn + self.xn1) / 2&lt;br /&gt;
        self.xn1 = xn&lt;br /&gt;
        output_items[0][0] = yn # On ne produit donc également qu'un seul échantillon en sortie&lt;br /&gt;
        return 1 # On retourne le nombre de valeurs consomémes&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
==== Filtre IIR : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc Python dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;np.float32&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;np.float32&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
&lt;br /&gt;
{{q| a)}}  Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au [[Cours:Elen4_TNS_TP_TraitAudioEtDemodulation|TP 5]].&lt;br /&gt;
&lt;br /&gt;
{{q| b)}}  Modifier votre code pour implémenter le filtre complet de démodulation.&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique, la sortie du controleur PID ''u(t)'' est donnée par:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
On considère que le temps est discrétisé : ''t = n.dt'' où ''dt'' est l'intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée &amp;lt;br/&amp;gt;[[Fichier:PIDderivative.png|400px]] [[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
** La dérivée est calculée par ''D = (e(n)-e(n-1))/dt''&lt;br /&gt;
** L'intégrale est approximée en cumulant progressivement : ''I = I + e(n).dt''&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** ''Ki = Kd = 0'' =&amp;gt; chercher le meilleur ''Kp'' =&amp;gt; erreur de régime permanent&lt;br /&gt;
** ''Kd = 0'' =&amp;gt; l'introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n'est pas nécessaire dans cet exemple car la température ne dépend que de la commande ''u(t)''.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d'un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d'un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l'équation différentielle&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:EqPID.png|500px]]&lt;br /&gt;
&amp;lt;br/&amp;gt;On applique la transformée de Laplace (dérivée =&amp;gt; multiplication par ''s'' ; intégrale =&amp;gt; division par ''s'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPID.png|130]]&lt;br /&gt;
&amp;lt;br/&amp;gt;Le terme dérivatif étant très sensible au bruit, on lui applique généralement un filtre passe bas (''w0/(w0+s)'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Archive : codage de bloc Gnuradio en C++ ===&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21072</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21072"/>
				<updated>2026-05-30T08:27:45Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* Codage de bloc Gnuradio en Python */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
Dans les deux cas, un système temps réel sera considéré :&lt;br /&gt;
* à intervalles de temps (réguliers ou non), une valeur ''x(n)'' rentre dans le système&lt;br /&gt;
* le travail consiste à calculer ''y(n)'' avec l'équation au différences du filtre, à partir de la valeur ''x(n)'' et de ses versions précédentes ''x(n-1)'' et ''x(n-2)'' (et aussi ''y(n-1)'', ''y(n-2)'') qu'il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de ''temps réel'' implique que ''y(n)'' doit être calculer avant qu'une nouvelle valeurs de ''x(n)'' ne rentre dans le système.&lt;br /&gt;
&lt;br /&gt;
=== bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
[https://wiki.gnuradio.org/index.php?title=Creating_Your_First_Block wiki Gnuradio - ''Creating Your First Block'']&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique, la sortie du controleur PID ''u(t)'' est donnée par:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
On considère que le temps est discrétisé : ''t = n.dt'' où ''dt'' est l'intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée &amp;lt;br/&amp;gt;[[Fichier:PIDderivative.png|400px]] [[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
** La dérivée est calculée par ''D = (e(n)-e(n-1))/dt''&lt;br /&gt;
** L'intégrale est approximée en cumulant progressivement : ''I = I + e(n).dt''&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** ''Ki = Kd = 0'' =&amp;gt; chercher le meilleur ''Kp'' =&amp;gt; erreur de régime permanent&lt;br /&gt;
** ''Kd = 0'' =&amp;gt; l'introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n'est pas nécessaire dans cet exemple car la température ne dépend que de la commande ''u(t)''.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d'un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d'un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l'équation différentielle&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:EqPID.png|500px]]&lt;br /&gt;
&amp;lt;br/&amp;gt;On applique la transformée de Laplace (dérivée =&amp;gt; multiplication par ''s'' ; intégrale =&amp;gt; division par ''s'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPID.png|130]]&lt;br /&gt;
&amp;lt;br/&amp;gt;Le terme dérivatif étant très sensible au bruit, on lui applique généralement un filtre passe bas (''w0/(w0+s)'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Archive : codage de bloc Gnuradio en C++ ===&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21071</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21071"/>
				<updated>2026-05-30T08:20:33Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
Dans les deux cas, un système temps réel sera considéré :&lt;br /&gt;
* à intervalles de temps (réguliers ou non), une valeur ''x(n)'' rentre dans le système&lt;br /&gt;
* le travail consiste à calculer ''y(n)'' avec l'équation au différences du filtre, à partir de la valeur ''x(n)'' et de ses versions précédentes ''x(n-1)'' et ''x(n-2)'' (et aussi ''y(n-1)'', ''y(n-2)'') qu'il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de ''temps réel'' implique que ''y(n)'' doit être calculer avant qu'une nouvelle valeurs de ''x(n)'' ne rentre dans le système.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
'''EN COURS DE RÉÉCRITURE (C++ vers Python)'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique, la sortie du controleur PID ''u(t)'' est donnée par:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
On considère que le temps est discrétisé : ''t = n.dt'' où ''dt'' est l'intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée &amp;lt;br/&amp;gt;[[Fichier:PIDderivative.png|400px]] [[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
** La dérivée est calculée par ''D = (e(n)-e(n-1))/dt''&lt;br /&gt;
** L'intégrale est approximée en cumulant progressivement : ''I = I + e(n).dt''&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** ''Ki = Kd = 0'' =&amp;gt; chercher le meilleur ''Kp'' =&amp;gt; erreur de régime permanent&lt;br /&gt;
** ''Kd = 0'' =&amp;gt; l'introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n'est pas nécessaire dans cet exemple car la température ne dépend que de la commande ''u(t)''.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d'un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d'un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l'équation différentielle&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:EqPID.png|500px]]&lt;br /&gt;
&amp;lt;br/&amp;gt;On applique la transformée de Laplace (dérivée =&amp;gt; multiplication par ''s'' ; intégrale =&amp;gt; division par ''s'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPID.png|130]]&lt;br /&gt;
&amp;lt;br/&amp;gt;Le terme dérivatif étant très sensible au bruit, on lui applique généralement un filtre passe bas (''w0/(w0+s)'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Archive : codage de bloc Gnuradio en C++ ===&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21070</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21070"/>
				<updated>2026-05-30T08:17:35Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
Dans les deux cas, un système temps réel sera considéré :&lt;br /&gt;
* à intervalles de temps (réguliers ou non), une valeur ''x(n)'' rentre dans le système&lt;br /&gt;
* le travail consiste à calculer ''y(n)'' avec l'équation au différences du filtre, à partir de la valeur ''x(n)'' et de ses versions précédentes ''x(n-1)'' et ''x(n-2)'' (et aussi ''y(n-1)'', ''y(n-2)'') qu'il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de ''temps réel&amp;quot; implique que ''y(n)'' doit pouvoir être calculer avant qu'une nouvelle valeurs de ''x(n)'' ne rentre dans le système.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
'''EN COURS DE RÉÉCRITURE (C++ vers Python)'''&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique, la sortie du controleur PID ''u(t)'' est donnée par:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
On considère que le temps est discrétisé : ''t = n.dt'' où ''dt'' est l'intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée &amp;lt;br/&amp;gt;[[Fichier:PIDderivative.png|400px]] [[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
** La dérivée est calculée par ''D = (e(n)-e(n-1))/dt''&lt;br /&gt;
** L'intégrale est approximée en cumulant progressivement : ''I = I + e(n).dt''&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** ''Ki = Kd = 0'' =&amp;gt; chercher le meilleur ''Kp'' =&amp;gt; erreur de régime permanent&lt;br /&gt;
** ''Kd = 0'' =&amp;gt; l'introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n'est pas nécessaire dans cet exemple car la température ne dépend que de la commande ''u(t)''.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d'un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d'un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l'équation différentielle&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:EqPID.png|500px]]&lt;br /&gt;
&amp;lt;br/&amp;gt;On applique la transformée de Laplace (dérivée =&amp;gt; multiplication par ''s'' ; intégrale =&amp;gt; division par ''s'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPID.png|130]]&lt;br /&gt;
&amp;lt;br/&amp;gt;Le terme dérivatif étant très sensible au bruit, on lui applique généralement un filtre passe bas (''w0/(w0+s)'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21069</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21069"/>
				<updated>2026-05-30T08:17:09Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 : Temps réel - Bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
Dans les deux cas, un système temps réel sera considéré :&lt;br /&gt;
* à intervalles de temps (réguliers ou non), une valeur ''x(n)'' rentre dans le système&lt;br /&gt;
* le travail consiste à calculer ''y(n)'' avec l'équation au différences du filtre, à partir de la valeur ''x(n)'' et de ses versions précédentes ''x(n-1)'' et ''x(n-2)'' (et aussi ''y(n-1)'', ''y(n-2)'') qu'il est donc nécessaire de stocker.&lt;br /&gt;
* La notion de ''temps réel&amp;quot; implique que ''y(n)'' doit pouvoir être calculer avant qu'une nouvelle valeurs de ''x(n)'' ne rentre dans le système.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
'''EN COURS DE RÉÉCRITURE (C++ vers Python)'''&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique, la sortie du controleur PID ''u(t)'' est donnée par:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
On considère que le temps est discrétisé : ''t = n.dt'' où ''dt'' est l'intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée &amp;lt;br/&amp;gt;[[Fichier:PIDderivative.png|400px]] [[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
** La dérivée est calculée par ''D = (e(n)-e(n-1))/dt''&lt;br /&gt;
** L'intégrale est approximée en cumulant progressivement : ''I = I + e(n).dt''&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** ''Ki = Kd = 0'' =&amp;gt; chercher le meilleur ''Kp'' =&amp;gt; erreur de régime permanent&lt;br /&gt;
** ''Kd = 0'' =&amp;gt; l'introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n'est pas nécessaire dans cet exemple car la température ne dépend que de la commande ''u(t)''.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d'un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d'un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l'équation différentielle&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:EqPID.png|500px]]&lt;br /&gt;
&amp;lt;br/&amp;gt;On applique la transformée de Laplace (dérivée =&amp;gt; multiplication par ''s'' ; intégrale =&amp;gt; division par ''s'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPID.png|130]]&lt;br /&gt;
&amp;lt;br/&amp;gt;Le terme dérivatif étant très sensible au bruit, on lui applique généralement un filtre passe bas (''w0/(w0+s)'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS&amp;diff=21068</id>
		<title>Cours:Elen4 TNS</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS&amp;diff=21068"/>
				<updated>2026-05-30T08:13:13Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* Travaux Pratiques */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;S4 - ESE - Traitement numérique du signal&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Description générale ==&lt;br /&gt;
&lt;br /&gt;
=== Contenu (Programme National) ===&lt;br /&gt;
&lt;br /&gt;
Filtrage numérique :&lt;br /&gt;
* Équation de récurrence, opérations élémentaires, fonction de transfert en Z, passage à un programme informatique;&lt;br /&gt;
* Filtre numérique : ﬁltres récursif et non récursif, réponses temporelles (impulsionnelle, indicielle, signal quelconque), réponse fréquentielle, stabilité;&lt;br /&gt;
* Synthèse de ﬁltres numériques simples (approximation d’Euler);&lt;br /&gt;
* Utilisation d’outils de synthèse des ﬁltres numériques RIF et RII (Matlab, Labview, GNU radio...) et comparaison des performances des ﬁltres RIF et RII;&lt;br /&gt;
* Présentation des différentes structures des ﬁltres numériques (direct, cascade, parallèle);&lt;br /&gt;
* Implantation d’un traitement numérique sur cible : ﬁltrage numérique simple, asservissement numérique simple (robot mobile, drone...), traitement de données.&lt;br /&gt;
&lt;br /&gt;
=== Volumes horaire ===&lt;br /&gt;
&lt;br /&gt;
* CM : 4 séances d'1,5h&lt;br /&gt;
* TD : 6 séances d'1,5h + une évaluation d'1,5h&lt;br /&gt;
* TP : 6 séances de 3h + une évaluation de 2h&lt;br /&gt;
&lt;br /&gt;
=== Évaluations ===&lt;br /&gt;
&lt;br /&gt;
* une évaluation sur table (derniere séance de CM/TD - 1,5h)&lt;br /&gt;
* une évaluation pratique (dernière séance de TP - 2h)&lt;br /&gt;
&lt;br /&gt;
== Cours Magistraux ==&lt;br /&gt;
&lt;br /&gt;
Contenu :&lt;br /&gt;
* Signaux et systèmes numériques&lt;br /&gt;
* Filtres numériques&lt;br /&gt;
* Quelques filtres RIF&lt;br /&gt;
* Synthèse de filtres numériques&lt;br /&gt;
* PID numérique &lt;br /&gt;
* Élements sur le traitement des images numériques&lt;br /&gt;
* Élements sur le temps-fréquence&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
Documents :&lt;br /&gt;
* [[Media:TNS-Support.pdf|Support de cours en pdf]]&lt;br /&gt;
* [[Media:TNS-diapos.pdf|Diapositives de cours en pdf]]&lt;br /&gt;
&lt;br /&gt;
== Travaux Dirigés ==&lt;br /&gt;
&lt;br /&gt;
Textes en pdf :&lt;br /&gt;
&lt;br /&gt;
* [[Media:TNS-td1.FxTransfert.pdf|TD1 : Fonctions de transfert]]&lt;br /&gt;
* [[Media:TNS-td2.Stabilité.pdf|TD2 : Causabilité et stabilité]]&lt;br /&gt;
* [[Media:TNS-td3.RepFreq.pdf|TD3 : Réponses fréquentielles]]&lt;br /&gt;
* [[Media:TNS-td4.Facteurs1et2.pdf|TD4 : Facteurs du premier et du second ordre]]&lt;br /&gt;
* [[Media:TNS-td5-Structures.pdf|TD5 : Structures de réalisation]]&lt;br /&gt;
* [[Media:TNS-td6-ConceptionFiltresRII.pdf|TD6 : Conception de filtres récursifs]]&lt;br /&gt;
* Évaluation&lt;br /&gt;
&lt;br /&gt;
== Travaux Pratiques ==&lt;br /&gt;
&lt;br /&gt;
Les TP utiliseront :&lt;br /&gt;
* Gnuradio (cf premier TP)&lt;br /&gt;
* Python, que nous utiliserons en installation locale avec [https://pixi.prefix.dev/ Pixi], en suivant ce guide rapide : [[Cours:Elen4_TNS#Travail avec Python et Pixi|Travail avec Python et Pixi]] &lt;br /&gt;
&amp;lt;!--* et occasionnellement des cartes Arduinio ou Rpi Pico.--&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Liste des TP :&lt;br /&gt;
* [[Cours:Elen4_TNS_TP_Gnuradio|TP1 - Fondamentaux Gnuradio]]&lt;br /&gt;
* [[Cours:Elen4_TNS_TP_FxTransfertStabilité|TP2 - Fonction de transfert et stabilité]]&lt;br /&gt;
* [[Cours:Elen4_TNS_TP_Implementations|TP3 - Implémentations de filtres]]&lt;br /&gt;
* [[Cours:Elen4_TNS_TP_TraitImage|TP4 - Traitements d'images numériques]]&lt;br /&gt;
* [[Cours:Elen4_TNS_TP_TraitAudioEtDemodulation| TP5 - Traitements audio et démodulation]]&lt;br /&gt;
* [[Cours:Elen4_TNS_TP_ TpsReel |TP6 - Temps réel : bloc Gnuradio en Python / démodulation / PID Numérique]]&lt;br /&gt;
* Évaluation&lt;br /&gt;
&lt;br /&gt;
== Évaluation de Travaux Pratiques ==&lt;br /&gt;
&lt;br /&gt;
Énoncés :&lt;br /&gt;
* [[Cours:Elen4_TNS_TP_eval1|Sujet n°1]]&lt;br /&gt;
&lt;br /&gt;
Documents autorisés :&lt;br /&gt;
* accès au wiki&lt;br /&gt;
* documents de cours&lt;br /&gt;
* notes personnelles&lt;br /&gt;
&lt;br /&gt;
== Travail avec Python et Pixi ==&lt;br /&gt;
&lt;br /&gt;
=== Gestionnaire de projets Pixi ===&lt;br /&gt;
&lt;br /&gt;
[https://pixi.prefix.dev/ Pixi] est un gestionnaire de projets Python permettant une reproductibilité grace une installation purement locale à l'utilisateur (pas d'utilisation d'éléments au niveau système). Dans le dossier du projet, on trouve principalement :&lt;br /&gt;
* un fichier &amp;lt;code&amp;gt;pixi.toml&amp;lt;/code&amp;gt; décrivant les dépendances du projet (souvent de façon souple)&lt;br /&gt;
* les fichiers du projets&lt;br /&gt;
* un dossier &amp;lt;code&amp;gt;.pixi&amp;lt;/code&amp;gt; contenant les binaires Python et les dépendances nécessaires, ainsi qu'un fichier &amp;lt;/code&amp;gt;pixi.lock&amp;lt;/code&amp;gt; contenant description complète et déterministe de l'environnement installé.&lt;br /&gt;
&lt;br /&gt;
Voici un guide :&lt;br /&gt;
# Installer pixi, en suivant l'indication décrite dans https://pixi.prefix.dev/latest/installation/&amp;lt;br/&amp;gt;''Note : l'installation est locale à l'utilisateur, elle ne sera nécessaire qu'une seule fois pour le semestre''&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Dans un terminal, instancier le projet (voir [https://pixi.prefix.dev/latest/first_workspace/ ici]) &amp;lt;source&amp;gt;&lt;br /&gt;
&amp;gt; pixi init nomduprojet&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
# Vvous positionner dans ce projet &amp;lt;source&amp;gt;&lt;br /&gt;
&amp;gt; cd nomduprojet&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
# Ajouter les dépendances nécessaire pour ce module &amp;lt;source&amp;gt;&lt;br /&gt;
&amp;gt; pixi add numpy scipy matplotlib&lt;br /&gt;
&amp;lt;/source&amp;gt; ''Incidemment, ces dépendances nécessitent python qui sera installé automatiquement (à l'aide du dépot conda). Vous pouvez afficher le fichier pixi.toml pour observer ces dépendances.''&lt;br /&gt;
# Et ajouter les dépendances nécessaire pour travailler avec [https://jupyter.org/ Jupyter] &amp;lt;source&amp;gt;&lt;br /&gt;
&amp;gt; pixi add jupyterlab pixi-kernel&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
# Travailler avec le workspace ainsi installé :&lt;br /&gt;
## en lançant l'interpréteur python, &amp;lt;code&amp;gt; pixi run python&amp;lt;/code&amp;gt;&lt;br /&gt;
## ou en executant un fichier python, &amp;lt;code&amp;gt; pixi run python monscript.py&amp;lt;/code&amp;gt;&lt;br /&gt;
## ou en lançant un serveur jupyter, &amp;lt;code&amp;gt; pixi run jupyter lab&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Important''' :&lt;br /&gt;
* Il n'est normalement pas nécessaire d'éditer le fichier &amp;lt;code&amp;gt;pixi.toml&amp;lt;/code&amp;gt;&lt;br /&gt;
* Il n'est '''jamais''' nécessaire d'éditer le fichier &amp;lt;code&amp;gt;pixi.lock&amp;lt;/code&amp;gt;&lt;br /&gt;
* Pour distribuer votre projet, seul le fichier &amp;lt;code&amp;gt;pixi.toml&amp;lt;/code&amp;gt; et les fichiers sources sont utiles.&lt;br /&gt;
&lt;br /&gt;
=== Packages Python ===&lt;br /&gt;
&lt;br /&gt;
* [https://numpy.org/ Numpy] pour la manipulation des tableaux de valeurs (ie les signaux)&lt;br /&gt;
* [https://scipy.org/ Scipy], en particulier [https://docs.scipy.org/doc/scipy/reference/signal.html le package Signal] pour les traitements et les filtrages,&lt;br /&gt;
* [https://matplotlib.org/ Matplotlib] pour les graphes&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21067</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21067"/>
				<updated>2026-05-30T08:12:52Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 : Temps réel - Bloc Gnuradio en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
'''EN COURS DE RÉÉCRITURE (C++ vers Python)'''&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique, la sortie du controleur PID ''u(t)'' est donnée par:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
On considère que le temps est discrétisé : ''t = n.dt'' où ''dt'' est l'intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée &amp;lt;br/&amp;gt;[[Fichier:PIDderivative.png|400px]] [[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
** La dérivée est calculée par ''D = (e(n)-e(n-1))/dt''&lt;br /&gt;
** L'intégrale est approximée en cumulant progressivement : ''I = I + e(n).dt''&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** ''Ki = Kd = 0'' =&amp;gt; chercher le meilleur ''Kp'' =&amp;gt; erreur de régime permanent&lt;br /&gt;
** ''Kd = 0'' =&amp;gt; l'introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n'est pas nécessaire dans cet exemple car la température ne dépend que de la commande ''u(t)''.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d'un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d'un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l'équation différentielle&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:EqPID.png|500px]]&lt;br /&gt;
&amp;lt;br/&amp;gt;On applique la transformée de Laplace (dérivée =&amp;gt; multiplication par ''s'' ; intégrale =&amp;gt; division par ''s'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPID.png|130]]&lt;br /&gt;
&amp;lt;br/&amp;gt;Le terme dérivatif étant très sensible au bruit, on lui applique généralement un filtre passe bas (''w0/(w0+s)'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21066</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21066"/>
				<updated>2026-05-30T06:10:48Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* PID numérique par approximation d'un filtre continu */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d'un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
'''EN COURS DE RÉÉCRITURE (C++ vers Python)'''&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique, la sortie du controleur PID ''u(t)'' est donnée par:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
On considère que le temps est discrétisé : ''t = n.dt'' où ''dt'' est l'intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée &amp;lt;br/&amp;gt;[[Fichier:PIDderivative.png|400px]] [[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
** La dérivée est calculée par ''D = (e(n)-e(n-1))/dt''&lt;br /&gt;
** L'intégrale est approximée en cumulant progressivement : ''I = I + e(n).dt''&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** ''Ki = Kd = 0'' =&amp;gt; chercher le meilleur ''Kp'' =&amp;gt; erreur de régime permanent&lt;br /&gt;
** ''Kd = 0'' =&amp;gt; l'introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n'est pas nécessaire dans cet exemple car la température ne dépend que de la commande ''u(t)''.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d'un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d'un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l'équation différentielle&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:EqPID.png|500px]]&lt;br /&gt;
&amp;lt;br/&amp;gt;On applique la transformée de Laplace (dérivée =&amp;gt; multiplication par ''s'' ; intégrale =&amp;gt; division par ''s'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPID.png|130]]&lt;br /&gt;
&amp;lt;br/&amp;gt;Le terme dérivatif étant très sensible au bruit, on lui applique généralement un filtre passe bas (''w0/(w0+s)'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21065</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21065"/>
				<updated>2026-05-29T13:32:32Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* PID numérique par approximation d'un filtre continu */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d'un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
'''EN COURS DE RÉÉCRITURE (C++ vers Python)'''&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique, la sortie du controleur PID ''u(t)'' est donnée par:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
On considère que le temps est discrétisé : ''t = n.dt'' où ''dt'' est l'intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée &amp;lt;br/&amp;gt;[[Fichier:PIDderivative.png|400px]] [[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
** La dérivée est calculée par ''D = (e(n)-e(n-1))/dt''&lt;br /&gt;
** L'intégrale est approximée en cumulant progressivement : ''I = I + e(n).dt''&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** ''Ki = Kd = 0'' =&amp;gt; chercher le meilleur ''Kp'' =&amp;gt; erreur de régime permanent&lt;br /&gt;
** ''Kd = 0'' =&amp;gt; l'introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n'est pas nécessaire dans cet exemple car la température ne dépend que de la commande ''u(t)''.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d'un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Cherchons la fonction de transfert du filtre continu d'un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l'équation différentielle&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:EqPID.png|500px]]&lt;br /&gt;
&amp;lt;br/&amp;gt;On applique la transformée de Laplace (dérivée =&amp;gt; multiplication par ''s'' ; intégrale =&amp;gt; division par ''s'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPID.png|200]]&lt;br /&gt;
&amp;lt;br/&amp;gt;Le terme dérivatif étant très sensible au bruit, on lui applique généralement un filtre passe bas (''w0/(w0+s)'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21064</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21064"/>
				<updated>2026-05-29T13:29:01Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* PID numérique par approximation d'un filtre continu */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d'un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
'''EN COURS DE RÉÉCRITURE (C++ vers Python)'''&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique, la sortie du controleur PID ''u(t)'' est donnée par:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
On considère que le temps est discrétisé : ''t = n.dt'' où ''dt'' est l'intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée &amp;lt;br/&amp;gt;[[Fichier:PIDderivative.png|400px]] [[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
** La dérivée est calculée par ''D = (e(n)-e(n-1))/dt''&lt;br /&gt;
** L'intégrale est approximée en cumulant progressivement : ''I = I + e(n).dt''&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** ''Ki = Kd = 0'' =&amp;gt; chercher le meilleur ''Kp'' =&amp;gt; erreur de régime permanent&lt;br /&gt;
** ''Kd = 0'' =&amp;gt; l'introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n'est pas nécessaire dans cet exemple car la température ne dépend que de la commande ''u(t)''.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d'un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Fonction de transfert Filtre continu d'un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l'équation différentielle&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:EqPID.png|500px]]&lt;br /&gt;
&amp;lt;br/&amp;gt;On applique la transformée de Laplace (dérivée =&amp;gt; multiplication par ''s'' ; intégrale =&amp;gt; division par ''s'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPID.png|200]]&lt;br /&gt;
&amp;lt;br/&amp;gt;On applique généralement un filtre passe bas (''w0/(w0+s)'') sur le terme dérivatif : &lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21063</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21063"/>
				<updated>2026-05-29T13:14:02Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* PID numérique par approximation d'un filtre continu */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d'un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
'''EN COURS DE RÉÉCRITURE (C++ vers Python)'''&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique, la sortie du controleur PID ''u(t)'' est donnée par:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
On considère que le temps est discrétisé : ''t = n.dt'' où ''dt'' est l'intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée &amp;lt;br/&amp;gt;[[Fichier:PIDderivative.png|400px]] [[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
** La dérivée est calculée par ''D = (e(n)-e(n-1))/dt''&lt;br /&gt;
** L'intégrale est approximée en cumulant progressivement : ''I = I + e(n).dt''&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** ''Ki = Kd = 0'' =&amp;gt; chercher le meilleur ''Kp'' =&amp;gt; erreur de régime permanent&lt;br /&gt;
** ''Kd = 0'' =&amp;gt; l'introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n'est pas nécessaire dans cet exemple car la température ne dépend que de la commande ''u(t)''.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d'un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Fonction de transfert Filtre continu d'un PID.&lt;br /&gt;
&amp;lt;br/&amp;gt;En partant de l'équation différentielle&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:EqPID.png|500px]]&lt;br /&gt;
&amp;lt;br/&amp;gt;On applique la transformée de Laplace (dérivée =&amp;gt; multiplication par ''s'' ; intégrale =&amp;gt; division par ''s'') :&lt;br /&gt;
&amp;lt;br/&amp;gt;[[Fichier:eqFxTransfertPID.png|200]]&lt;br /&gt;
&amp;lt;br/&amp;gt;On applique&lt;br /&gt;
[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21062</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21062"/>
				<updated>2026-05-29T13:11:13Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* PID numérique &amp;quot;classique&amp;quot; */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d'un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
'''EN COURS DE RÉÉCRITURE (C++ vers Python)'''&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique, la sortie du controleur PID ''u(t)'' est donnée par:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
On considère que le temps est discrétisé : ''t = n.dt'' où ''dt'' est l'intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée &amp;lt;br/&amp;gt;[[Fichier:PIDderivative.png|400px]] [[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
** La dérivée est calculée par ''D = (e(n)-e(n-1))/dt''&lt;br /&gt;
** L'intégrale est approximée en cumulant progressivement : ''I = I + e(n).dt''&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** ''Ki = Kd = 0'' =&amp;gt; chercher le meilleur ''Kp'' =&amp;gt; erreur de régime permanent&lt;br /&gt;
** ''Kd = 0'' =&amp;gt; l'introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n'est pas nécessaire dans cet exemple car la température ne dépend que de la commande ''u(t)''.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d'un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Fonction de transfert Filtre continu d'un PID&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|500px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:eqFxTransfertPID.png|200]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21061</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21061"/>
				<updated>2026-05-29T13:10:56Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* PID numérique &amp;quot;classique&amp;quot; */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d'un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
'''EN COURS DE RÉÉCRITURE (C++ vers Python)'''&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique, la sortie du controleur PID ''u(t)'' est donnée par:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
On considère que le temps est discrétisé : ''t = n.dt'' où ''dt'' est l'intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée &amp;lt;br/&amp;gt;[[Fichier:PIDderivative.png|400px]] [[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
** La dérivée est calculée par ''D = (e(n)-e(n-1))/dt''&lt;br /&gt;
** L'intégrale est approximée en cumulant progressivement : ''I = I + e(n).dt''&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
** ''Ki = Kd = 0'' =&amp;gt; chercher le meilleur ''Kp'' =&amp;gt; erreur de régime permanent&lt;br /&gt;
** ''Kd = 0'' =&amp;gt; l'introduction du terme integral permet de corriger cette erreur de régime permanent&lt;br /&gt;
** Le terme dérivatif n'est pas nécessaire dans cet exemple car la température ne dépend que de la commande.&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d'un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Fonction de transfert Filtre continu d'un PID&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|500px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:eqFxTransfertPID.png|200]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21060</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21060"/>
				<updated>2026-05-29T13:06:59Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* PID numérique &amp;quot;classique&amp;quot; */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d'un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
'''EN COURS DE RÉÉCRITURE (C++ vers Python)'''&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique, la sortie du controleur PID ''u(t)'' est donnée par:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
On considère que le temps est discrétisé : ''t = n.dt'' où ''dt'' est l'intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée &amp;lt;br/&amp;gt;[[Fichier:PIDderivative.png|400px]] [[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
** La dérivée est calculée par ''D = (e(n)-e(n-1))/dt''&lt;br /&gt;
** L'intégrale est approximée en cumulant progressivement : ''I = I + e(n).dt''&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d'un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Fonction de transfert Filtre continu d'un PID&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|500px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:eqFxTransfertPID.png|200]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21059</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21059"/>
				<updated>2026-05-29T13:06:25Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* PID numérique &amp;quot;classique&amp;quot; */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d'un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
'''EN COURS DE RÉÉCRITURE (C++ vers Python)'''&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique, la sortie du controleur PID ''u(t)'' est donnée par:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
On considère que le temps est discrétisé : ''t = n.dt'' où ''dt'' est l'intervalle de temps entre deux valeurs.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée&lt;br /&gt;
[[Fichier:PIDderivative.png|400px]] [[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
** La dérivée est calculée par ''D = (e(n)-e(n-1))/dt''&lt;br /&gt;
** L'intégrale est approximée en cumulant progressivement : ''I = I + e(n).dt''&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d'un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Fonction de transfert Filtre continu d'un PID&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|500px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:eqFxTransfertPID.png|200]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21058</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21058"/>
				<updated>2026-05-29T12:50:25Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* Approximation de PID par filtre numérique linéaire */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d'un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
'''EN COURS DE RÉÉCRITURE (C++ vers Python)'''&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique, la sortie du controleur PID ''u(t)'' est donnée par:&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
On considère que le temps est discrétisé : ''t = n.Ts'' où ''Ts'' est la période d'échantillonnage.&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée&lt;br /&gt;
[[Fichier:PIDderivative.png|400px]] [[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
** La dérivée est calculée par ''D = (e(n)-e(n-1))/Ts''&lt;br /&gt;
** L'intégrale est approximée en cumulant progressivement : ''I = I + e(n).Ts''&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d'un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Fonction de transfert Filtre continu d'un PID&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|500px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:eqFxTransfertPID.png|200]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21057</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21057"/>
				<updated>2026-05-29T12:36:12Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* Approximation de PID par filtre numérique linéaire */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d'un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
'''EN COURS DE RÉÉCRITURE (C++ vers Python)'''&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDderivative.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDintegral.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d'un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Fonction de transfert Filtre continu d'un PID&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:eqFxTransfertPID.png|150]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21056</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21056"/>
				<updated>2026-05-29T12:35:24Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* Approximation de PID par filtre numérique linéaire */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d'un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
'''EN COURS DE RÉÉCRITURE (C++ vers Python)'''&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDprincipe.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:PIDdetail.png|400px]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d'un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Fonction de transfert Filtre continu d'un PID&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:eqFxTransfertPID.png|150]]&lt;br /&gt;
&lt;br /&gt;
[[Fichier:eqFxTransfertPIDetPB.png|130]]&lt;br /&gt;
&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Fichier:EqFxTransfertPIDetPB.png&amp;diff=21055</id>
		<title>Fichier:EqFxTransfertPIDetPB.png</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Fichier:EqFxTransfertPIDetPB.png&amp;diff=21055"/>
				<updated>2026-05-29T10:54:06Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Fichier:EqFxTransfertPID.png&amp;diff=21054</id>
		<title>Fichier:EqFxTransfertPID.png</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Fichier:EqFxTransfertPID.png&amp;diff=21054"/>
				<updated>2026-05-29T10:51:22Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Fichier:PIDderivative.png&amp;diff=21053</id>
		<title>Fichier:PIDderivative.png</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Fichier:PIDderivative.png&amp;diff=21053"/>
				<updated>2026-05-29T10:46:05Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Fichier:PIDintegral.png&amp;diff=21052</id>
		<title>Fichier:PIDintegral.png</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Fichier:PIDintegral.png&amp;diff=21052"/>
				<updated>2026-05-29T10:45:53Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Fichier:PIDdetail.png&amp;diff=21051</id>
		<title>Fichier:PIDdetail.png</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Fichier:PIDdetail.png&amp;diff=21051"/>
				<updated>2026-05-29T10:43:30Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Fichier:PIDprincipe.png&amp;diff=21050</id>
		<title>Fichier:PIDprincipe.png</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Fichier:PIDprincipe.png&amp;diff=21050"/>
				<updated>2026-05-29T10:41:12Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21049</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21049"/>
				<updated>2026-05-29T10:40:22Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* Approximation de PID par filtre numérique linéaire */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d'un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
'''EN COURS DE RÉÉCRITURE (C++ vers Python)'''&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
&lt;br /&gt;
[[Fichier:https://wikigeii.iut-troyes.univ-reims.fr/images/d/d5/PIDprincipe.webp]]&lt;br /&gt;
&lt;br /&gt;
* Définition mathématique&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d'un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Fonction de transfert Filtre continu d'un PID&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21047</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21047"/>
				<updated>2026-05-29T10:35:37Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* Approximation de PID par filtre numérique linéaire */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d'un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
'''EN COURS DE RÉÉCRITURE (C++ vers Python)'''&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
* Définition mathématique&lt;br /&gt;
&lt;br /&gt;
[[Fichier:EqPID.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d'un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Fonction de transfert Filtre continu d'un PID&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Fichier:EqPID.png&amp;diff=21046</id>
		<title>Fichier:EqPID.png</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Fichier:EqPID.png&amp;diff=21046"/>
				<updated>2026-05-29T10:33:28Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21045</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21045"/>
				<updated>2026-05-29T10:28:52Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d'un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
'''EN COURS DE RÉÉCRITURE (C++ vers Python)'''&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
* Définitions mathématique&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ====&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d'un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Fonction de transfert Filtre continu d'un PID&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21044</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21044"/>
				<updated>2026-05-29T10:28:21Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* Approximation de PID par filtre numérique linéaire */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d'un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
'''EN COURS DE RÉÉCRITURE (C++ vers Python)'''&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;br /&gt;
&lt;br /&gt;
==== Rappels PID ====&lt;br /&gt;
&lt;br /&gt;
* Principe&lt;br /&gt;
* Définitions mathématique&lt;br /&gt;
&lt;br /&gt;
==== PID numérique &amp;quot;classique&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
* En approximant grossièrement l'intégrale et la dérivée&lt;br /&gt;
* Notebook exemple : asservissement de température&lt;br /&gt;
&lt;br /&gt;
==== PID numérique par approximation d'un filtre continu ====&lt;br /&gt;
&lt;br /&gt;
* Fonction de transfert Filtre continu d'un PID&lt;br /&gt;
* Approximation de la fonction de transfert pour obtenir un filtre numérique&lt;br /&gt;
** ''backward euler''&lt;br /&gt;
** et transformée bilinéaire&lt;br /&gt;
* Implémentation du Filtre : classe &amp;lt;code&amp;gt;FilterController&amp;lt;/code&amp;gt;&lt;br /&gt;
* Application sur l'asservissement d'altitude d'un drone&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21043</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21043"/>
				<updated>2026-05-29T10:19:21Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d'un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
'''EN COURS DE RÉÉCRITURE (C++ vers Python)'''&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
==== Application : démodulation ====&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21042</id>
		<title>Cours:Elen4 TNS TP TpsReel</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TpsReel&amp;diff=21042"/>
				<updated>2026-05-29T10:18:54Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP6 : Temps réel : Codage d'un bloc en Python / démodulation / PID Numérique&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est double :&lt;br /&gt;
* réaliser des implémentations temps réel de filtre IIR en créant un bloc Gnuradio qui execute un traitement codé en Python&lt;br /&gt;
* et étudier l'implémentation d'un PID numérique sous forme d'un filtre IIR.&lt;br /&gt;
&lt;br /&gt;
=== Codage de bloc Gnuradio en Python ===&lt;br /&gt;
&lt;br /&gt;
'''EN COURS DE RÉÉCRITURE (C++ vers Python)'''&lt;br /&gt;
&lt;br /&gt;
Ce guide est inspirée du guide [https://wiki.gnuradio.org/index.php?title=Creating_C%2B%2B_OOT_with_gr-modtool Creating an OOT (C++ block example)] en l'adaptant pour nos besoins :&lt;br /&gt;
&lt;br /&gt;
Nous allons créer un simple bloc qui recopie son entrée (en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;) sur sa sortie. Donc le filtre caractérisé par ''y(n)'' = ''x(n)'' ou encore ''H(z)''=1. Il s'agit donc d'une sorte de filtre passe-tout.&lt;br /&gt;
&lt;br /&gt;
'''Suivez bien toutes les étapes, sans aller trop rapidement'''&lt;br /&gt;
&lt;br /&gt;
* Vous pourrez utiliser &amp;lt;code&amp;gt;gedit&amp;lt;/code&amp;gt; pour éditer les divers fichiers.&lt;br /&gt;
&lt;br /&gt;
==== Création d'un module externe ====&lt;br /&gt;
&lt;br /&gt;
Dans les lignes qui suivent, le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; indique que l'on saisi une commande dans un terminal. Le &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; n'est pas à saisir.&lt;br /&gt;
&lt;br /&gt;
* Ouvrez un terminal et placez-vous à la racine de votre dossier personnel :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd $HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Créez un dossier de travail dédié à gnuradio et déplacez-vous à l'intérieur :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ mkdir gnuradio&lt;br /&gt;
$ cd gnuradio&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* GNU Radio est livré avec gr_modtool, un utilitaire qui permet de créer des modules externes (OOT). Créons un module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool newmod monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Le dossier &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; est créé et contient tout le code squelette d'un module OOT, mais il n'a pas encore de blocs. Déplacez-vous dans &amp;lt;code&amp;gt;gr-monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ cd gr-monModule&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Vous pouvez afficher le contenu de ce dossier par&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ ls&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Création d'un bloc dans ce module ====&lt;br /&gt;
&lt;br /&gt;
* Ajoutez un nouveau bloc nommé &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ gr_modtool add passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Quelques questions permettent alors de spécifier le type de bloc&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
GNU Radio module name identified: passetout&lt;br /&gt;
('sink', 'source', 'sync', 'decimator', 'interpolator', 'general', 'tagged_stream', 'hier', 'noblock')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Saisissez &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt; comme type de bloc, car le bloc que nous écrivons produira le même nombre d'échantillons en sortie que le nombre d'échantillons consommés depuis l'entrée.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter block type: sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez &amp;lt;code&amp;gt;cpp&amp;lt;/code&amp;gt; comme langage :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Language (python/cpp): cpp&lt;br /&gt;
Language: C++&lt;br /&gt;
Block/code identifier: passetout&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Spécifiez un nom pour le copyright :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Please specify the copyright holder: Bibi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Il est possible de spécifier des paramètres d'entrée qui peuvent permettre de régler le fonctionnement du bloc. Ce ne sera pas notre cas, ne rien saisir sur cette question :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Enter valid argument list, including default arguments: &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* De même, on ne donnera pas de code permettant de tester le bon fonctionnement :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Add Python QA code? [Y/n] n&lt;br /&gt;
Add C++ QA code? [Y/n] n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Plusieurs fichers sont alors crées :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Adding file 'lib/passetout_impl.h'...&lt;br /&gt;
Adding file 'lib/passetout_impl.cc'...&lt;br /&gt;
Adding file 'include/gnuradio/monModule/passetout.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/docstrings/passetout_pydoc_template.h'...&lt;br /&gt;
Adding file 'python/monModule/bindings/passetout_python.cc'...&lt;br /&gt;
Adding file 'grc/monModule_passetout.block.yml'...&lt;br /&gt;
Editing grc/CMakeLists.txt...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quelques indications :&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; contient l'entête de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; contient l'implémentation de la classe de notre bloc&lt;br /&gt;
* le fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; va contenir des informations faisant le lien entre notre code c++ et le code python utilisé en interne par Gnuradio&lt;br /&gt;
* Le tout sera compilé par un &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; généré par &amp;lt;code&amp;gt;cmake&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.h&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
class passetout_impl : public passetout&lt;br /&gt;
{&lt;br /&gt;
private:&lt;br /&gt;
    // Nothing to declare in this block.&lt;br /&gt;
&lt;br /&gt;
public:&lt;br /&gt;
    passetout_impl();&lt;br /&gt;
    ~passetout_impl();&lt;br /&gt;
&lt;br /&gt;
    // Where all the action really happens&lt;br /&gt;
    int work(int noutput_items,&lt;br /&gt;
             gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
             gr_vector_void_star&amp;amp; output_items);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour se réveiller les neurones sur la POO, qu'est-ce que sont&lt;br /&gt;
* &amp;lt;code&amp;gt;passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;~passetout_impl()&amp;lt;/code&amp;gt;,&lt;br /&gt;
* &amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; ?&lt;br /&gt;
&lt;br /&gt;
Le travail sera réalisé dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;, mais nous n'avons pas de modification à apporter dans les déclarations par défaut.&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;passetout_impl.cc&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Le code utile généré est le suivant :&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=passetout_impl.cc}}&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
namespace monModule {&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
passetout::sptr passetout::make() { return gnuradio::make_block_sptr&amp;lt;passetout_impl&amp;gt;(); }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * The private constructor&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Our virtual destructor.&lt;br /&gt;
 */&lt;br /&gt;
passetout_impl::~passetout_impl() {}&lt;br /&gt;
&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} /* namespace monModule */&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
Détaillons :&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using input_type = float;&lt;br /&gt;
#pragma message(&amp;quot;set the following appropriately and remove this warning&amp;quot;)&lt;br /&gt;
using output_type = float;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{Todos| On spécifie ici le type des données d'entrée et de sortie. Pas de modification à apporter, il suffit de supprimer les deux &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
passetout_impl::passetout_impl()&lt;br /&gt;
    : gr::sync_block(&amp;quot;passetout&amp;quot;,&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min inputs */, 1 /* max inputs */, sizeof(input_type)),&lt;br /&gt;
                     gr::io_signature::make(&lt;br /&gt;
                         1 /* min outputs */, 1 /*max outputs */, sizeof(output_type)))&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| On spécifie ici le nombre d'entrées (1) et le nombre de sorties (1). Pas de modification non plus.}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Expliquez la syntaxe &amp;lt;code&amp;gt;passetout_impl::passetout_impl() : gr::sync_block(...)&amp;quot;&amp;lt;/code&amp;gt; }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=cpp&amp;gt;&lt;br /&gt;
int passetout_impl::work(int noutput_items,&lt;br /&gt;
                         gr_vector_const_void_star&amp;amp; input_items,&lt;br /&gt;
                         gr_vector_void_star&amp;amp; output_items)&lt;br /&gt;
{&lt;br /&gt;
    auto in = static_cast&amp;lt;const input_type*&amp;gt;(input_items[0]);&lt;br /&gt;
    auto out = static_cast&amp;lt;output_type*&amp;gt;(output_items[0]);&lt;br /&gt;
&lt;br /&gt;
#pragma message(&amp;quot;Implement the signal processing in your block and remove this warning&amp;quot;)&lt;br /&gt;
    // Do &amp;lt;+signal processing+&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    // Tell runtime system how many output items we produced.&lt;br /&gt;
    return noutput_items;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Cette méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; implémente véritablement le filtrage.&lt;br /&gt;
* Les tableaux &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; contiennent respectivement les données en entrée et les données en sortie. Il faut donc calculer &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; en fonction de &amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&lt;br /&gt;
* Les données d'entrée arrivent par paquets dans un buffer. La variable &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt; contient le nombre de données disponibles en entrées.&lt;br /&gt;
* à la fin de la méthode, on renvoie le nombre de données en sortie que l'on a calculé (entre 1 et &amp;lt;code&amp;gt;noutput_items&amp;lt;/code&amp;gt;). Les données d'entrées éventuellement non consommées seront conservées dans le buffer pour le prochain appel de &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt;&lt;br /&gt;
{{Todos| On souhaite ici seulement recopier l'entrée sur la sortie, donc }}&lt;br /&gt;
# Enlever la ligne &amp;lt;code&amp;gt;#pragma&amp;lt;/code&amp;gt;&lt;br /&gt;
# ajouter le code &amp;lt;code&amp;gt; out[0] = in[0];&amp;lt;/code&amp;gt; (on recopie le premier échantillon disponible en entrée)&lt;br /&gt;
# changer &amp;lt;code&amp;gt;return noutput_items;&amp;lt;/code&amp;gt; en &amp;lt;code&amp;gt;return 1;&amp;lt;/code&amp;gt; (un seul échantillon a été consommé).&lt;br /&gt;
&lt;br /&gt;
==== Fichier &amp;lt;code&amp;gt;monModule_passetout.block.yml&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Ce fichier au format YAML (''yet another markup language'') fait le lien entre le code c++ et le code python utilisé en interne par GnuRadio.&lt;br /&gt;
&lt;br /&gt;
{{boîte déroulante/début|titre=monModule_passetout.block.yml}}&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
id: monModule_passetout&lt;br /&gt;
label: passetout&lt;br /&gt;
category: '[monModule]'&lt;br /&gt;
&lt;br /&gt;
templates:&lt;br /&gt;
  imports: from gnuradio import monModule&lt;br /&gt;
  make: monModule.passetout()&lt;br /&gt;
&lt;br /&gt;
#  Make one 'parameters' list entry for every parameter you want settable from the GUI.&lt;br /&gt;
#     Keys include:&lt;br /&gt;
#     * id (makes the value accessible as keyname, e.g. in the make entry)&lt;br /&gt;
#     * label (label shown in the GUI)&lt;br /&gt;
#     * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#     * default&lt;br /&gt;
parameters:&lt;br /&gt;
- id: parametername_replace_me&lt;br /&gt;
  label: FIX ME:&lt;br /&gt;
  dtype: string&lt;br /&gt;
  default: You need to fill in your grc/monModule_passetout.block.yaml&lt;br /&gt;
#- id: ...&lt;br /&gt;
#  label: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
&lt;br /&gt;
#  Make one 'inputs' list entry per input and one 'outputs' list entry per output.&lt;br /&gt;
#  Keys include:&lt;br /&gt;
#      * label (an identifier for the GUI)&lt;br /&gt;
#      * domain (optional - stream or message. Default is stream)&lt;br /&gt;
#      * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)&lt;br /&gt;
#      * vlen (optional - data stream vector length. Default is 1)&lt;br /&gt;
#      * optional (optional - set to 1 for optional inputs. Default is 0)&lt;br /&gt;
inputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
outputs:&lt;br /&gt;
#- label: ...&lt;br /&gt;
#  domain: ...&lt;br /&gt;
#  dtype: ...&lt;br /&gt;
#  vlen: ...&lt;br /&gt;
#  optional: ...&lt;br /&gt;
&lt;br /&gt;
#  'file_format' specifies the version of the GRC yml format used in the file&lt;br /&gt;
#  and should usually not be changed.&lt;br /&gt;
file_format: 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{{boîte déroulante/fin}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; (pas de paramètres, on commente) :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
#parameters:&lt;br /&gt;
#- id: parametername_replace_me&lt;br /&gt;
#  label: FIX ME:&lt;br /&gt;
#  dtype: string&lt;br /&gt;
#  default: You need to fill in your grc/customModule_testMod.block.yaml&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;inputs&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
inputs:&lt;br /&gt;
- label: in&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todos| Mettre à jour la section &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; :}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=yaml&amp;gt;&lt;br /&gt;
outputs:&lt;br /&gt;
- label: out&lt;br /&gt;
  domain: stream&lt;br /&gt;
  dtype: float&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Compilation et installation ====&lt;br /&gt;
&lt;br /&gt;
Voici les étapes :&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
$ cd CHEMIN-DE-VOTRE-DOSSIER/gr-monModule&lt;br /&gt;
$ mkdir build&lt;br /&gt;
$ cd build&lt;br /&gt;
$ cmake ..&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cmake ..&amp;lt;/code&amp;gt; lance la création des fichiers &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; qui permettent la compilation et l'installation&lt;br /&gt;
* &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; lance la compilation&lt;br /&gt;
* &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; lance l'installation (copie des fichiers dans les dossiers gnuradio)&lt;br /&gt;
&lt;br /&gt;
{{Todos| Exécuter chacune de ces lignes, en contrôlant l'absence d'erreur. Dans le cas contraire, contrôler les fichiers &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.cc&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;.yaml&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| '''Après ces étapes, et avant de lancer gnuRadio, appeler l'enseignant qui va mettre à jours les bibliothèques partagées.'''}}. Sinon tenter :&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH&lt;br /&gt;
$ gnuradio-companion &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Utilisation du bloc et test ====&lt;br /&gt;
&lt;br /&gt;
* Dans Gnuradio, rafraichir la liste des bloc (bouton ''reload'')&lt;br /&gt;
* le bloc &amp;lt;code&amp;gt;passetout&amp;lt;/code&amp;gt; doit être présent dans la section &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt;&lt;br /&gt;
* Tester le bon fonctionnement de ce bloc en lui envoyant une sinusoïde que vous devez observer identique à la sortie du bloc. Vérifier avec des graphes.&lt;br /&gt;
&lt;br /&gt;
== Application : démodulation ==&lt;br /&gt;
&lt;br /&gt;
En reprenant le signal modulé en amplitude et la fonction de transfert du filtre passe-bas du TP précédent :&lt;br /&gt;
&lt;br /&gt;
* Obtenir l'équation aux différence du filtre, ''ie'' écrire ''y(n)='' en fonction de ''x(n)'', ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
* Créer un nouveau bloc C++ (similaire au passe-tout précédent) dans le module &amp;lt;code&amp;gt;monModule&amp;lt;/code&amp;gt; :&lt;br /&gt;
** de type &amp;lt;code&amp;gt;sync&amp;lt;/code&amp;gt;&lt;br /&gt;
** une entrée en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
** une sortie en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&lt;br /&gt;
* Écrire le code permettant d'obtenir ''y(n)'' dans la méthode &amp;lt;code&amp;gt;work()&amp;lt;/code&amp;gt; :&lt;br /&gt;
** ''x(n)'' est donné par &amp;lt;code&amp;gt;in0[0]&amp;lt;/code&amp;gt;&lt;br /&gt;
** il sera nécessaire d'affecter &amp;lt;code&amp;gt;out0[0]&amp;lt;/code&amp;gt; pour produire ''y(n)''.&lt;br /&gt;
** il sera nécessaire de stocker dans des '''attributs''' les valeurs de &amp;lt;code&amp;gt;in[0]&amp;lt;/code&amp;gt; afin de disposer de ''x(n-1)'', ''x(n-2)'', ''y(n-1)'' et ''y(n-2)''.&lt;br /&gt;
** On rappelle que les attributs doivent être déclarées dans le fichier &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; et initialisés dans le constructeur de la classe.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Réaliser cette implémentation du passe-bas et contrôler que la démodulation est identique à celle obtenue au TP précédent}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Modifier votre code pour implémenter le filtre complet de démodulation}}&lt;br /&gt;
&lt;br /&gt;
=== Approximation de PID par filtre numérique linéaire ===&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TraitAudioEtDemodulation&amp;diff=21038</id>
		<title>Cours:Elen4 TNS TP TraitAudioEtDemodulation</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TraitAudioEtDemodulation&amp;diff=21038"/>
				<updated>2026-05-26T07:53:51Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* Réverbération */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP5 : Traitements audio et démodulation d'amplitude&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est d'ajouter puis de supprimer des effets audio (écho et réverbération). La source sera un enregistrement parlé numérisé. Les effets et leurs suppressions seront implémentés à l'aide de filtres numériques.&lt;br /&gt;
&lt;br /&gt;
=== Traitements audio ===&lt;br /&gt;
&lt;br /&gt;
Ces traitements seront implémentés dans GnuRadio.&lt;br /&gt;
&lt;br /&gt;
===== Écho =====&lt;br /&gt;
&lt;br /&gt;
Les échos se produisent lorsqu'au signal émis s'ajoutent une ou plusieurs répliques retardées et affaiblies de ce même signal source. Nous considérons une situation simple où seul un écho s'ajoute au signal original ''x(n)''. En raison de l'écho, le signal obtenu est&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
''s(n) = x(n) + a x(n-d)''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
où ''a'' représente le facteur d'atténuation (0 &amp;lt; ''a'' &amp;lt; 1) et ''d'' est le nombre d'échantillons de retard du signal répliqué.&lt;br /&gt;
&lt;br /&gt;
Vous travaillerez avec un retard de τ=0,5s en considérant que ''τ=d T&amp;lt;sub&amp;gt;e&amp;lt;/sub&amp;gt;'', ''T&amp;lt;sub&amp;gt;e&amp;lt;/sub&amp;gt;'' étant la période d'échantillonnage. &lt;br /&gt;
&lt;br /&gt;
{{q| a)}} Si la fréquence d’échantillonnage est fixée à ''F&amp;lt;sub&amp;gt;e&amp;lt;/sub&amp;gt; = 22050''Hz, montrer que la fonction de transfert du filtre d'écho est&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
''H(z) = 1 + a z&amp;lt;sup&amp;gt;-11025&amp;lt;/sup&amp;gt;''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{q| b)}} Télécharger le ﬁchier [[:Fichier:RienNeSertdeCourir.zip|RienNeSertdeCourir.zip]], et l'utiliser comme entrée dans Gnuradio à l'aide d'un bloc &amp;lt;code&amp;gt;Wav File Source&amp;lt;/code&amp;gt;. L'écouter en audio en l'envoyant dans un bloc &amp;lt;code&amp;gt;Audio Sink&amp;lt;/code&amp;gt;, en spécifiant 22050Hz comme fréquence d'échantillonnage.&lt;br /&gt;
&lt;br /&gt;
{{q| c)}} Appliquer le filtre ''H'' à la phrase enregistrée pour créer une sortie ''y(n)''. Écouter cette phrase pour vérifier à l'oreille la présence d’un écho. L’application du filtre sera réalisée de la même façon qu'au [[Cours:Elen4_TNS_TP_Implementations|TP3 - Implémentations de filtres]].&lt;br /&gt;
&lt;br /&gt;
===== Réverbération =====&lt;br /&gt;
&lt;br /&gt;
La réverbération est due au mélange de réflexions directes ou indirectes et résulte en un son confus. Considérons une situation simple où une seule réverbération est présente. Soit ''x(n)'' le signal original, la réverbération est obtenue en additionnant le signal d’entrée avec le signal de sortie retardé :&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
''y(n) = x(n) + b y(n-r)''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
où ''b'' est le facteur d’atténuation (0 &amp;lt; ''b'' &amp;lt; 1) et ''r'' le nombre d’échantillons de retard du signal répliqué. En choisissant un retard de τ (par exemple 0,1s), on a alors ''r = τF&amp;lt;sub&amp;gt;e&amp;lt;/sub&amp;gt;''.&lt;br /&gt;
&lt;br /&gt;
{{q| a)}} La fréquence d’échantillonnage étant toujours ﬁxée à ''F&amp;lt;sub&amp;gt;e&amp;lt;/sub&amp;gt;''=22050Hz et en considérant un facteur d’atténuation ''b'' = 0,8 montrer que la fonction de transfert de la réverbération est&lt;br /&gt;
&lt;br /&gt;
{{FxT | H(z) |&lt;br /&gt;
1&lt;br /&gt;
|&lt;br /&gt;
1 - b z&amp;lt;sup&amp;gt;-r&amp;lt;/sup&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{q| b)}} Dans GnuRadio, l'implémentation de ce filtre n'est pas possible avec des blocs retards, gain et additionneur car GnuRadio n'accepte pas de boucles. Une solution simple est de passer par un bloc &amp;lt;code&amp;gt;IIR Filter&amp;lt;/code&amp;gt;. Dans ce type de bloc, il faut spécifier les coefficients du numérateur et du dénominateur. Pour le dénominateur, vous pourrez créer un bloc &amp;lt;code&amp;gt;variable&amp;lt;/code&amp;gt; avec le code suivant :&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
np.concatenate( (np.array([1]), np.zeros(N), np.array([-b])))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
où &amp;lt;code&amp;gt;N&amp;lt;/code&amp;gt; est à remplacer par le nombre de zéros nécessaires et &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt; par sa valeur.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Ajouter un bloc &amp;lt;code&amp;gt;import&amp;lt;/code&amp;gt; avec le code suivant &amp;lt;code&amp;gt;import numpy as np&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Implémenter ce filtre et l’appliquer à l’enregistrement. Écouter le résultat ''y'' pour vérifier la présence d’une réverbération. &amp;lt;br/&amp;gt;''Attention au paramètre &amp;lt;code&amp;gt;old style of taps&amp;lt;/code&amp;gt; du bloc, consultez sa documentation.''}}&lt;br /&gt;
&lt;br /&gt;
===== Annulation de l'écho et de la réverbération =====&lt;br /&gt;
&lt;br /&gt;
{{q| d)}} On souhaite à présent concevoir un système d’annulation de l’écho. Il s’agit donc de déterminer un filtre numérique de réponse impulsionnelle ''g(n)'' qui doit permettre de supprimer l’écho.&lt;br /&gt;
&lt;br /&gt;
Déterminer la fonction de transfert ''G(z)'' du filtre d’annulation en fonction de ''H(z)''.&lt;br /&gt;
&lt;br /&gt;
{{q| e)}} Appliquer ce filtre au signal ''y'' et écouter le signal qui ne doit plus présenter de phénomène d’écho.&lt;br /&gt;
&lt;br /&gt;
{{q| c)}} De même, concevoir un filtre d’annulation de la réverbération en déterminant sa fonction de transfert.&lt;br /&gt;
&lt;br /&gt;
{{q| d)}} Appliquer ce filtre et écouter le résultat en vérifiant le bon fonctionnement : l'annulation de la réverbération.&lt;br /&gt;
&lt;br /&gt;
{{q| e)}} Comparer les filtres de la section ''Réverbération'' et de la section ''Écho'' et faire une remarque pertinente.&lt;br /&gt;
&lt;br /&gt;
{{q| f)}} Est-il toujours possible de construire un filtre d'annulation, autrement dit, est-il toujours possible de construire un filtre réciproque d'un autre filtre ? (vous pouvez réfléchir en prenant exemple d'un filtre passe-bas par exemple)&lt;br /&gt;
&lt;br /&gt;
=== Démodulation ===&lt;br /&gt;
&lt;br /&gt;
On dispose d'un signal modulé en amplitude par une porteuse de fréquence élevée. Afin de récupérer le signal utile, la démodulation d'amplitude se décompose en deux étapes :&lt;br /&gt;
# Redressement du signal modulé&lt;br /&gt;
# Application d'un filtre passe-bas pour enlever la porteuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
[[Fichier:Tns_figure_demodulation.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Fig : principe d'une démodulation d'amplitude.&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Le signal modulé est disponible dans le fichier [[Fichier:Tns_tp3_signal_mod.hex]] (valeurs codées en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;)&lt;br /&gt;
* Le signal démodulé (pour référence) est disponible dans le fichier [[Fichier:Tns_tp3_signal.hex]] (valeurs codées en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Détermination du Filtre passe-bas =====&lt;br /&gt;
&lt;br /&gt;
Dans un notebook Python/Jupyter :&lt;br /&gt;
&lt;br /&gt;
* En affichant le graphe du contenu fréquentiel du signal modulé :&lt;br /&gt;
** Identifier l'information de signal utile et l'information de porteuse de modulation&lt;br /&gt;
** Choisir une fréquence de coupure, normalisée ''Wn'' pour un filtre passe-bas, permettant de rejeter la porteuse. Les fréquences normalisées sont comprises entre 0 et 1, où 1 représente la fréquence de Nyquist (moitié de la fréquence d'échantillonnage).&lt;br /&gt;
* Déterminer les coefficients de la fonction de transfert de ce passe-bas, à l'aide de la fonction &amp;lt;code&amp;gt;scipy.signal.butter()&amp;lt;/code&amp;gt; (avec un filtre d'ordre &amp;lt;code&amp;gt;N=2&amp;lt;/code&amp;gt; pour ne pas avoir trop de coefficients). Il s'agit d'un filtre à réponse impulsionnelle infinie du type Butterworth, qui contient une rétroaction.&lt;br /&gt;
&lt;br /&gt;
===== Implémentations de la démodulation =====&lt;br /&gt;
&lt;br /&gt;
''N'oubliez pas le redressement dans la modulation !''&lt;br /&gt;
&lt;br /&gt;
Dans Python/Jupyter :&lt;br /&gt;
* Comme un filtre RIF, Puisque le filtre est IIR, la réponse impulsionnelle sera forcément tronquée. Vous pouvez l'obtenir dans Matlab à l'aide de la fonction &amp;lt;code&amp;gt;scipy.signal.dimpulse()&amp;lt;/code&amp;gt;. &lt;br /&gt;
* Par un produit dans le domaine fréquentiel. Vous pourrez obtenir la réponse fréquentielle du filtre à l'aide de la fonction &amp;lt;code&amp;gt;scipy.signal.freqz()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dans Gnuradio :&lt;br /&gt;
* Comme un filtre RIF, avec le bloc &amp;lt;code&amp;gt;Frequency Xlating FIR Filter&amp;lt;/code&amp;gt; (comme dans le tutoriel [https://wiki.gnuradio.org/index.php/Designing_Filter_Taps Designing Filter Taps]). &lt;br /&gt;
* En implémentant le filtre IIR de la même façon que le filtre de réverbération.&lt;br /&gt;
* Vous pourrez également chercher à utiliser un bloc &amp;lt;code&amp;gt;Low Pass Filter&amp;lt;/code&amp;gt;. Dans ce cas, vous aurez trois paramètres à régler dans ce bloc :&lt;br /&gt;
** ''Cutoff Freq'' : une fraction de la fréquence d'échantionnage (&amp;lt;code&amp;gt;samp_rate&amp;lt;/code&amp;gt;), déterminée dans la partie précédente.&lt;br /&gt;
** ''Transition Width'' : également une fraction de la fréquence d'échantillonnage, qui détermine la plage de transition entre la partie passante et la partie bloquante du passe-bas.&lt;br /&gt;
** ''Window'' : choix de la fenêtre de pondération (qui vise à limiter les oscillations du filtre). Vous pourrez tester l'effet de ces diverses fenêtres (cf [https://fr.wikipedia.org/wiki/Fenêtrage Fenêtrage]).&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TraitAudioEtDemodulation&amp;diff=21037</id>
		<title>Cours:Elen4 TNS TP TraitAudioEtDemodulation</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TraitAudioEtDemodulation&amp;diff=21037"/>
				<updated>2026-05-26T07:53:18Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* Réverbération */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP5 : Traitements audio et démodulation d'amplitude&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est d'ajouter puis de supprimer des effets audio (écho et réverbération). La source sera un enregistrement parlé numérisé. Les effets et leurs suppressions seront implémentés à l'aide de filtres numériques.&lt;br /&gt;
&lt;br /&gt;
=== Traitements audio ===&lt;br /&gt;
&lt;br /&gt;
Ces traitements seront implémentés dans GnuRadio.&lt;br /&gt;
&lt;br /&gt;
===== Écho =====&lt;br /&gt;
&lt;br /&gt;
Les échos se produisent lorsqu'au signal émis s'ajoutent une ou plusieurs répliques retardées et affaiblies de ce même signal source. Nous considérons une situation simple où seul un écho s'ajoute au signal original ''x(n)''. En raison de l'écho, le signal obtenu est&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
''s(n) = x(n) + a x(n-d)''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
où ''a'' représente le facteur d'atténuation (0 &amp;lt; ''a'' &amp;lt; 1) et ''d'' est le nombre d'échantillons de retard du signal répliqué.&lt;br /&gt;
&lt;br /&gt;
Vous travaillerez avec un retard de τ=0,5s en considérant que ''τ=d T&amp;lt;sub&amp;gt;e&amp;lt;/sub&amp;gt;'', ''T&amp;lt;sub&amp;gt;e&amp;lt;/sub&amp;gt;'' étant la période d'échantillonnage. &lt;br /&gt;
&lt;br /&gt;
{{q| a)}} Si la fréquence d’échantillonnage est fixée à ''F&amp;lt;sub&amp;gt;e&amp;lt;/sub&amp;gt; = 22050''Hz, montrer que la fonction de transfert du filtre d'écho est&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
''H(z) = 1 + a z&amp;lt;sup&amp;gt;-11025&amp;lt;/sup&amp;gt;''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{q| b)}} Télécharger le ﬁchier [[:Fichier:RienNeSertdeCourir.zip|RienNeSertdeCourir.zip]], et l'utiliser comme entrée dans Gnuradio à l'aide d'un bloc &amp;lt;code&amp;gt;Wav File Source&amp;lt;/code&amp;gt;. L'écouter en audio en l'envoyant dans un bloc &amp;lt;code&amp;gt;Audio Sink&amp;lt;/code&amp;gt;, en spécifiant 22050Hz comme fréquence d'échantillonnage.&lt;br /&gt;
&lt;br /&gt;
{{q| c)}} Appliquer le filtre ''H'' à la phrase enregistrée pour créer une sortie ''y(n)''. Écouter cette phrase pour vérifier à l'oreille la présence d’un écho. L’application du filtre sera réalisée de la même façon qu'au [[Cours:Elen4_TNS_TP_Implementations|TP3 - Implémentations de filtres]].&lt;br /&gt;
&lt;br /&gt;
===== Réverbération =====&lt;br /&gt;
&lt;br /&gt;
La réverbération est due au mélange de réflexions directes ou indirectes et résulte en un son confus. Considérons une situation simple où une seule réverbération est présente. Soit ''x(n)'' le signal original, la réverbération est obtenue en additionnant le signal d’entrée avec le signal de sortie retardé :&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
''y(n) = x(n) + b y(n-r)''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
où ''b'' est le facteur d’atténuation (0 &amp;lt; ''b'' &amp;lt; 1) et ''r'' le nombre d’échantillons de retard du signal répliqué. En choisissant un retard de τ (par exemple 0,1s), on a alors ''r = τF&amp;lt;sub&amp;gt;e&amp;lt;/sub&amp;gt;''.&lt;br /&gt;
&lt;br /&gt;
{{q| a)}} La fréquence d’échantillonnage étant toujours ﬁxée à ''F&amp;lt;sub&amp;gt;e&amp;lt;/sub&amp;gt;''=22050Hz et en considérant un facteur d’atténuation ''b'' = 0,8 montrer que la fonction de transfert de la réverbération est&lt;br /&gt;
&lt;br /&gt;
{{FxT | H(z) |&lt;br /&gt;
1&lt;br /&gt;
|&lt;br /&gt;
1 - b z&amp;lt;sup&amp;gt;-r&amp;lt;/sup&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{q| b)}} Dans GnuRadio, l'implémentation de ce filtre n'est pas possible avec des blocs retards, gain et additionneur car GnuRadio n'accepte pas de boucles. Une solution simple est de passer par un bloc &amp;lt;code&amp;gt;IIR Filter&amp;lt;/code&amp;gt;. Dans ce type de bloc, il faut spécifier les coefficients du numérateur et du dénominateur. Pour le dénominateur, vous pourrez créer un bloc &amp;lt;code&amp;gt;variable&amp;lt;/code&amp;gt; avec le code suivant :&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
np.concatenate( (np.array([1]), np.zeros(N), np.array([-b])))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
où &amp;lt;code&amp;gt;N&amp;lt;/code&amp;gt; est à remplacer par le nombre de zéros nécessaires et &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt; par sa valeur.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Ajouter un bloc &amp;lt;code&amp;gt;import&amp;lt;/code&amp;gt; avec le code suivant &amp;lt;code&amp;gt;import numpy as np&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Implémenter ce filtre et l’appliquer à l’enregistrement. Écouter le résultat ''y'' pour vérifier la présence d’une réverbération. ''Attention au paramètre &amp;lt;code&amp;gt;old style of taps&amp;lt;/code&amp;gt; du bloc, consultez sa documentation.''}}&lt;br /&gt;
&lt;br /&gt;
===== Annulation de l'écho et de la réverbération =====&lt;br /&gt;
&lt;br /&gt;
{{q| d)}} On souhaite à présent concevoir un système d’annulation de l’écho. Il s’agit donc de déterminer un filtre numérique de réponse impulsionnelle ''g(n)'' qui doit permettre de supprimer l’écho.&lt;br /&gt;
&lt;br /&gt;
Déterminer la fonction de transfert ''G(z)'' du filtre d’annulation en fonction de ''H(z)''.&lt;br /&gt;
&lt;br /&gt;
{{q| e)}} Appliquer ce filtre au signal ''y'' et écouter le signal qui ne doit plus présenter de phénomène d’écho.&lt;br /&gt;
&lt;br /&gt;
{{q| c)}} De même, concevoir un filtre d’annulation de la réverbération en déterminant sa fonction de transfert.&lt;br /&gt;
&lt;br /&gt;
{{q| d)}} Appliquer ce filtre et écouter le résultat en vérifiant le bon fonctionnement : l'annulation de la réverbération.&lt;br /&gt;
&lt;br /&gt;
{{q| e)}} Comparer les filtres de la section ''Réverbération'' et de la section ''Écho'' et faire une remarque pertinente.&lt;br /&gt;
&lt;br /&gt;
{{q| f)}} Est-il toujours possible de construire un filtre d'annulation, autrement dit, est-il toujours possible de construire un filtre réciproque d'un autre filtre ? (vous pouvez réfléchir en prenant exemple d'un filtre passe-bas par exemple)&lt;br /&gt;
&lt;br /&gt;
=== Démodulation ===&lt;br /&gt;
&lt;br /&gt;
On dispose d'un signal modulé en amplitude par une porteuse de fréquence élevée. Afin de récupérer le signal utile, la démodulation d'amplitude se décompose en deux étapes :&lt;br /&gt;
# Redressement du signal modulé&lt;br /&gt;
# Application d'un filtre passe-bas pour enlever la porteuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
[[Fichier:Tns_figure_demodulation.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Fig : principe d'une démodulation d'amplitude.&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Le signal modulé est disponible dans le fichier [[Fichier:Tns_tp3_signal_mod.hex]] (valeurs codées en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;)&lt;br /&gt;
* Le signal démodulé (pour référence) est disponible dans le fichier [[Fichier:Tns_tp3_signal.hex]] (valeurs codées en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Détermination du Filtre passe-bas =====&lt;br /&gt;
&lt;br /&gt;
Dans un notebook Python/Jupyter :&lt;br /&gt;
&lt;br /&gt;
* En affichant le graphe du contenu fréquentiel du signal modulé :&lt;br /&gt;
** Identifier l'information de signal utile et l'information de porteuse de modulation&lt;br /&gt;
** Choisir une fréquence de coupure, normalisée ''Wn'' pour un filtre passe-bas, permettant de rejeter la porteuse. Les fréquences normalisées sont comprises entre 0 et 1, où 1 représente la fréquence de Nyquist (moitié de la fréquence d'échantillonnage).&lt;br /&gt;
* Déterminer les coefficients de la fonction de transfert de ce passe-bas, à l'aide de la fonction &amp;lt;code&amp;gt;scipy.signal.butter()&amp;lt;/code&amp;gt; (avec un filtre d'ordre &amp;lt;code&amp;gt;N=2&amp;lt;/code&amp;gt; pour ne pas avoir trop de coefficients). Il s'agit d'un filtre à réponse impulsionnelle infinie du type Butterworth, qui contient une rétroaction.&lt;br /&gt;
&lt;br /&gt;
===== Implémentations de la démodulation =====&lt;br /&gt;
&lt;br /&gt;
''N'oubliez pas le redressement dans la modulation !''&lt;br /&gt;
&lt;br /&gt;
Dans Python/Jupyter :&lt;br /&gt;
* Comme un filtre RIF, Puisque le filtre est IIR, la réponse impulsionnelle sera forcément tronquée. Vous pouvez l'obtenir dans Matlab à l'aide de la fonction &amp;lt;code&amp;gt;scipy.signal.dimpulse()&amp;lt;/code&amp;gt;. &lt;br /&gt;
* Par un produit dans le domaine fréquentiel. Vous pourrez obtenir la réponse fréquentielle du filtre à l'aide de la fonction &amp;lt;code&amp;gt;scipy.signal.freqz()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dans Gnuradio :&lt;br /&gt;
* Comme un filtre RIF, avec le bloc &amp;lt;code&amp;gt;Frequency Xlating FIR Filter&amp;lt;/code&amp;gt; (comme dans le tutoriel [https://wiki.gnuradio.org/index.php/Designing_Filter_Taps Designing Filter Taps]). &lt;br /&gt;
* En implémentant le filtre IIR de la même façon que le filtre de réverbération.&lt;br /&gt;
* Vous pourrez également chercher à utiliser un bloc &amp;lt;code&amp;gt;Low Pass Filter&amp;lt;/code&amp;gt;. Dans ce cas, vous aurez trois paramètres à régler dans ce bloc :&lt;br /&gt;
** ''Cutoff Freq'' : une fraction de la fréquence d'échantionnage (&amp;lt;code&amp;gt;samp_rate&amp;lt;/code&amp;gt;), déterminée dans la partie précédente.&lt;br /&gt;
** ''Transition Width'' : également une fraction de la fréquence d'échantillonnage, qui détermine la plage de transition entre la partie passante et la partie bloquante du passe-bas.&lt;br /&gt;
** ''Window'' : choix de la fenêtre de pondération (qui vise à limiter les oscillations du filtre). Vous pourrez tester l'effet de ces diverses fenêtres (cf [https://fr.wikipedia.org/wiki/Fenêtrage Fenêtrage]).&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TraitAudioEtDemodulation&amp;diff=21036</id>
		<title>Cours:Elen4 TNS TP TraitAudioEtDemodulation</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TraitAudioEtDemodulation&amp;diff=21036"/>
				<updated>2026-05-26T07:53:03Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* Réverbération */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP5 : Traitements audio et démodulation d'amplitude&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est d'ajouter puis de supprimer des effets audio (écho et réverbération). La source sera un enregistrement parlé numérisé. Les effets et leurs suppressions seront implémentés à l'aide de filtres numériques.&lt;br /&gt;
&lt;br /&gt;
=== Traitements audio ===&lt;br /&gt;
&lt;br /&gt;
Ces traitements seront implémentés dans GnuRadio.&lt;br /&gt;
&lt;br /&gt;
===== Écho =====&lt;br /&gt;
&lt;br /&gt;
Les échos se produisent lorsqu'au signal émis s'ajoutent une ou plusieurs répliques retardées et affaiblies de ce même signal source. Nous considérons une situation simple où seul un écho s'ajoute au signal original ''x(n)''. En raison de l'écho, le signal obtenu est&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
''s(n) = x(n) + a x(n-d)''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
où ''a'' représente le facteur d'atténuation (0 &amp;lt; ''a'' &amp;lt; 1) et ''d'' est le nombre d'échantillons de retard du signal répliqué.&lt;br /&gt;
&lt;br /&gt;
Vous travaillerez avec un retard de τ=0,5s en considérant que ''τ=d T&amp;lt;sub&amp;gt;e&amp;lt;/sub&amp;gt;'', ''T&amp;lt;sub&amp;gt;e&amp;lt;/sub&amp;gt;'' étant la période d'échantillonnage. &lt;br /&gt;
&lt;br /&gt;
{{q| a)}} Si la fréquence d’échantillonnage est fixée à ''F&amp;lt;sub&amp;gt;e&amp;lt;/sub&amp;gt; = 22050''Hz, montrer que la fonction de transfert du filtre d'écho est&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
''H(z) = 1 + a z&amp;lt;sup&amp;gt;-11025&amp;lt;/sup&amp;gt;''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{q| b)}} Télécharger le ﬁchier [[:Fichier:RienNeSertdeCourir.zip|RienNeSertdeCourir.zip]], et l'utiliser comme entrée dans Gnuradio à l'aide d'un bloc &amp;lt;code&amp;gt;Wav File Source&amp;lt;/code&amp;gt;. L'écouter en audio en l'envoyant dans un bloc &amp;lt;code&amp;gt;Audio Sink&amp;lt;/code&amp;gt;, en spécifiant 22050Hz comme fréquence d'échantillonnage.&lt;br /&gt;
&lt;br /&gt;
{{q| c)}} Appliquer le filtre ''H'' à la phrase enregistrée pour créer une sortie ''y(n)''. Écouter cette phrase pour vérifier à l'oreille la présence d’un écho. L’application du filtre sera réalisée de la même façon qu'au [[Cours:Elen4_TNS_TP_Implementations|TP3 - Implémentations de filtres]].&lt;br /&gt;
&lt;br /&gt;
===== Réverbération =====&lt;br /&gt;
&lt;br /&gt;
La réverbération est due au mélange de réflexions directes ou indirectes et résulte en un son confus. Considérons une situation simple où une seule réverbération est présente. Soit ''x(n)'' le signal original, la réverbération est obtenue en additionnant le signal d’entrée avec le signal de sortie retardé :&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
''y(n) = x(n) + b y(n-r)''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
où ''b'' est le facteur d’atténuation (0 &amp;lt; ''b'' &amp;lt; 1) et ''r'' le nombre d’échantillons de retard du signal répliqué. En choisissant un retard de τ (par exemple 0,1s), on a alors ''r = τF&amp;lt;sub&amp;gt;e&amp;lt;/sub&amp;gt;''.&lt;br /&gt;
&lt;br /&gt;
{{q| a)}} La fréquence d’échantillonnage étant toujours ﬁxée à ''F&amp;lt;sub&amp;gt;e&amp;lt;/sub&amp;gt;''=22050Hz et en considérant un facteur d’atténuation ''b'' = 0,8 montrer que la fonction de transfert de la réverbération est&lt;br /&gt;
&lt;br /&gt;
{{FxT | H(z) |&lt;br /&gt;
1&lt;br /&gt;
|&lt;br /&gt;
1 - b z&amp;lt;sup&amp;gt;-r&amp;lt;/sup&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{q| b)}} Dans GnuRadio, l'implémentation de ce filtre n'est pas possible avec des blocs retards, gain et additionneur car GnuRadio n'accepte pas de boucles. Une solution simple est de passer par un bloc &amp;lt;code&amp;gt;IIR Filter&amp;lt;/code&amp;gt;. Dans ce type de bloc, il faut spécifier les coefficients du numérateur et du dénominateur. Pour le dénominateur, vous pourrez créer un bloc &amp;lt;code&amp;gt;variable&amp;lt;/code&amp;gt; avec le code suivant :&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
np.concatenate( (np.array([1]), np.zeros(N), np.array([-b])))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
où &amp;lt;code&amp;gt;N&amp;lt;/code&amp;gt; est à remplacer par le nombre de zéros nécessaires et &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt; par sa valeur.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Ajouter un bloc &amp;lt;code&amp;gt;import&amp;lt;/code&amp;gt; avec le code suivant &amp;lt;code&amp;gt;import numpy as np&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Implémenter ce filtre et l’appliquer à l’enregistrement. Écouter le résultat ''y'' pour vérifier la présence d’une réverbération. '''Attention au paramètre &amp;lt;code&amp;gt;old style of taps&amp;lt;/code&amp;gt; du bloc, consultez sa documentation.'''}}&lt;br /&gt;
&lt;br /&gt;
===== Annulation de l'écho et de la réverbération =====&lt;br /&gt;
&lt;br /&gt;
{{q| d)}} On souhaite à présent concevoir un système d’annulation de l’écho. Il s’agit donc de déterminer un filtre numérique de réponse impulsionnelle ''g(n)'' qui doit permettre de supprimer l’écho.&lt;br /&gt;
&lt;br /&gt;
Déterminer la fonction de transfert ''G(z)'' du filtre d’annulation en fonction de ''H(z)''.&lt;br /&gt;
&lt;br /&gt;
{{q| e)}} Appliquer ce filtre au signal ''y'' et écouter le signal qui ne doit plus présenter de phénomène d’écho.&lt;br /&gt;
&lt;br /&gt;
{{q| c)}} De même, concevoir un filtre d’annulation de la réverbération en déterminant sa fonction de transfert.&lt;br /&gt;
&lt;br /&gt;
{{q| d)}} Appliquer ce filtre et écouter le résultat en vérifiant le bon fonctionnement : l'annulation de la réverbération.&lt;br /&gt;
&lt;br /&gt;
{{q| e)}} Comparer les filtres de la section ''Réverbération'' et de la section ''Écho'' et faire une remarque pertinente.&lt;br /&gt;
&lt;br /&gt;
{{q| f)}} Est-il toujours possible de construire un filtre d'annulation, autrement dit, est-il toujours possible de construire un filtre réciproque d'un autre filtre ? (vous pouvez réfléchir en prenant exemple d'un filtre passe-bas par exemple)&lt;br /&gt;
&lt;br /&gt;
=== Démodulation ===&lt;br /&gt;
&lt;br /&gt;
On dispose d'un signal modulé en amplitude par une porteuse de fréquence élevée. Afin de récupérer le signal utile, la démodulation d'amplitude se décompose en deux étapes :&lt;br /&gt;
# Redressement du signal modulé&lt;br /&gt;
# Application d'un filtre passe-bas pour enlever la porteuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
[[Fichier:Tns_figure_demodulation.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Fig : principe d'une démodulation d'amplitude.&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Le signal modulé est disponible dans le fichier [[Fichier:Tns_tp3_signal_mod.hex]] (valeurs codées en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;)&lt;br /&gt;
* Le signal démodulé (pour référence) est disponible dans le fichier [[Fichier:Tns_tp3_signal.hex]] (valeurs codées en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Détermination du Filtre passe-bas =====&lt;br /&gt;
&lt;br /&gt;
Dans un notebook Python/Jupyter :&lt;br /&gt;
&lt;br /&gt;
* En affichant le graphe du contenu fréquentiel du signal modulé :&lt;br /&gt;
** Identifier l'information de signal utile et l'information de porteuse de modulation&lt;br /&gt;
** Choisir une fréquence de coupure, normalisée ''Wn'' pour un filtre passe-bas, permettant de rejeter la porteuse. Les fréquences normalisées sont comprises entre 0 et 1, où 1 représente la fréquence de Nyquist (moitié de la fréquence d'échantillonnage).&lt;br /&gt;
* Déterminer les coefficients de la fonction de transfert de ce passe-bas, à l'aide de la fonction &amp;lt;code&amp;gt;scipy.signal.butter()&amp;lt;/code&amp;gt; (avec un filtre d'ordre &amp;lt;code&amp;gt;N=2&amp;lt;/code&amp;gt; pour ne pas avoir trop de coefficients). Il s'agit d'un filtre à réponse impulsionnelle infinie du type Butterworth, qui contient une rétroaction.&lt;br /&gt;
&lt;br /&gt;
===== Implémentations de la démodulation =====&lt;br /&gt;
&lt;br /&gt;
''N'oubliez pas le redressement dans la modulation !''&lt;br /&gt;
&lt;br /&gt;
Dans Python/Jupyter :&lt;br /&gt;
* Comme un filtre RIF, Puisque le filtre est IIR, la réponse impulsionnelle sera forcément tronquée. Vous pouvez l'obtenir dans Matlab à l'aide de la fonction &amp;lt;code&amp;gt;scipy.signal.dimpulse()&amp;lt;/code&amp;gt;. &lt;br /&gt;
* Par un produit dans le domaine fréquentiel. Vous pourrez obtenir la réponse fréquentielle du filtre à l'aide de la fonction &amp;lt;code&amp;gt;scipy.signal.freqz()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dans Gnuradio :&lt;br /&gt;
* Comme un filtre RIF, avec le bloc &amp;lt;code&amp;gt;Frequency Xlating FIR Filter&amp;lt;/code&amp;gt; (comme dans le tutoriel [https://wiki.gnuradio.org/index.php/Designing_Filter_Taps Designing Filter Taps]). &lt;br /&gt;
* En implémentant le filtre IIR de la même façon que le filtre de réverbération.&lt;br /&gt;
* Vous pourrez également chercher à utiliser un bloc &amp;lt;code&amp;gt;Low Pass Filter&amp;lt;/code&amp;gt;. Dans ce cas, vous aurez trois paramètres à régler dans ce bloc :&lt;br /&gt;
** ''Cutoff Freq'' : une fraction de la fréquence d'échantionnage (&amp;lt;code&amp;gt;samp_rate&amp;lt;/code&amp;gt;), déterminée dans la partie précédente.&lt;br /&gt;
** ''Transition Width'' : également une fraction de la fréquence d'échantillonnage, qui détermine la plage de transition entre la partie passante et la partie bloquante du passe-bas.&lt;br /&gt;
** ''Window'' : choix de la fenêtre de pondération (qui vise à limiter les oscillations du filtre). Vous pourrez tester l'effet de ces diverses fenêtres (cf [https://fr.wikipedia.org/wiki/Fenêtrage Fenêtrage]).&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	<entry>
		<id>http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TraitAudioEtDemodulation&amp;diff=21035</id>
		<title>Cours:Elen4 TNS TP TraitAudioEtDemodulation</title>
		<link rel="alternate" type="text/html" href="http://wikigeii.iut-troyes.univ-reims.fr//index.php?title=Cours:Elen4_TNS_TP_TraitAudioEtDemodulation&amp;diff=21035"/>
				<updated>2026-05-25T05:00:57Z</updated>
		
		<summary type="html">&lt;p&gt;Fredmn : /* Détermination du Filtre passe-bas */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Cours:Elen4_TNS|{{Rouge|'''Retour à la page du cours'''}}]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
'''&amp;lt;big&amp;gt;TP5 : Traitements audio et démodulation d'amplitude&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but de ce TP est d'ajouter puis de supprimer des effets audio (écho et réverbération). La source sera un enregistrement parlé numérisé. Les effets et leurs suppressions seront implémentés à l'aide de filtres numériques.&lt;br /&gt;
&lt;br /&gt;
=== Traitements audio ===&lt;br /&gt;
&lt;br /&gt;
Ces traitements seront implémentés dans GnuRadio.&lt;br /&gt;
&lt;br /&gt;
===== Écho =====&lt;br /&gt;
&lt;br /&gt;
Les échos se produisent lorsqu'au signal émis s'ajoutent une ou plusieurs répliques retardées et affaiblies de ce même signal source. Nous considérons une situation simple où seul un écho s'ajoute au signal original ''x(n)''. En raison de l'écho, le signal obtenu est&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
''s(n) = x(n) + a x(n-d)''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
où ''a'' représente le facteur d'atténuation (0 &amp;lt; ''a'' &amp;lt; 1) et ''d'' est le nombre d'échantillons de retard du signal répliqué.&lt;br /&gt;
&lt;br /&gt;
Vous travaillerez avec un retard de τ=0,5s en considérant que ''τ=d T&amp;lt;sub&amp;gt;e&amp;lt;/sub&amp;gt;'', ''T&amp;lt;sub&amp;gt;e&amp;lt;/sub&amp;gt;'' étant la période d'échantillonnage. &lt;br /&gt;
&lt;br /&gt;
{{q| a)}} Si la fréquence d’échantillonnage est fixée à ''F&amp;lt;sub&amp;gt;e&amp;lt;/sub&amp;gt; = 22050''Hz, montrer que la fonction de transfert du filtre d'écho est&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
''H(z) = 1 + a z&amp;lt;sup&amp;gt;-11025&amp;lt;/sup&amp;gt;''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{q| b)}} Télécharger le ﬁchier [[:Fichier:RienNeSertdeCourir.zip|RienNeSertdeCourir.zip]], et l'utiliser comme entrée dans Gnuradio à l'aide d'un bloc &amp;lt;code&amp;gt;Wav File Source&amp;lt;/code&amp;gt;. L'écouter en audio en l'envoyant dans un bloc &amp;lt;code&amp;gt;Audio Sink&amp;lt;/code&amp;gt;, en spécifiant 22050Hz comme fréquence d'échantillonnage.&lt;br /&gt;
&lt;br /&gt;
{{q| c)}} Appliquer le filtre ''H'' à la phrase enregistrée pour créer une sortie ''y(n)''. Écouter cette phrase pour vérifier à l'oreille la présence d’un écho. L’application du filtre sera réalisée de la même façon qu'au [[Cours:Elen4_TNS_TP_Implementations|TP3 - Implémentations de filtres]].&lt;br /&gt;
&lt;br /&gt;
===== Réverbération =====&lt;br /&gt;
&lt;br /&gt;
La réverbération est due au mélange de réflexions directes ou indirectes et résulte en un son confus. Considérons une situation simple où une seule réverbération est présente. Soit ''x(n)'' le signal original, la réverbération est obtenue en additionnant le signal d’entrée avec le signal de sortie retardé :&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
''y(n) = x(n) + b y(n-r)''&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
où ''b'' est le facteur d’atténuation (0 &amp;lt; ''b'' &amp;lt; 1) et ''r'' le nombre d’échantillons de retard du signal répliqué. En choisissant un retard de τ (par exemple 0,1s), on a alors ''r = τF&amp;lt;sub&amp;gt;e&amp;lt;/sub&amp;gt;''.&lt;br /&gt;
&lt;br /&gt;
{{q| a)}} La fréquence d’échantillonnage étant toujours ﬁxée à ''F&amp;lt;sub&amp;gt;e&amp;lt;/sub&amp;gt;''=22050Hz et en considérant un facteur d’atténuation ''b'' = 0,8 montrer que la fonction de transfert de la réverbération est&lt;br /&gt;
&lt;br /&gt;
{{FxT | H(z) |&lt;br /&gt;
1&lt;br /&gt;
|&lt;br /&gt;
1 - b z&amp;lt;sup&amp;gt;-r&amp;lt;/sup&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{q| b)}} Dans GnuRadio, l'implémentation de ce filtre n'est pas possible avec des blocs retards, gain et additionneur car GnuRadio n'accepte pas de boucles. Une solution simple est de passer par un bloc &amp;lt;code&amp;gt;IIR Filter&amp;lt;/code&amp;gt;. Dans ce type de bloc, il faut spécifier les coefficients du numérateur et du dénominateur. Pour le dénominateur, vous pourrez créer un bloc &amp;lt;code&amp;gt;variable&amp;lt;/code&amp;gt; avec le code suivant :&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
np.concatenate( (np.array([1]), np.zeros(N), np.array([-b])))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
où &amp;lt;code&amp;gt;N&amp;lt;/code&amp;gt; est à remplacer par le nombre de zéros nécessaires et &amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt; par sa valeur.&lt;br /&gt;
&lt;br /&gt;
{{Todos| Ajouter un bloc &amp;lt;code&amp;gt;import&amp;lt;/code&amp;gt; avec le code suivant &amp;lt;code&amp;gt;import numpy as np&amp;lt;/code&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{Todos| Implémenter ce filtre et l’appliquer à l’enregistrement. Écouter le résultat ''y'' pour vérifier la présence d’une réverbération.}}&lt;br /&gt;
&lt;br /&gt;
===== Annulation de l'écho et de la réverbération =====&lt;br /&gt;
&lt;br /&gt;
{{q| d)}} On souhaite à présent concevoir un système d’annulation de l’écho. Il s’agit donc de déterminer un filtre numérique de réponse impulsionnelle ''g(n)'' qui doit permettre de supprimer l’écho.&lt;br /&gt;
&lt;br /&gt;
Déterminer la fonction de transfert ''G(z)'' du filtre d’annulation en fonction de ''H(z)''.&lt;br /&gt;
&lt;br /&gt;
{{q| e)}} Appliquer ce filtre au signal ''y'' et écouter le signal qui ne doit plus présenter de phénomène d’écho.&lt;br /&gt;
&lt;br /&gt;
{{q| c)}} De même, concevoir un filtre d’annulation de la réverbération en déterminant sa fonction de transfert.&lt;br /&gt;
&lt;br /&gt;
{{q| d)}} Appliquer ce filtre et écouter le résultat en vérifiant le bon fonctionnement : l'annulation de la réverbération.&lt;br /&gt;
&lt;br /&gt;
{{q| e)}} Comparer les filtres de la section ''Réverbération'' et de la section ''Écho'' et faire une remarque pertinente.&lt;br /&gt;
&lt;br /&gt;
{{q| f)}} Est-il toujours possible de construire un filtre d'annulation, autrement dit, est-il toujours possible de construire un filtre réciproque d'un autre filtre ? (vous pouvez réfléchir en prenant exemple d'un filtre passe-bas par exemple)&lt;br /&gt;
&lt;br /&gt;
=== Démodulation ===&lt;br /&gt;
&lt;br /&gt;
On dispose d'un signal modulé en amplitude par une porteuse de fréquence élevée. Afin de récupérer le signal utile, la démodulation d'amplitude se décompose en deux étapes :&lt;br /&gt;
# Redressement du signal modulé&lt;br /&gt;
# Application d'un filtre passe-bas pour enlever la porteuse.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
[[Fichier:Tns_figure_demodulation.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Fig : principe d'une démodulation d'amplitude.&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Le signal modulé est disponible dans le fichier [[Fichier:Tns_tp3_signal_mod.hex]] (valeurs codées en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;)&lt;br /&gt;
* Le signal démodulé (pour référence) est disponible dans le fichier [[Fichier:Tns_tp3_signal.hex]] (valeurs codées en &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Détermination du Filtre passe-bas =====&lt;br /&gt;
&lt;br /&gt;
Dans un notebook Python/Jupyter :&lt;br /&gt;
&lt;br /&gt;
* En affichant le graphe du contenu fréquentiel du signal modulé :&lt;br /&gt;
** Identifier l'information de signal utile et l'information de porteuse de modulation&lt;br /&gt;
** Choisir une fréquence de coupure, normalisée ''Wn'' pour un filtre passe-bas, permettant de rejeter la porteuse. Les fréquences normalisées sont comprises entre 0 et 1, où 1 représente la fréquence de Nyquist (moitié de la fréquence d'échantillonnage).&lt;br /&gt;
* Déterminer les coefficients de la fonction de transfert de ce passe-bas, à l'aide de la fonction &amp;lt;code&amp;gt;scipy.signal.butter()&amp;lt;/code&amp;gt; (avec un filtre d'ordre &amp;lt;code&amp;gt;N=2&amp;lt;/code&amp;gt; pour ne pas avoir trop de coefficients). Il s'agit d'un filtre à réponse impulsionnelle infinie du type Butterworth, qui contient une rétroaction.&lt;br /&gt;
&lt;br /&gt;
===== Implémentations de la démodulation =====&lt;br /&gt;
&lt;br /&gt;
''N'oubliez pas le redressement dans la modulation !''&lt;br /&gt;
&lt;br /&gt;
Dans Python/Jupyter :&lt;br /&gt;
* Comme un filtre RIF, Puisque le filtre est IIR, la réponse impulsionnelle sera forcément tronquée. Vous pouvez l'obtenir dans Matlab à l'aide de la fonction &amp;lt;code&amp;gt;scipy.signal.dimpulse()&amp;lt;/code&amp;gt;. &lt;br /&gt;
* Par un produit dans le domaine fréquentiel. Vous pourrez obtenir la réponse fréquentielle du filtre à l'aide de la fonction &amp;lt;code&amp;gt;scipy.signal.freqz()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dans Gnuradio :&lt;br /&gt;
* Comme un filtre RIF, avec le bloc &amp;lt;code&amp;gt;Frequency Xlating FIR Filter&amp;lt;/code&amp;gt; (comme dans le tutoriel [https://wiki.gnuradio.org/index.php/Designing_Filter_Taps Designing Filter Taps]). &lt;br /&gt;
* En implémentant le filtre IIR de la même façon que le filtre de réverbération.&lt;br /&gt;
* Vous pourrez également chercher à utiliser un bloc &amp;lt;code&amp;gt;Low Pass Filter&amp;lt;/code&amp;gt;. Dans ce cas, vous aurez trois paramètres à régler dans ce bloc :&lt;br /&gt;
** ''Cutoff Freq'' : une fraction de la fréquence d'échantionnage (&amp;lt;code&amp;gt;samp_rate&amp;lt;/code&amp;gt;), déterminée dans la partie précédente.&lt;br /&gt;
** ''Transition Width'' : également une fraction de la fréquence d'échantillonnage, qui détermine la plage de transition entre la partie passante et la partie bloquante du passe-bas.&lt;br /&gt;
** ''Window'' : choix de la fenêtre de pondération (qui vise à limiter les oscillations du filtre). Vous pourrez tester l'effet de ces diverses fenêtres (cf [https://fr.wikipedia.org/wiki/Fenêtrage Fenêtrage]).&lt;/div&gt;</summary>
		<author><name>Fredmn</name></author>	</entry>

	</feed>